aboutsummaryrefslogtreecommitdiffstats
path: root/tools/node_modules/expresso/deps
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/expresso/deps')
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po166
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po105
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po196
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po190
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po178
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po161
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po176
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po183
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po176
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po249
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po182
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po252
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po126
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po116
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po117
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/.deps/util.Po177
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/COPYING339
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Makefile884
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Makefile.am81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Makefile.in884
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/Readme.md8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/aclocal.m4872
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.guess1526
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/config.h93
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/config.h.in92
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/config.log899
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.rpath666
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.status1080
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/config.sub1658
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/configure7971
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/configure.ac88
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/depcomp589
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/demo.html87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/doc.css45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js20
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme10
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js534
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js705
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js102
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html189
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html23
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html67
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html16
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js306
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css83
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gifbin0 -> 811 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gifbin0 -> 2465 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gifbin0 -> 968 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gifbin0 -> 811 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html213
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt470
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt340
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html141
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt504
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html167
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example/index.html24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/example/script.js20
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/faq.html164
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.pngbin0 -> 689 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/help.html45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/index.html151
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gifbin0 -> 425 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css328
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html125
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js1024
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gifbin0 -> 425 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css328
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html125
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js1024
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/license.html382
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/links.html59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/manual.html701
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/news.html214
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot.pngbin0 -> 19071 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.pngbin0 -> 20888 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.pngbin0 -> 22690 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.pngbin0 -> 20440 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.pngbin0 -> 20738 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.pngbin0 -> 28866 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.pngbin0 -> 18924 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.pngbin0 -> 338 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/style.css138
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/doc/users.html58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/encoding.c315
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/encoding.h33
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/generate-resourcesbin0 -> 13201 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/generate-resources.c58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/global.h29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/highlight.c478
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/highlight.h37
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-connection.c192
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-exchange.c494
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-host.c95
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-message.c900
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-server.c236
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-server.h208
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/http-url.c156
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/install-sh519
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp1873
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument-js.h81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument.c226
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/instrument.h31
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref483
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/README.html54
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/aclocal.m49
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/bench.sh5
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl202
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4154
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess1481
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub1595
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh119
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile315
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh101
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m482
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m459
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper75
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/hcc111
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/hcpp155
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl165
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl63
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py40
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl98
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config.mk206
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in106
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm232
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in349
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py108
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/config.mk884
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl66
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk53
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl112
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in84
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c233
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h184
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c549
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h83
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h733
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c337
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c860
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man382
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c686
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c124
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c481
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py139
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c247
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h74
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl671
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl48
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk2269
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/system-headers1038
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/version.mk85
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl423
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/dtoa.c3321
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref143
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/README83
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3175
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c1368
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h135
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c182
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h82
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d73
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl52
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js-config.in111
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js.cpp4050
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js.mdpbin0 -> 17922 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js.msg309
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/js3240.rc79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def654
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp6060
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsapi.h2699
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp450
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarena.h318
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp3426
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsarray.h191
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp1064
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsatom.h458
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbit.h253
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp182
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbool.h75
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp497
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h374
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsclist.h139
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp1394
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h1247
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscompat.h57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk181
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp388
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h212
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp2475
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdate.h124
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp1954
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h500
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp876
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h588
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp572
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h131
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c318
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp6857
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsemit.h777
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp1376
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsexn.h96
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp2736
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfile.h56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg90
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp2706
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsfun.h296
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp3763
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsgc.h427
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp476
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jshash.h151
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsify.pl483
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp7225
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h591
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp42
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp1050
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsiter.h140
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl124
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp460
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h69
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp1417
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslock.h311
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm60
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp94
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp264
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jslong.h412
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp721
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsmath.h63
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp1338
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsnum.h287
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp5563
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsobj.h735
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/json.cpp954
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/json.h107
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp5304
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h404
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl557
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp121
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h202
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp6822
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsparse.h508
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp1262
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsprf.h150
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl129
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h263
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h727
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp4772
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h192
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl145
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp2017
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscan.h389
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp1955
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscope.h419
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp1891
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsscript.h330
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp5347
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsstr.h662
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp8276
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jstracer.h552
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jstypes.h490
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp345
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsutil.h168
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsversion.h243
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp800
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h220
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp8343
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/jsxml.h298
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s119
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.abin0 -> 26986 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jsbin0 -> 812800 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp0
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/js.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h401
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h237
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d7
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfgbin0 -> 12823 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d6
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jskwgenbin0 -> 13542 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/json.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d8
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengenbin0 -> 17157 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.abin0 -> 1175224 bytes
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/obj/libjs.sobin0 -> 903258 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp846
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h103
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk64
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk85
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk41
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk81
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk72
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk80
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk105
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk82
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk72
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk69
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk101
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk91
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk92
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk87
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk118
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk64
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/resource.h15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/rules.mk206
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/js/time.sh13
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/js/win32.order384
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css89
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js211
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/jscoverage-serverbin0 -> 1126648 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt17
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-server.179
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c1307
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gifbin0 -> 425 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.152
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.c142
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.css328
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.html125
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.js1024
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm22
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/jscoverage.xul36
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4180
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4110
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4709
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4185
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-dist.sh43
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in43
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/missing367
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/node-jscoveragebin0 -> 1012871 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/report.js76
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/resource-manager.c59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/resource-manager.h46
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/resources.c3596
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/stamp-h11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/stream.c129
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/stream.h57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/Makefile846
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am130
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in846
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c42
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh19
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/charset.sh110
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/chunked.sh74
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/common.sh7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/encodings.c223
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/encodings.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/fatal.sh110
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c53
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh25
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/help.sh35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c98
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c77
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c97
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c97
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c144
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c196
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c60
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js106
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh28
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js44
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js15
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh43
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js32
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js96
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js28
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js30
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js9
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js51
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js16
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js45
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js32
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js31
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js71
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js148
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js22
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js57
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js108
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js24
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js30
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js36
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js66
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js27
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js15
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js30
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/javascript.sh53
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js42
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js10
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js0
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js22
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js8
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js38
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js18
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js30
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js79
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js4
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js5
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js21
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js32
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js9
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js65
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/json.c48
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/json.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c42
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl35
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh58
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh53
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh54
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh53
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh49
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh67
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/proxy.sh143
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh59
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c93
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh19
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh41
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh40
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh41
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.pngbin0 -> 67 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/recursive.sh55
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.pngbin0 -> 67 bytes
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html12
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/recursive/x1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh30
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh104
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh47
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh68
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected4
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh57
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh50
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh57
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-error.sh61
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-help.sh26
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out4
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh68
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh49
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err1
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh42
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh62
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh61
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh62
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err4
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh54
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server-version.sh25
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/server.pl61
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/server.sh216
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err2
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh50
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh48
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh56
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js11
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json3
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh52
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh59
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err1
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json6
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json3
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh50
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err3
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json14
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh66
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh58
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json14
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/store.json5
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/store.sh137
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/streams.c107
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/streams.sh19
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err2
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh7
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out13
-rwxr-xr-xtools/node_modules/expresso/deps/jscoverage/tests/version.sh29
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/util.c570
-rw-r--r--tools/node_modules/expresso/deps/jscoverage/util.h133
711 files changed, 213636 insertions, 0 deletions
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po
new file mode 100644
index 0000000..788e721
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/encoding.Po
@@ -0,0 +1,166 @@
+encoding.o: encoding.c config.h encoding.h /usr/include/stdint.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/wchar.h /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h js/jsapi.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/obj/js-config.h \
+ js/jspubtd.h js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h \
+ js/jslong.h js/jsproto.tbl js/jsversion.h js/jsutil.h \
+ /usr/include/assert.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/string.h \
+ /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h \
+ /usr/include/iconv.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+encoding.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jsapi.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+/usr/include/assert.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h:
+
+/usr/include/limits.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/bits/posix2_lim.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/iconv.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po
new file mode 100644
index 0000000..06cd018
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/generate-resources.Po
@@ -0,0 +1,105 @@
+generate-resources.o: generate-resources.c /usr/include/ctype.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/xlocale.h /usr/include/stdio.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/sys/types.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+/usr/include/ctype.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/stdio.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po
new file mode 100644
index 0000000..d54c451
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/highlight.Po
@@ -0,0 +1,196 @@
+highlight.o: highlight.c config.h highlight.h js/jscntxt.h js/jsarena.h \
+ /usr/include/stdlib.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h js/jstypes.h \
+ js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h js/jslong.h js/jsclist.h \
+ js/jsatom.h js/jsversion.h js/jshash.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/jsdhash.h \
+ js/jsapi.h js/obj/js-config.h js/jspubtd.h js/jsproto.tbl js/jsutil.h \
+ js/jsprvtd.h js/jslock.h js/jsgc.h js/jsbit.h js/jsinterp.h js/jsfun.h \
+ js/jsobj.h js/jsopcode.h js/jsopcode.tbl js/jsscript.h js/jsregexp.h \
+ js/jsstr.h /usr/include/ctype.h /usr/include/xlocale.h js/js.msg \
+ stream.h /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/assert.h /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h js/jslock.h \
+ js/jsscan.h js/jskeyword.tbl util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+highlight.h:
+
+js/jscntxt.h:
+
+js/jsarena.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsclist.h:
+
+js/jsatom.h:
+
+js/jsversion.h:
+
+js/jshash.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/jsdhash.h:
+
+js/jsapi.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jsproto.tbl:
+
+js/jsutil.h:
+
+js/jsprvtd.h:
+
+js/jslock.h:
+
+js/jsgc.h:
+
+js/jsbit.h:
+
+js/jsinterp.h:
+
+js/jsfun.h:
+
+js/jsobj.h:
+
+js/jsopcode.h:
+
+js/jsopcode.tbl:
+
+js/jsscript.h:
+
+js/jsregexp.h:
+
+js/jsstr.h:
+
+/usr/include/ctype.h:
+
+/usr/include/xlocale.h:
+
+js/js.msg:
+
+stream.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+js/jslock.h:
+
+js/jsscan.h:
+
+js/jskeyword.tbl:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po
new file mode 100644
index 0000000..2676d36
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-connection.Po
@@ -0,0 +1,190 @@
+http-connection.o: http-connection.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/assert.h /usr/include/string.h /usr/include/xlocale.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h /usr/include/errno.h /usr/include/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po
new file mode 100644
index 0000000..c10e985
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-exchange.Po
@@ -0,0 +1,178 @@
+http-exchange.o: http-exchange.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/assert.h /usr/include/ctype.h /usr/include/xlocale.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h util.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/assert.h:
+
+/usr/include/ctype.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po
new file mode 100644
index 0000000..7ff79f1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-host.Po
@@ -0,0 +1,161 @@
+http-host.o: http-host.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h util.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po
new file mode 100644
index 0000000..15fa835
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-message.Po
@@ -0,0 +1,176 @@
+http-message.o: http-message.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/assert.h /usr/include/string.h /usr/include/xlocale.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po
new file mode 100644
index 0000000..ef3908e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-server.Po
@@ -0,0 +1,183 @@
+http-server.o: http-server.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/string.h /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h \
+ /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/setjmp.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/pthread.h:
+
+/usr/include/sched.h:
+
+/usr/include/bits/sched.h:
+
+/usr/include/bits/setjmp.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po
new file mode 100644
index 0000000..438b6ba
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/http-url.Po
@@ -0,0 +1,176 @@
+http-url.o: http-url.c config.h http-server.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h \
+ /usr/include/stdlib.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/sys/types.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/ctype.h /usr/include/xlocale.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h
+
+config.h:
+
+http-server.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/ctype.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po
new file mode 100644
index 0000000..ab7680e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument-js.Po
@@ -0,0 +1,249 @@
+instrument-js.o: instrument-js.cpp config.h instrument-js.h \
+ /usr/include/stdint.h /usr/include/features.h \
+ /usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-64.h /usr/include/bits/wchar.h stream.h \
+ /usr/include/stdio.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/xlocale.h /usr/include/sys/types.h /usr/include/time.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h /usr/include/assert.h \
+ /usr/include/math.h /usr/include/bits/huge_val.h \
+ /usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
+ /usr/include/bits/inf.h /usr/include/bits/nan.h \
+ /usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
+ /usr/include/bits/mathinline.h /usr/include/string.h \
+ /usr/include/bits/string3.h js/jsapi.h js/obj/js-config.h js/jspubtd.h \
+ js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h js/jslong.h \
+ js/jsproto.tbl js/jsversion.h js/jsutil.h js/jsarena.h js/jsatom.h \
+ js/jshash.h js/jsdhash.h js/jsapi.h js/jsprvtd.h js/jslock.h js/jsemit.h \
+ js/jsstddef.h js/jsatom.h js/jsopcode.h js/jsopcode.tbl js/jsscript.h \
+ js/jsexn.h js/jsfun.h js/jsobj.h js/jsinterp.h js/jsfun.h js/jsiter.h \
+ js/jsparse.h js/jsscan.h js/jskeyword.tbl js/jsregexp.h js/jsstr.h \
+ /usr/include/ctype.h js/jsscope.h js/jsstr.h encoding.h global.h \
+ highlight.h js/jscntxt.h js/jsarena.h js/jsclist.h js/jsgc.h js/jsbit.h \
+ js/jsinterp.h js/jsregexp.h js/js.msg resource-manager.h
+
+config.h:
+
+instrument-js.h:
+
+/usr/include/stdint.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/bits/wchar.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/assert.h:
+
+/usr/include/math.h:
+
+/usr/include/bits/huge_val.h:
+
+/usr/include/bits/huge_valf.h:
+
+/usr/include/bits/huge_vall.h:
+
+/usr/include/bits/inf.h:
+
+/usr/include/bits/nan.h:
+
+/usr/include/bits/mathdef.h:
+
+/usr/include/bits/mathcalls.h:
+
+/usr/include/bits/mathinline.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string3.h:
+
+js/jsapi.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+js/jsarena.h:
+
+js/jsatom.h:
+
+js/jshash.h:
+
+js/jsdhash.h:
+
+js/jsapi.h:
+
+js/jsprvtd.h:
+
+js/jslock.h:
+
+js/jsemit.h:
+
+js/jsstddef.h:
+
+js/jsatom.h:
+
+js/jsopcode.h:
+
+js/jsopcode.tbl:
+
+js/jsscript.h:
+
+js/jsexn.h:
+
+js/jsfun.h:
+
+js/jsobj.h:
+
+js/jsinterp.h:
+
+js/jsfun.h:
+
+js/jsiter.h:
+
+js/jsparse.h:
+
+js/jsscan.h:
+
+js/jskeyword.tbl:
+
+js/jsregexp.h:
+
+js/jsstr.h:
+
+/usr/include/ctype.h:
+
+js/jsscope.h:
+
+js/jsstr.h:
+
+encoding.h:
+
+global.h:
+
+highlight.h:
+
+js/jscntxt.h:
+
+js/jsarena.h:
+
+js/jsclist.h:
+
+js/jsgc.h:
+
+js/jsbit.h:
+
+js/jsinterp.h:
+
+js/jsregexp.h:
+
+js/js.msg:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po
new file mode 100644
index 0000000..1971764
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/instrument.Po
@@ -0,0 +1,182 @@
+instrument.o: instrument.c config.h instrument.h /usr/include/assert.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/errno.h /usr/include/bits/errno.h \
+ /usr/include/linux/errno.h /usr/include/asm/errno.h \
+ /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \
+ /usr/include/string.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/stdlib.h /usr/include/bits/string3.h /usr/include/dirent.h \
+ /usr/include/bits/dirent.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/sys/stat.h /usr/include/time.h /usr/include/bits/stat.h \
+ /usr/include/sys/types.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h encoding.h /usr/include/stdint.h \
+ /usr/include/bits/wchar.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h js/jsapi.h /usr/include/stdio.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/obj/js-config.h \
+ js/jspubtd.h js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h \
+ js/jslong.h js/jsproto.tbl js/jsversion.h js/jsutil.h global.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h instrument-js.h \
+ stream.h util.h resource-manager.h
+
+config.h:
+
+instrument.h:
+
+/usr/include/assert.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
+
+/usr/include/string.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/dirent.h:
+
+/usr/include/bits/dirent.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/time.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+encoding.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jsapi.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+global.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+instrument-js.h:
+
+stream.h:
+
+util.h:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po
new file mode 100644
index 0000000..044b1fd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage-server.Po
@@ -0,0 +1,252 @@
+jscoverage-server.o: jscoverage-server.c config.h /usr/include/assert.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/include/ctype.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/xlocale.h /usr/include/signal.h /usr/include/bits/sigset.h \
+ /usr/include/bits/signum.h /usr/include/time.h \
+ /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
+ /usr/include/bits/sigcontext.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/sigstack.h /usr/include/sys/ucontext.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/bits/sigthread.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/stdlib.h /usr/include/bits/string3.h /usr/include/dirent.h \
+ /usr/include/bits/dirent.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/pthread.h /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/time.h /usr/include/bits/setjmp.h encoding.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/sys/types.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/sys/sysmacros.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h js/jsapi.h \
+ /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \
+ /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h js/obj/js-config.h \
+ js/jspubtd.h js/jstypes.h js/obj/jsautocfg.h js/jsotypes.h js/jscompat.h \
+ js/jslong.h js/jsproto.tbl js/jsversion.h js/jsutil.h global.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h http-server.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/asm/socket.h /usr/include/asm-generic/socket.h \
+ /usr/include/asm/sockios.h /usr/include/asm-generic/sockios.h \
+ /usr/include/bits/socket2.h /usr/include/bits/in.h /usr/include/netdb.h \
+ /usr/include/rpc/netdb.h /usr/include/bits/netdb.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h stream.h instrument-js.h util.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h resource-manager.h
+
+config.h:
+
+/usr/include/assert.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/include/ctype.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/signal.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/signum.h:
+
+/usr/include/time.h:
+
+/usr/include/bits/siginfo.h:
+
+/usr/include/bits/sigaction.h:
+
+/usr/include/bits/sigcontext.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/sigstack.h:
+
+/usr/include/sys/ucontext.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/bits/sigthread.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/dirent.h:
+
+/usr/include/bits/dirent.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/pthread.h:
+
+/usr/include/sched.h:
+
+/usr/include/bits/sched.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/bits/setjmp.h:
+
+encoding.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+js/jsapi.h:
+
+/usr/include/stdio.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+js/obj/js-config.h:
+
+js/jspubtd.h:
+
+js/jstypes.h:
+
+js/obj/jsautocfg.h:
+
+js/jsotypes.h:
+
+js/jscompat.h:
+
+js/jslong.h:
+
+js/jsproto.tbl:
+
+js/jsversion.h:
+
+js/jsutil.h:
+
+global.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+http-server.h:
+
+/usr/include/arpa/inet.h:
+
+/usr/include/netinet/in.h:
+
+/usr/include/sys/socket.h:
+
+/usr/include/sys/uio.h:
+
+/usr/include/bits/uio.h:
+
+/usr/include/bits/socket.h:
+
+/usr/include/bits/sockaddr.h:
+
+/usr/include/asm/socket.h:
+
+/usr/include/asm-generic/socket.h:
+
+/usr/include/asm/sockios.h:
+
+/usr/include/asm-generic/sockios.h:
+
+/usr/include/bits/socket2.h:
+
+/usr/include/bits/in.h:
+
+/usr/include/netdb.h:
+
+/usr/include/rpc/netdb.h:
+
+/usr/include/bits/netdb.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
+
+stream.h:
+
+instrument-js.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po
new file mode 100644
index 0000000..6799cc5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/jscoverage.Po
@@ -0,0 +1,126 @@
+jscoverage.o: jscoverage.c config.h /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h /usr/include/string.h /usr/include/xlocale.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h global.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h instrument.h \
+ instrument-js.h /usr/include/stdint.h /usr/include/bits/wchar.h stream.h \
+ util.h /usr/include/sys/stat.h /usr/include/bits/stat.h \
+ resource-manager.h
+
+config.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+global.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+instrument.h:
+
+instrument-js.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+stream.h:
+
+util.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+resource-manager.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po
new file mode 100644
index 0000000..2f5fc3c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/resource-manager.Po
@@ -0,0 +1,116 @@
+resource-manager.o: resource-manager.c config.h resource-manager.h \
+ /usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h /usr/include/assert.h /usr/include/string.h \
+ /usr/include/xlocale.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/bits/string3.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h resources.c
+
+config.h:
+
+resource-manager.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/assert.h:
+
+/usr/include/string.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+resources.c:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po
new file mode 100644
index 0000000..6e13a4c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/stream.Po
@@ -0,0 +1,117 @@
+stream.o: stream.c config.h stream.h /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/stdlib.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/bits/byteswap.h /usr/include/xlocale.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
+ /usr/include/bits/stdlib.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h
+
+config.h:
+
+stream.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/.deps/util.Po b/tools/node_modules/expresso/deps/jscoverage/.deps/util.Po
new file mode 100644
index 0000000..3233dfb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/.deps/util.Po
@@ -0,0 +1,177 @@
+util.o: util.c config.h util.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h \
+ /usr/include/stdio.h /usr/include/features.h /usr/include/bits/predefs.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/bits/stdio2.h \
+ /usr/include/stdlib.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/byteswap.h \
+ /usr/include/xlocale.h /usr/include/sys/types.h /usr/include/time.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/alloca.h /usr/include/bits/stdlib.h /usr/include/sys/stat.h \
+ /usr/include/bits/stat.h /usr/include/assert.h /usr/include/errno.h \
+ /usr/include/bits/errno.h /usr/include/linux/errno.h \
+ /usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
+ /usr/include/asm-generic/errno-base.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h \
+ /usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h \
+ /usr/include/limits.h /usr/include/bits/posix1_lim.h \
+ /usr/include/bits/local_lim.h /usr/include/linux/limits.h \
+ /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/bits/string3.h /usr/include/strings.h /usr/include/dirent.h \
+ /usr/include/bits/dirent.h /usr/include/libgen.h /usr/include/unistd.h \
+ /usr/include/bits/posix_opt.h /usr/include/bits/environments.h \
+ /usr/include/bits/confname.h /usr/include/getopt.h \
+ /usr/include/bits/unistd.h
+
+config.h:
+
+util.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdbool.h:
+
+/usr/include/stdio.h:
+
+/usr/include/features.h:
+
+/usr/include/bits/predefs.h:
+
+/usr/include/sys/cdefs.h:
+
+/usr/include/bits/wordsize.h:
+
+/usr/include/gnu/stubs.h:
+
+/usr/include/gnu/stubs-64.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stddef.h:
+
+/usr/include/bits/types.h:
+
+/usr/include/bits/typesizes.h:
+
+/usr/include/libio.h:
+
+/usr/include/_G_config.h:
+
+/usr/include/wchar.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include/stdarg.h:
+
+/usr/include/bits/stdio_lim.h:
+
+/usr/include/bits/sys_errlist.h:
+
+/usr/include/bits/stdio.h:
+
+/usr/include/bits/stdio2.h:
+
+/usr/include/stdlib.h:
+
+/usr/include/bits/waitflags.h:
+
+/usr/include/bits/waitstatus.h:
+
+/usr/include/endian.h:
+
+/usr/include/bits/endian.h:
+
+/usr/include/bits/byteswap.h:
+
+/usr/include/xlocale.h:
+
+/usr/include/sys/types.h:
+
+/usr/include/time.h:
+
+/usr/include/sys/select.h:
+
+/usr/include/bits/select.h:
+
+/usr/include/bits/sigset.h:
+
+/usr/include/bits/time.h:
+
+/usr/include/sys/sysmacros.h:
+
+/usr/include/bits/pthreadtypes.h:
+
+/usr/include/alloca.h:
+
+/usr/include/bits/stdlib.h:
+
+/usr/include/sys/stat.h:
+
+/usr/include/bits/stat.h:
+
+/usr/include/assert.h:
+
+/usr/include/errno.h:
+
+/usr/include/bits/errno.h:
+
+/usr/include/linux/errno.h:
+
+/usr/include/asm/errno.h:
+
+/usr/include/asm-generic/errno.h:
+
+/usr/include/asm-generic/errno-base.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/limits.h:
+
+/usr/lib/gcc/x86_64-linux-gnu/4.4.5/include-fixed/syslimits.h:
+
+/usr/include/limits.h:
+
+/usr/include/bits/posix1_lim.h:
+
+/usr/include/bits/local_lim.h:
+
+/usr/include/linux/limits.h:
+
+/usr/include/bits/posix2_lim.h:
+
+/usr/include/bits/xopen_lim.h:
+
+/usr/include/stdint.h:
+
+/usr/include/bits/wchar.h:
+
+/usr/include/string.h:
+
+/usr/include/bits/string.h:
+
+/usr/include/bits/string2.h:
+
+/usr/include/bits/string3.h:
+
+/usr/include/strings.h:
+
+/usr/include/dirent.h:
+
+/usr/include/bits/dirent.h:
+
+/usr/include/libgen.h:
+
+/usr/include/unistd.h:
+
+/usr/include/bits/posix_opt.h:
+
+/usr/include/bits/environments.h:
+
+/usr/include/bits/confname.h:
+
+/usr/include/getopt.h:
+
+/usr/include/bits/unistd.h:
diff --git a/tools/node_modules/expresso/deps/jscoverage/COPYING b/tools/node_modules/expresso/deps/jscoverage/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/tools/node_modules/expresso/deps/jscoverage/Makefile b/tools/node_modules/expresso/deps/jscoverage/Makefile
new file mode 100644
index 0000000..df3509d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Makefile
@@ -0,0 +1,884 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+# Makefile.am - builds jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+pkgdatadir = $(datadir)/jscoverage
+pkglibdir = $(libdir)/jscoverage
+pkgincludedir = $(includedir)/jscoverage
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+bin_PROGRAMS = jscoverage$(EXEEXT) jscoverage-server$(EXEEXT)
+noinst_PROGRAMS = generate-resources$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/make-bin-dist.sh.in \
+ $(srcdir)/make-dist.sh.in $(top_srcdir)/configure COPYING \
+ config.guess config.rpath config.sub depcomp install-sh \
+ missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = make-dist.sh make-bin-dist.sh
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_generate_resources_OBJECTS = generate-resources.$(OBJEXT)
+generate_resources_OBJECTS = $(am_generate_resources_OBJECTS)
+generate_resources_LDADD = $(LDADD)
+am__objects_1 =
+am_jscoverage_OBJECTS = encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument.$(OBJEXT) instrument-js.$(OBJEXT) \
+ jscoverage.$(OBJEXT) resource-manager.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT) $(am__objects_1)
+jscoverage_OBJECTS = $(am_jscoverage_OBJECTS)
+jscoverage_DEPENDENCIES = js/obj/libjs.a
+am_jscoverage_server_OBJECTS = http-connection.$(OBJEXT) \
+ http-exchange.$(OBJEXT) http-host.$(OBJEXT) \
+ http-message.$(OBJEXT) http-server.$(OBJEXT) \
+ http-url.$(OBJEXT) encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument-js.$(OBJEXT) jscoverage-server.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT) \
+ $(am__objects_1)
+jscoverage_server_OBJECTS = $(am_jscoverage_server_OBJECTS)
+jscoverage_server_DEPENDENCIES = js/obj/libjs.a
+DEFAULT_INCLUDES = -I.
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+DIST_SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10
+AMTAR = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar
+AUTOCONF = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf
+AUTOHEADER = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader
+AUTOMAKE = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10
+AWK = gawk
+CC = gcc -std=gnu99
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -std=gnu99 -E
+CPPFLAGS =
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+EXTRA_SOCKET_LIBS =
+EXTRA_THREAD_LIBS = -lpthread
+EXTRA_TIMER_LIBS =
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS =
+LIBICONV =
+LIBOBJS =
+LIBS =
+LTLIBICONV =
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = jscoverage
+PACKAGE_BUGREPORT =
+PACKAGE_NAME = jscoverage
+PACKAGE_STRING = jscoverage 0.4
+PACKAGE_TARNAME = jscoverage
+PACKAGE_VERSION = 0.4
+PATH_SEPARATOR = :
+SET_MAKE =
+SHELL = /bin/sh
+STRIP =
+VERSION = 0.4
+XP_DEF = -DXP_UNIX
+abs_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_top_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_top_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias =
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias =
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = $(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias =
+top_builddir = .
+top_srcdir = .
+ACLOCAL_AMFLAGS = -I m4
+SUBDIRS = js
+AM_CFLAGS = -Ijs -Ijs/obj -DXP_UNIX
+AM_CXXFLAGS = -Ijs -Ijs/obj -DXP_UNIX
+resources = jscoverage-help.txt jscoverage-server-help.txt \
+ jscoverage.jsm jscoverage.manifest jscoverage.xul jscoverage-overlay.js \
+ jscoverage.html \
+ jscoverage.css jscoverage-ie.css jscoverage-highlight.css \
+ jscoverage.js report.js \
+ jscoverage-throbber.gif
+
+jscoverage_SOURCES = encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument.c instrument.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_LDADD = js/obj/libjs.a -lm
+jscoverage_server_SOURCES = http-connection.c \
+ http-exchange.c \
+ http-host.c \
+ http-message.c \
+ http-server.c http-server.h \
+ http-url.c \
+ encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage-server.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_server_LDADD = js/obj/libjs.a -lm -lpthread
+generate_resources_SOURCES = generate-resources.c
+BUILT_SOURCES = resources.c
+dist_man_MANS = jscoverage.1 jscoverage-server.1
+CLEANFILES = *.gcno *.exe resources.c *~
+all: $(BUILT_SOURCES) config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+make-dist.sh: $(top_builddir)/config.status $(srcdir)/make-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+make-bin-dist.sh: $(top_builddir)/config.status $(srcdir)/make-bin-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+generate-resources$(EXEEXT): $(generate_resources_OBJECTS) $(generate_resources_DEPENDENCIES)
+ @rm -f generate-resources$(EXEEXT)
+ $(LINK) $(generate_resources_OBJECTS) $(generate_resources_LDADD) $(LIBS)
+jscoverage$(EXEEXT): $(jscoverage_OBJECTS) $(jscoverage_DEPENDENCIES)
+ @rm -f jscoverage$(EXEEXT)
+ $(CXXLINK) $(jscoverage_OBJECTS) $(jscoverage_LDADD) $(LIBS)
+jscoverage-server$(EXEEXT): $(jscoverage_server_OBJECTS) $(jscoverage_server_DEPENDENCIES)
+ @rm -f jscoverage-server$(EXEEXT)
+ $(CXXLINK) $(jscoverage_server_OBJECTS) $(jscoverage_server_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/encoding.Po
+include ./$(DEPDIR)/generate-resources.Po
+include ./$(DEPDIR)/highlight.Po
+include ./$(DEPDIR)/http-connection.Po
+include ./$(DEPDIR)/http-exchange.Po
+include ./$(DEPDIR)/http-host.Po
+include ./$(DEPDIR)/http-message.Po
+include ./$(DEPDIR)/http-server.Po
+include ./$(DEPDIR)/http-url.Po
+include ./$(DEPDIR)/instrument-js.Po
+include ./$(DEPDIR)/instrument.Po
+include ./$(DEPDIR)/jscoverage-server.Po
+include ./$(DEPDIR)/jscoverage.Po
+include ./$(DEPDIR)/resource-manager.Po
+include ./$(DEPDIR)/stream.Po
+include ./$(DEPDIR)/util.Po
+
+.c.o:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d $(distdir) || mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(PROGRAMS) $(MANS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-binPROGRAMS \
+ clean-generic clean-noinstPROGRAMS ctags ctags-recursive dist \
+ dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
+ dist-zip distcheck distclean distclean-compile \
+ distclean-generic distclean-hdr distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man1 install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-man uninstall-man1
+
+
+resources.c: generate-resources $(resources)
+ $(srcdir)/generate-resources $(resources) > $@
+
+example: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example doc/instrumented
+
+example-inverted: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example-inverted doc/instrumented-inverted
+
+example-jsunit: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+
+# override default install target so as not to recursively install subpackages
+install: install-am
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/Makefile.am b/tools/node_modules/expresso/deps/jscoverage/Makefile.am
new file mode 100644
index 0000000..2b36e6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Makefile.am
@@ -0,0 +1,81 @@
+# Makefile.am - builds jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = js
+
+AM_CFLAGS = -Ijs -Ijs/obj @XP_DEF@
+AM_CXXFLAGS = -Ijs -Ijs/obj @XP_DEF@
+
+resources = jscoverage-help.txt jscoverage-server-help.txt \
+ jscoverage.jsm jscoverage.manifest jscoverage.xul jscoverage-overlay.js \
+ jscoverage.html \
+ jscoverage.css jscoverage-ie.css jscoverage-highlight.css \
+ jscoverage.js report.js \
+ jscoverage-throbber.gif
+
+bin_PROGRAMS = jscoverage jscoverage-server
+jscoverage_SOURCES = encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument.c instrument.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+jscoverage_LDADD = js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+jscoverage_server_SOURCES = http-connection.c \
+ http-exchange.c \
+ http-host.c \
+ http-message.c \
+ http-server.c http-server.h \
+ http-url.c \
+ encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage-server.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+jscoverage_server_LDADD = js/obj/libjs.a -lm @EXTRA_SOCKET_LIBS@ @EXTRA_THREAD_LIBS@ @LIBICONV@ @EXTRA_TIMER_LIBS@
+
+noinst_PROGRAMS = generate-resources
+generate_resources_SOURCES = generate-resources.c
+
+BUILT_SOURCES = resources.c
+
+resources.c: generate-resources $(resources)
+ $(srcdir)/generate-resources $(resources) > $@
+
+dist_man_MANS = jscoverage.1 jscoverage-server.1
+
+CLEANFILES = *.gcno *.exe resources.c *~
+
+example: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example doc/instrumented
+
+example-inverted: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example-inverted doc/instrumented-inverted
+
+example-jsunit: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+
+# override default install target so as not to recursively install subpackages
+install: install-am
diff --git a/tools/node_modules/expresso/deps/jscoverage/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/Makefile.in
new file mode 100644
index 0000000..a81160d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Makefile.in
@@ -0,0 +1,884 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - builds jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = jscoverage$(EXEEXT) jscoverage-server$(EXEEXT)
+noinst_PROGRAMS = generate-resources$(EXEEXT)
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in $(srcdir)/make-bin-dist.sh.in \
+ $(srcdir)/make-dist.sh.in $(top_srcdir)/configure COPYING \
+ config.guess config.rpath config.sub depcomp install-sh \
+ missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES = make-dist.sh make-bin-dist.sh
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+am_generate_resources_OBJECTS = generate-resources.$(OBJEXT)
+generate_resources_OBJECTS = $(am_generate_resources_OBJECTS)
+generate_resources_LDADD = $(LDADD)
+am__objects_1 =
+am_jscoverage_OBJECTS = encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument.$(OBJEXT) instrument-js.$(OBJEXT) \
+ jscoverage.$(OBJEXT) resource-manager.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT) $(am__objects_1)
+jscoverage_OBJECTS = $(am_jscoverage_OBJECTS)
+jscoverage_DEPENDENCIES = js/obj/libjs.a
+am_jscoverage_server_OBJECTS = http-connection.$(OBJEXT) \
+ http-exchange.$(OBJEXT) http-host.$(OBJEXT) \
+ http-message.$(OBJEXT) http-server.$(OBJEXT) \
+ http-url.$(OBJEXT) encoding.$(OBJEXT) highlight.$(OBJEXT) \
+ instrument-js.$(OBJEXT) jscoverage-server.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT) \
+ $(am__objects_1)
+jscoverage_server_OBJECTS = $(am_jscoverage_server_OBJECTS)
+jscoverage_server_DEPENDENCIES = js/obj/libjs.a
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+DIST_SOURCES = $(generate_resources_SOURCES) $(jscoverage_SOURCES) \
+ $(jscoverage_server_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ { test ! -d $(distdir) \
+ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@
+EXTRA_THREAD_LIBS = @EXTRA_THREAD_LIBS@
+EXTRA_TIMER_LIBS = @EXTRA_TIMER_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XP_DEF = @XP_DEF@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I m4
+SUBDIRS = js
+AM_CFLAGS = -Ijs -Ijs/obj @XP_DEF@
+AM_CXXFLAGS = -Ijs -Ijs/obj @XP_DEF@
+resources = jscoverage-help.txt jscoverage-server-help.txt \
+ jscoverage.jsm jscoverage.manifest jscoverage.xul jscoverage-overlay.js \
+ jscoverage.html \
+ jscoverage.css jscoverage-ie.css jscoverage-highlight.css \
+ jscoverage.js report.js \
+ jscoverage-throbber.gif
+
+jscoverage_SOURCES = encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument.c instrument.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_LDADD = js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+jscoverage_server_SOURCES = http-connection.c \
+ http-exchange.c \
+ http-host.c \
+ http-message.c \
+ http-server.c http-server.h \
+ http-url.c \
+ encoding.c encoding.h \
+ highlight.c highlight.h \
+ instrument-js.cpp instrument-js.h \
+ jscoverage-server.c global.h \
+ resource-manager.c resource-manager.h \
+ stream.c stream.h \
+ util.c util.h \
+ $(resources)
+
+jscoverage_server_LDADD = js/obj/libjs.a -lm @EXTRA_SOCKET_LIBS@ @EXTRA_THREAD_LIBS@ @LIBICONV@ @EXTRA_TIMER_LIBS@
+generate_resources_SOURCES = generate-resources.c
+BUILT_SOURCES = resources.c
+dist_man_MANS = jscoverage.1 jscoverage-server.1
+CLEANFILES = *.gcno *.exe resources.c *~
+all: $(BUILT_SOURCES) config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+am--refresh:
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \
+ cd $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+make-dist.sh: $(top_builddir)/config.status $(srcdir)/make-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+make-bin-dist.sh: $(top_builddir)/config.status $(srcdir)/make-bin-dist.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(bindir)/$$f"; \
+ done
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+generate-resources$(EXEEXT): $(generate_resources_OBJECTS) $(generate_resources_DEPENDENCIES)
+ @rm -f generate-resources$(EXEEXT)
+ $(LINK) $(generate_resources_OBJECTS) $(generate_resources_LDADD) $(LIBS)
+jscoverage$(EXEEXT): $(jscoverage_OBJECTS) $(jscoverage_DEPENDENCIES)
+ @rm -f jscoverage$(EXEEXT)
+ $(CXXLINK) $(jscoverage_OBJECTS) $(jscoverage_LDADD) $(LIBS)
+jscoverage-server$(EXEEXT): $(jscoverage_server_OBJECTS) $(jscoverage_server_DEPENDENCIES)
+ @rm -f jscoverage-server$(EXEEXT)
+ $(CXXLINK) $(jscoverage_server_OBJECTS) $(jscoverage_server_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-resources.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/highlight.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-connection.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-exchange.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-host.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-message.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-url.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrument-js.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrument.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jscoverage-server.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jscoverage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+install-man1: $(man1_MANS) $(man_MANS)
+ @$(NORMAL_INSTALL)
+ test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)"
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list='$(man1_MANS) $(dist_man1_MANS) $(nodist_man1_MANS)'; \
+ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+ for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ case "$$ext" in \
+ 1*) ;; \
+ *) ext='1' ;; \
+ esac; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed -e 's/^.*\///'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f '$(DESTDIR)$(man1dir)/$$inst'"; \
+ rm -f "$(DESTDIR)$(man1dir)/$$inst"; \
+ done
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d $(distdir) || mkdir $(distdir)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r $(distdir)
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+ $(am__remove_distdir)
+
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
+
+dist-tarZ: distdir
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__remove_distdir)
+
+dist-shar: distdir
+ shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+ $(am__remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__remove_distdir)
+
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir); chmod a+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
+ chmod a-w $(distdir)
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && cd $(distdir)/_build \
+ && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+ $(am__remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @cd $(distuninstallcheck_dir) \
+ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(PROGRAMS) $(MANS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-recursive
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-recursive
+
+install-info: install-info-recursive
+
+install-man: install-man1
+
+install-pdf: install-pdf-recursive
+
+install-ps: install-ps-recursive
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \
+ install-strip
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am am--refresh check check-am clean clean-binPROGRAMS \
+ clean-generic clean-noinstPROGRAMS ctags ctags-recursive dist \
+ dist-all dist-bzip2 dist-gzip dist-lzma dist-shar dist-tarZ \
+ dist-zip distcheck distclean distclean-compile \
+ distclean-generic distclean-hdr distclean-tags distcleancheck \
+ distdir distuninstallcheck dvi dvi-am html html-am info \
+ info-am install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-man1 install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \
+ tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-man uninstall-man1
+
+
+resources.c: generate-resources $(resources)
+ $(srcdir)/generate-resources $(resources) > $@
+
+example: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example doc/instrumented
+
+example-inverted: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn doc/example-inverted doc/instrumented-inverted
+
+example-jsunit: jscoverage
+ $(srcdir)/jscoverage --exclude=.svn --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+
+# override default install target so as not to recursively install subpackages
+install: install-am
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/Readme.md b/tools/node_modules/expresso/deps/jscoverage/Readme.md
new file mode 100644
index 0000000..7d7bda7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/Readme.md
@@ -0,0 +1,8 @@
+# node-jscoverage
+
+ [JScoverage](http://siliconforks.com/jscoverage/) for node.
+
+## Installation
+
+ $ ./configure && make && make install
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/aclocal.m4 b/tools/node_modules/expresso/deps/jscoverage/aclocal.m4
new file mode 100644
index 0000000..8c0fb02
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/aclocal.m4
@@ -0,0 +1,872 @@
+# generated automatically by aclocal 1.10.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(AC_AUTOCONF_VERSION, [2.61],,
+[m4_warning([this file was generated for autoconf 2.61.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.10'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.10.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.10.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 3
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`AS_DIRNAME("$mf")`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`AS_DIRNAME(["$file"])`
+ AS_MKDIR_P([$dirpart/$fdir])
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled. FIXME. This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 13
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.60])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 3
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+ [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+ [m4_case([$1], [ustar],, [pax],,
+ [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar;
+ do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/iconv.m4])
+m4_include([m4/lib-ld.m4])
+m4_include([m4/lib-link.m4])
+m4_include([m4/lib-prefix.m4])
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.guess b/tools/node_modules/expresso/deps/jscoverage/config.guess
new file mode 100755
index 0000000..f32079a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.guess
@@ -0,0 +1,1526 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-23'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[456])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ case ${UNAME_MACHINE} in
+ pc98)
+ echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ *:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ *:Interix*:[3456]*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ EM64T | authenticamd)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^CPU/{
+ s: ::g
+ p
+ }'`"
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
+ /^LIBC/{
+ s: ::g
+ p
+ }'`"
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.h b/tools/node_modules/expresso/deps/jscoverage/config.h
new file mode 100644
index 0000000..ece8c61
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.h
@@ -0,0 +1,93 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#define HAVE_GETHOSTBYNAME_R 1
+
+/* Define if you have the iconv() function and it works. */
+#define HAVE_ICONV 1
+
+/* Define to 1 if you have the <iconv.h> header file. */
+#define HAVE_ICONV_H 1
+
+/* Define to 1 if you have the `inet_aton' function. */
+#define HAVE_INET_ATON 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `MultiByteToWideChar' function. */
+/* #undef HAVE_MULTIBYTETOWIDECHAR */
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strndup' function. */
+#define HAVE_STRNDUP 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+/* Define as const if the declaration of iconv() needs const. */
+#define ICONV_CONST
+
+/* Name of package */
+#define PACKAGE "jscoverage"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "jscoverage"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "jscoverage 0.4"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "jscoverage"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.4"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.4"
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.h.in b/tools/node_modules/expresso/deps/jscoverage/config.h.in
new file mode 100644
index 0000000..fb3f802
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.h.in
@@ -0,0 +1,92 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `gethostbyname_r' function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define if you have the iconv() function and it works. */
+#undef HAVE_ICONV
+
+/* Define to 1 if you have the <iconv.h> header file. */
+#undef HAVE_ICONV_H
+
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `MultiByteToWideChar' function. */
+#undef HAVE_MULTIBYTETOWIDECHAR
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strndup' function. */
+#undef HAVE_STRNDUP
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
+/* Define as const if the declaration of iconv() needs const. */
+#undef ICONV_CONST
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.log b/tools/node_modules/expresso/deps/jscoverage/config.log
new file mode 100644
index 0000000..8600990
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.log
@@ -0,0 +1,899 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by jscoverage configure 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ ./configure
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = happy.bec-systems.com
+uname -m = x86_64
+uname -r = 2.6.35-30-generic
+uname -s = Linux
+uname -v = #54-Ubuntu SMP Tue Jun 7 18:41:54 UTC 2011
+
+/usr/bin/uname -p = unknown
+/bin/uname -X = unknown
+
+/bin/arch = unknown
+/usr/bin/arch -k = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo = unknown
+/bin/machine = unknown
+/usr/bin/oslevel = unknown
+/bin/universe = unknown
+
+PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin
+PATH: /scratch/oe/oe-admin/tools/node_modules/expresso/node_modules/.bin
+PATH: /scratch/oe/oe-admin/tools/node_modules/.bin
+PATH: /home/cbrake/bin
+PATH: /home/cbrake/bin
+PATH: /usr/local/sbin
+PATH: /usr/local/bin
+PATH: /usr/sbin
+PATH: /usr/bin
+PATH: /sbin
+PATH: /bin
+PATH: /usr/games
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:1807: checking for a BSD-compatible install
+configure:1863: result: /usr/bin/install -c
+configure:1874: checking whether build environment is sane
+configure:1917: result: yes
+configure:1945: checking for a thread-safe mkdir -p
+configure:1984: result: /bin/mkdir -p
+configure:1997: checking for gawk
+configure:2013: found /usr/bin/gawk
+configure:2024: result: gawk
+configure:2035: checking whether make sets $(MAKE)
+configure:2056: result: yes
+configure:2253: checking build system type
+configure:2271: result: x86_64-unknown-linux-gnu
+configure:2293: checking host system type
+configure:2308: result: x86_64-unknown-linux-gnu
+configure:2380: checking for gcc
+configure:2396: found /usr/bin/gcc
+configure:2407: result: gcc
+configure:2645: checking for C compiler version
+configure:2652: gcc --version >&5
+gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
+Copyright (C) 2010 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:2655: $? = 0
+configure:2662: gcc -v >&5
+Using built-in specs.
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
+configure:2665: $? = 0
+configure:2672: gcc -V >&5
+gcc: '-V' option must have argument
+configure:2675: $? = 1
+configure:2698: checking for C compiler default output file name
+configure:2725: gcc conftest.c >&5
+configure:2728: $? = 0
+configure:2766: result: a.out
+configure:2783: checking whether the C compiler works
+configure:2793: ./a.out
+configure:2796: $? = 0
+configure:2813: result: yes
+configure:2820: checking whether we are cross compiling
+configure:2822: result: no
+configure:2825: checking for suffix of executables
+configure:2832: gcc -o conftest conftest.c >&5
+configure:2835: $? = 0
+configure:2859: result:
+configure:2865: checking for suffix of object files
+configure:2891: gcc -c conftest.c >&5
+configure:2894: $? = 0
+configure:2917: result: o
+configure:2921: checking whether we are using the GNU C compiler
+configure:2950: gcc -c conftest.c >&5
+configure:2956: $? = 0
+configure:2973: result: yes
+configure:2978: checking whether gcc accepts -g
+configure:3008: gcc -c -g conftest.c >&5
+configure:3014: $? = 0
+configure:3113: result: yes
+configure:3130: checking for gcc option to accept ISO C89
+configure:3204: gcc -c -g -O2 conftest.c >&5
+configure:3210: $? = 0
+configure:3233: result: none needed
+configure:3262: checking for style of include used by make
+configure:3290: result: GNU
+configure:3315: checking dependency style of gcc
+configure:3406: result: gcc3
+configure:3421: checking for gcc option to accept ISO C99
+configure:3580: gcc -c -g -O2 conftest.c >&5
+conftest.c:60: error: expected ';', ',' or ')' before 'text'
+conftest.c: In function 'main':
+conftest.c:114: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'newvar'
+conftest.c:114: error: 'newvar' undeclared (first use in this function)
+conftest.c:114: error: (Each undeclared identifier is reported only once
+conftest.c:114: error: for each function it appears in.)
+conftest.c:124: error: 'for' loop initial declarations are only allowed in C99 mode
+conftest.c:124: note: use option -std=c99 or -std=gnu99 to compile your code
+configure:3586: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| /* end confdefs.h. */
+| #include <stdarg.h>
+| #include <stdbool.h>
+| #include <stdlib.h>
+| #include <wchar.h>
+| #include <stdio.h>
+|
+| // Check varargs macros. These examples are taken from C99 6.10.3.5.
+| #define debug(...) fprintf (stderr, __VA_ARGS__)
+| #define showlist(...) puts (#__VA_ARGS__)
+| #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+| static void
+| test_varargs_macros (void)
+| {
+| int x = 1234;
+| int y = 5678;
+| debug ("Flag");
+| debug ("X = %d\n", x);
+| showlist (The first, second, and third items.);
+| report (x>y, "x is %d but y is %d", x, y);
+| }
+|
+| // Check long long types.
+| #define BIG64 18446744073709551615ull
+| #define BIG32 4294967295ul
+| #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+| #if !BIG_OK
+| your preprocessor is broken;
+| #endif
+| #if BIG_OK
+| #else
+| your preprocessor is broken;
+| #endif
+| static long long int bignum = -9223372036854775807LL;
+| static unsigned long long int ubignum = BIG64;
+|
+| struct incomplete_array
+| {
+| int datasize;
+| double data[];
+| };
+|
+| struct named_init {
+| int number;
+| const wchar_t *name;
+| double average;
+| };
+|
+| typedef const char *ccp;
+|
+| static inline int
+| test_restrict (ccp restrict text)
+| {
+| // See if C++-style comments work.
+| // Iterate through items via the restricted pointer.
+| // Also check for declarations in for loops.
+| for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+| continue;
+| return 0;
+| }
+|
+| // Check varargs and va_copy.
+| static void
+| test_varargs (const char *format, ...)
+| {
+| va_list args;
+| va_start (args, format);
+| va_list args_copy;
+| va_copy (args_copy, args);
+|
+| const char *str;
+| int number;
+| float fnumber;
+|
+| while (*format)
+| {
+| switch (*format++)
+| {
+| case 's': // string
+| str = va_arg (args_copy, const char *);
+| break;
+| case 'd': // int
+| number = va_arg (args_copy, int);
+| break;
+| case 'f': // float
+| fnumber = va_arg (args_copy, double);
+| break;
+| default:
+| break;
+| }
+| }
+| va_end (args_copy);
+| va_end (args);
+| }
+|
+| int
+| main ()
+| {
+|
+| // Check bool.
+| _Bool success = false;
+|
+| // Check restrict.
+| if (test_restrict ("String literal") == 0)
+| success = true;
+| char *restrict newvar = "Another string";
+|
+| // Check varargs.
+| test_varargs ("s, d' f .", "string", 65, 34.234);
+| test_varargs_macros ();
+|
+| // Check flexible array members.
+| struct incomplete_array *ia =
+| malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+| ia->datasize = 10;
+| for (int i = 0; i < ia->datasize; ++i)
+| ia->data[i] = i * 1.234;
+|
+| // Check named initializers.
+| struct named_init ni = {
+| .number = 34,
+| .name = L"Test wide string",
+| .average = 543.34343,
+| };
+|
+| ni.number = 58;
+|
+| int dynamic_array[ni.number];
+| dynamic_array[ni.number - 1] = 543;
+|
+| // work around unused variable warnings
+| return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+| || dynamic_array[ni.number - 1] != 543);
+|
+| ;
+| return 0;
+| }
+configure:3580: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:3586: $? = 0
+configure:3616: result: -std=gnu99
+configure:3680: checking for g++
+configure:3696: found /usr/bin/g++
+configure:3707: result: g++
+configure:3738: checking for C++ compiler version
+configure:3745: g++ --version >&5
+g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
+Copyright (C) 2010 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:3748: $? = 0
+configure:3755: g++ -v >&5
+Using built-in specs.
+Target: x86_64-linux-gnu
+Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
+Thread model: posix
+gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)
+configure:3758: $? = 0
+configure:3765: g++ -V >&5
+g++: '-V' option must have argument
+configure:3768: $? = 1
+configure:3771: checking whether we are using the GNU C++ compiler
+configure:3800: g++ -c conftest.cpp >&5
+configure:3806: $? = 0
+configure:3823: result: yes
+configure:3828: checking whether g++ accepts -g
+configure:3858: g++ -c -g conftest.cpp >&5
+configure:3864: $? = 0
+configure:3963: result: yes
+configure:3988: checking dependency style of g++
+configure:4079: result: gcc3
+configure:4136: checking for ld used by GCC
+configure:4200: result: /usr/bin/ld
+configure:4209: checking if the linker (/usr/bin/ld) is GNU ld
+configure:4222: result: yes
+configure:4229: checking for shared library run path origin
+configure:4242: result: done
+configure:4751: checking for iconv
+configure:4783: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:4789: $? = 0
+configure:4859: result: yes
+configure:4862: checking for working iconv
+configure:4948: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:4951: $? = 0
+configure:4957: ./conftest
+configure:4960: $? = 0
+configure:4978: result: yes
+configure:5008: checking for iconv declaration
+configure:5047: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5053: $? = 0
+configure:5072: result:
+ extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+configure:5089: checking how to run the C preprocessor
+configure:5129: gcc -std=gnu99 -E conftest.c
+configure:5135: $? = 0
+configure:5166: gcc -std=gnu99 -E conftest.c
+conftest.c:12: fatal error: ac_nonexistent.h: No such file or directory
+compilation terminated.
+configure:5172: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:5205: result: gcc -std=gnu99 -E
+configure:5234: gcc -std=gnu99 -E conftest.c
+configure:5240: $? = 0
+configure:5271: gcc -std=gnu99 -E conftest.c
+conftest.c:12: fatal error: ac_nonexistent.h: No such file or directory
+compilation terminated.
+configure:5277: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:5315: checking for grep that handles long lines and -e
+configure:5389: result: /bin/grep
+configure:5394: checking for egrep
+configure:5472: result: /bin/grep -E
+configure:5477: checking for ANSI C header files
+configure:5507: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5513: $? = 0
+configure:5612: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:5615: $? = 0
+configure:5621: ./conftest
+configure:5624: $? = 0
+configure:5641: result: yes
+configure:5665: checking for sys/types.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for sys/stat.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for stdlib.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for string.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for memory.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for strings.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for inttypes.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for stdint.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5665: checking for unistd.h
+configure:5686: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5692: $? = 0
+configure:5708: result: yes
+configure:5735: checking pthread.h usability
+configure:5752: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5758: $? = 0
+configure:5772: result: yes
+configure:5776: checking pthread.h presence
+configure:5791: gcc -std=gnu99 -E conftest.c
+configure:5797: $? = 0
+configure:5811: result: yes
+configure:5839: checking for pthread.h
+configure:5847: result: yes
+configure:5875: checking iconv.h usability
+configure:5892: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:5898: $? = 0
+configure:5912: result: yes
+configure:5916: checking iconv.h presence
+configure:5931: gcc -std=gnu99 -E conftest.c
+configure:5937: $? = 0
+configure:5951: result: yes
+configure:5979: checking for iconv.h
+configure:5987: result: yes
+configure:6015: checking windows.h usability
+configure:6032: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+conftest.c:57: fatal error: windows.h: No such file or directory
+compilation terminated.
+configure:6038: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <windows.h>
+configure:6052: result: no
+configure:6056: checking windows.h presence
+configure:6071: gcc -std=gnu99 -E conftest.c
+conftest.c:24: fatal error: windows.h: No such file or directory
+compilation terminated.
+configure:6077: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| /* end confdefs.h. */
+| #include <windows.h>
+configure:6091: result: no
+configure:6119: checking for windows.h
+configure:6127: result: no
+configure:6142: checking whether byte ordering is bigendian
+configure:6175: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+configure:6181: $? = 0
+configure:6213: gcc -std=gnu99 -c -g -O2 conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:31: error: 'not' undeclared (first use in this function)
+conftest.c:31: error: (Each undeclared identifier is reported only once
+conftest.c:31: error: for each function it appears in.)
+conftest.c:31: error: expected ';' before 'big'
+configure:6219: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| /* end confdefs.h. */
+| #include <sys/types.h>
+| #include <sys/param.h>
+|
+| int
+| main ()
+| {
+| #if BYTE_ORDER != BIG_ENDIAN
+| not big endian
+| #endif
+|
+| ;
+| return 0;
+| }
+configure:6359: result: no
+configure:6389: checking for getaddrinfo
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for gethostbyname_r
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for inet_aton
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for strndup
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+conftest.c:50: warning: conflicting types for built-in function 'strndup'
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for vasprintf
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6389: checking for asprintf
+configure:6445: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+configure:6451: $? = 0
+configure:6469: result: yes
+configure:6479: checking for MultiByteToWideChar
+configure:6508: gcc -std=gnu99 -o conftest -g -O2 conftest.c >&5
+conftest.c:30: fatal error: windows.h: No such file or directory
+compilation terminated.
+configure:6514: $? = 1
+configure: failed program was:
+| /* confdefs.h. */
+| #define PACKAGE_NAME "jscoverage"
+| #define PACKAGE_TARNAME "jscoverage"
+| #define PACKAGE_VERSION "0.4"
+| #define PACKAGE_STRING "jscoverage 0.4"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE "jscoverage"
+| #define VERSION "0.4"
+| #define HAVE_ICONV 1
+| #define ICONV_CONST
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_PTHREAD_H 1
+| #define HAVE_ICONV_H 1
+| #define HAVE_GETADDRINFO 1
+| #define HAVE_GETHOSTBYNAME_R 1
+| #define HAVE_INET_ATON 1
+| #define HAVE_STRNDUP 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| /* end confdefs.h. */
+| #include <windows.h>
+| int
+| main ()
+| {
+| MultiByteToWideChar(0,0,0,0,0,0);
+| ;
+| return 0;
+| }
+configure:6533: result: no
+configure:6699: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by jscoverage config.status 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status
+
+on happy.bec-systems.com
+
+config.status:661: creating Makefile
+config.status:661: creating make-dist.sh
+config.status:661: creating make-bin-dist.sh
+config.status:661: creating tests/Makefile
+config.status:661: creating config.h
+config.status:944: executing depfiles commands
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_build=x86_64-unknown-linux-gnu
+ac_cv_c_bigendian=no
+ac_cv_c_compiler_gnu=yes
+ac_cv_cxx_compiler_gnu=yes
+ac_cv_env_CCC_set=
+ac_cv_env_CCC_value=
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_CXXFLAGS_set=
+ac_cv_env_CXXFLAGS_value=
+ac_cv_env_CXX_set=
+ac_cv_env_CXX_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func_asprintf=yes
+ac_cv_func_getaddrinfo=yes
+ac_cv_func_gethostbyname_r=yes
+ac_cv_func_inet_aton=yes
+ac_cv_func_strndup=yes
+ac_cv_func_vasprintf=yes
+ac_cv_header_iconv_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_memory_h=yes
+ac_cv_header_pthread_h=yes
+ac_cv_header_stdc=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_stat_h=yes
+ac_cv_header_sys_types_h=yes
+ac_cv_header_unistd_h=yes
+ac_cv_header_windows_h=no
+ac_cv_host=x86_64-unknown-linux-gnu
+ac_cv_objext=o
+ac_cv_path_EGREP='/bin/grep -E'
+ac_cv_path_GREP=/bin/grep
+ac_cv_path_install='/usr/bin/install -c'
+ac_cv_path_mkdir=/bin/mkdir
+ac_cv_prog_AWK=gawk
+ac_cv_prog_CPP='gcc -std=gnu99 -E'
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_CXX=g++
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_c99=-std=gnu99
+ac_cv_prog_cc_g=yes
+ac_cv_prog_cxx_g=yes
+ac_cv_prog_make_make_set=yes
+acl_cv_hardcode_direct=no
+acl_cv_hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+acl_cv_hardcode_libdir_separator=
+acl_cv_hardcode_minus_L=no
+acl_cv_libext=a
+acl_cv_libname_spec='lib$name'
+acl_cv_library_names_spec='$libname$shrext'
+acl_cv_path_LD=/usr/bin/ld
+acl_cv_prog_gnu_ld=yes
+acl_cv_rpath=done
+acl_cv_shlibext=so
+acl_cv_wl=-Wl,
+am_cv_CC_dependencies_compiler_type=gcc3
+am_cv_CXX_dependencies_compiler_type=gcc3
+am_cv_func_iconv=yes
+am_cv_func_iconv_works=yes
+am_cv_lib_iconv=no
+am_cv_proto_iconv='extern size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);'
+am_cv_proto_iconv_arg1=
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+ACLOCAL='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10'
+AMDEPBACKSLASH='\'
+AMDEP_FALSE='#'
+AMDEP_TRUE=''
+AMTAR='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar'
+AUTOCONF='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf'
+AUTOHEADER='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader'
+AUTOMAKE='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10'
+AWK='gawk'
+CC='gcc -std=gnu99'
+CCDEPMODE='depmode=gcc3'
+CFLAGS='-g -O2'
+CPP='gcc -std=gnu99 -E'
+CPPFLAGS=''
+CXX='g++'
+CXXDEPMODE='depmode=gcc3'
+CXXFLAGS='-g -O2'
+CYGPATH_W='echo'
+DEFS='-DHAVE_CONFIG_H'
+DEPDIR='.deps'
+ECHO_C=''
+ECHO_N='-n'
+ECHO_T=''
+EGREP='/bin/grep -E'
+EXEEXT=''
+EXTRA_SOCKET_LIBS=''
+EXTRA_THREAD_LIBS='-lpthread'
+EXTRA_TIMER_LIBS=''
+GREP='/bin/grep'
+INSTALL_DATA='${INSTALL} -m 644'
+INSTALL_PROGRAM='${INSTALL}'
+INSTALL_SCRIPT='${INSTALL}'
+INSTALL_STRIP_PROGRAM='$(install_sh) -c -s'
+LDFLAGS=''
+LIBICONV=''
+LIBOBJS=''
+LIBS=''
+LTLIBICONV=''
+LTLIBOBJS=''
+MAKEINFO='${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo'
+OBJEXT='o'
+PACKAGE='jscoverage'
+PACKAGE_BUGREPORT=''
+PACKAGE_NAME='jscoverage'
+PACKAGE_STRING='jscoverage 0.4'
+PACKAGE_TARNAME='jscoverage'
+PACKAGE_VERSION='0.4'
+PATH_SEPARATOR=':'
+SET_MAKE=''
+SHELL='/bin/sh'
+STRIP=''
+VERSION='0.4'
+XP_DEF='-DXP_UNIX'
+ac_ct_CC='gcc'
+ac_ct_CXX='g++'
+am__fastdepCC_FALSE='#'
+am__fastdepCC_TRUE=''
+am__fastdepCXX_FALSE='#'
+am__fastdepCXX_TRUE=''
+am__include='include'
+am__isrc=''
+am__leading_dot='.'
+am__quote=''
+am__tar='${AMTAR} chof - "$$tardir"'
+am__untar='${AMTAR} xf -'
+bindir='${exec_prefix}/bin'
+build='x86_64-unknown-linux-gnu'
+build_alias=''
+build_cpu='x86_64'
+build_os='linux-gnu'
+build_vendor='unknown'
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host='x86_64-unknown-linux-gnu'
+host_alias=''
+host_cpu='x86_64'
+host_os='linux-gnu'
+host_vendor='unknown'
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+install_sh='$(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+mkdir_p='/bin/mkdir -p'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target_alias=''
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+#define PACKAGE_NAME "jscoverage"
+#define PACKAGE_TARNAME "jscoverage"
+#define PACKAGE_VERSION "0.4"
+#define PACKAGE_STRING "jscoverage 0.4"
+#define PACKAGE_BUGREPORT ""
+#define PACKAGE "jscoverage"
+#define VERSION "0.4"
+#define HAVE_ICONV 1
+#define ICONV_CONST
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_PTHREAD_H 1
+#define HAVE_ICONV_H 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETHOSTBYNAME_R 1
+#define HAVE_INET_ATON 1
+#define HAVE_STRNDUP 1
+#define HAVE_VASPRINTF 1
+#define HAVE_ASPRINTF 1
+
+configure: exit 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.rpath b/tools/node_modules/expresso/deps/jscoverage/config.rpath
new file mode 100755
index 0000000..c547c68
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.rpath
@@ -0,0 +1,666 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+# Copyright 1996-2007 Free Software Foundation, Inc.
+# Taken from GNU libtool, 2001
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# Known limitations:
+# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
+# than 256 bytes, otherwise the compiler driver will dump core. The only
+# known workaround is to choose shorter directory names for the build
+# directory and/or the installation directory.
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+shrext=.so
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+# Code taken from libtool.m4's _LT_CC_BASENAME.
+
+for cc_temp in $CC""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
+
+# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
+
+wl=
+if test "$GCC" = yes; then
+ wl='-Wl,'
+else
+ case "$host_os" in
+ aix*)
+ wl='-Wl,'
+ ;;
+ darwin*)
+ case $cc_basename in
+ xlc*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | pw32* | os2*)
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ wl='-Wl,'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ wl='-Wl,'
+ ;;
+ newsos6)
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ icc* | ecc*)
+ wl='-Wl,'
+ ;;
+ pgcc | pgf77 | pgf90)
+ wl='-Wl,'
+ ;;
+ ccc*)
+ wl='-Wl,'
+ ;;
+ como)
+ wl='-lopt='
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ osf3* | osf4* | osf5*)
+ wl='-Wl,'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ wl='-Wl,'
+ ;;
+ sunos4*)
+ wl='-Qoption ld '
+ ;;
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ wl='-Wl,'
+ ;;
+ sysv4*MP*)
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ wl='-Wl,'
+ ;;
+ unicos*)
+ wl='-Wl,'
+ ;;
+ uts4*)
+ ;;
+ esac
+fi
+
+# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ # Unlike libtool, we use -rpath here, not --rpath, since the documented
+ # option of GNU ld is called -rpath, not --rpath.
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ case "$host_os" in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we cannot use
+ # them.
+ ld_shlibs=no
+ ;;
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ cygwin* | mingw* | pw32*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ gnu* | linux* | k*bsd*-gnu)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ netbsd*)
+ ;;
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+ sunos4*)
+ hardcode_direct=yes
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ if test "$ld_shlibs" = no; then
+ hardcode_libdir_flag_spec=
+ fi
+else
+ case "$host_os" in
+ aix3*)
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ else
+ aix_use_runtimelinking=no
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+ fi
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ fi
+ # Begin _LT_AC_SYS_LIBPATH_AIX.
+ echo 'int main () { return 0; }' > conftest.c
+ ${CC} ${LDFLAGS} conftest.c -o conftest
+ aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ fi
+ if test -z "$aix_libpath"; then
+ aix_libpath="/usr/lib:/lib"
+ fi
+ rm -f conftest.c conftest
+ # End _LT_AC_SYS_LIBPATH_AIX.
+ if test "$aix_use_runtimelinking" = yes; then
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ else
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ fi
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+ bsdi[45]*)
+ ;;
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ libext=lib
+ ;;
+ darwin* | rhapsody*)
+ hardcode_direct=no
+ if test "$GCC" = yes ; then
+ :
+ else
+ case $cc_basename in
+ xlc*)
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+ dgux*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+ freebsd2.2*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ freebsd2*)
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ freebsd* | dragonfly*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ hpux10*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+ hpux11*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ ;;
+ *)
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+ irix5* | irix6* | nonstopux*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ netbsd*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ newsos6)
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ else
+ case "$host_os" in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ osf3*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ osf4* | osf5*)
+ if test "$GCC" = yes; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ # Both cc and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+ solaris*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ sunos4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ sysv4)
+ case $host_vendor in
+ sni)
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ hardcode_direct=no
+ ;;
+ motorola)
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ ;;
+ sysv4.3*)
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ ld_shlibs=yes
+ fi
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ ;;
+ uts4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+
+# Check dynamic linker characteristics
+# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
+# Unlike libtool.m4, here we don't care about _all_ names of the library, but
+# only about the one the linker finds when passed -lNAME. This is the last
+# element of library_names_spec in libtool.m4, or possibly two of them if the
+# linker has special search rules.
+library_names_spec= # the last element of library_names_spec in libtool.m4
+libname_spec='lib$name'
+case "$host_os" in
+ aix3*)
+ library_names_spec='$libname.a'
+ ;;
+ aix4* | aix5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ amigaos*)
+ library_names_spec='$libname.a'
+ ;;
+ beos*)
+ library_names_spec='$libname$shrext'
+ ;;
+ bsdi[45]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ cygwin* | mingw* | pw32*)
+ shrext=.dll
+ library_names_spec='$libname.dll.a $libname.lib'
+ ;;
+ darwin* | rhapsody*)
+ shrext=.dylib
+ library_names_spec='$libname$shrext'
+ ;;
+ dgux*)
+ library_names_spec='$libname$shrext'
+ ;;
+ freebsd1*)
+ ;;
+ freebsd* | dragonfly*)
+ case "$host_os" in
+ freebsd[123]*)
+ library_names_spec='$libname$shrext$versuffix' ;;
+ *)
+ library_names_spec='$libname$shrext' ;;
+ esac
+ ;;
+ gnu*)
+ library_names_spec='$libname$shrext'
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $host_cpu in
+ ia64*)
+ shrext=.so
+ ;;
+ hppa*64*)
+ shrext=.sl
+ ;;
+ *)
+ shrext=.sl
+ ;;
+ esac
+ library_names_spec='$libname$shrext'
+ ;;
+ interix[3-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ library_names_spec='$libname$shrext'
+ case "$host_os" in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
+ *) libsuff= shlibsuff= ;;
+ esac
+ ;;
+ esac
+ ;;
+ linux*oldld* | linux*aout* | linux*coff*)
+ ;;
+ linux* | k*bsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ knetbsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ netbsd*)
+ library_names_spec='$libname$shrext'
+ ;;
+ newsos6)
+ library_names_spec='$libname$shrext'
+ ;;
+ nto-qnx*)
+ library_names_spec='$libname$shrext'
+ ;;
+ openbsd*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ os2*)
+ libname_spec='$name'
+ shrext=.dll
+ library_names_spec='$libname.a'
+ ;;
+ osf3* | osf4* | osf5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sunos4*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ sysv4 | sysv4.3*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv4*MP*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ library_names_spec='$libname$shrext'
+ ;;
+ uts4*)
+ library_names_spec='$libname$shrext'
+ ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
+escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Format of library name prefix.
+libname_spec="$escaped_libname_spec"
+
+# Library names that the linker finds when passed -lNAME.
+library_names_spec="$escaped_library_names_spec"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+EOF
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.status b/tools/node_modules/expresso/deps/jscoverage/config.status
new file mode 100755
index 0000000..cde41cb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.status
@@ -0,0 +1,1080 @@
+#! /bin/sh
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=${CONFIG_SHELL-/bin/sh}
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by jscoverage $as_me 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile make-dist.sh make-bin-dist.sh tests/Makefile"
+config_headers=" config.h"
+config_commands=" depfiles"
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+ac_cs_version="\
+jscoverage config.status 0.4
+configured by ./configure, generated by GNU Autoconf 2.61,
+ with options \"\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage'
+srcdir='.'
+INSTALL='/usr/bin/install -c'
+MKDIR_P='/bin/mkdir -p'
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+ echo "running CONFIG_SHELL=/bin/sh /bin/sh ./configure " $ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=/bin/sh
+ export CONFIG_SHELL
+ exec /bin/sh "./configure" $ac_configure_extra_args --no-create --no-recursion
+fi
+
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="" ac_aux_dir="."
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "make-dist.sh") CONFIG_FILES="$CONFIG_FILES make-dist.sh" ;;
+ "make-bin-dist.sh") CONFIG_FILES="$CONFIG_FILES make-bin-dist.sh" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+cat >"$tmp/subs-1.sed" <<\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@SHELL@,|#_!!_#|/bin/sh,g
+s,@PATH_SEPARATOR@,|#_!!_#|:,g
+s,@PACKAGE_NAME@,|#_!!_#|jscoverage,g
+s,@PACKAGE_TARNAME@,|#_!!_#|jscoverage,g
+s,@PACKAGE_VERSION@,|#_!!_#|0.4,g
+s,@PACKAGE_STRING@,|#_!!_#|jscoverage 0.4,g
+s,@PACKAGE_BUGREPORT@,|#_!!_#|,g
+s,@exec_prefix@,|#_!!_#|${prefix},g
+s,@prefix@,|#_!!_#|/usr/local,g
+s,@program_transform_name@,|#_!!_#|s\,x\,x\,,g
+s,@bindir@,|#_!!_#|${exec_prefix}/bin,g
+s,@sbindir@,|#_!!_#|${exec_prefix}/sbin,g
+s,@libexecdir@,|#_!!_#|${exec_prefix}/libexec,g
+s,@datarootdir@,|#_!!_#|${prefix}/share,g
+s,@datadir@,|#_!!_#|${datarootdir},g
+s,@sysconfdir@,|#_!!_#|${prefix}/etc,g
+s,@sharedstatedir@,|#_!!_#|${prefix}/com,g
+s,@localstatedir@,|#_!!_#|${prefix}/var,g
+s,@includedir@,|#_!!_#|${prefix}/include,g
+s,@oldincludedir@,|#_!!_#|/usr/include,g
+s,@docdir@,|#_!!_#|${datarootdir}/doc/${PACKAGE_TARNAME},g
+s,@infodir@,|#_!!_#|${datarootdir}/info,g
+s,@htmldir@,|#_!!_#|${docdir},g
+s,@dvidir@,|#_!!_#|${docdir},g
+s,@pdfdir@,|#_!!_#|${docdir},g
+s,@psdir@,|#_!!_#|${docdir},g
+s,@libdir@,|#_!!_#|${exec_prefix}/lib,g
+s,@localedir@,|#_!!_#|${datarootdir}/locale,g
+s,@mandir@,|#_!!_#|${datarootdir}/man,g
+s,@DEFS@,|#_!!_#|-DHAVE_CONFIG_H,g
+s,@ECHO_C@,|#_!!_#|,g
+s,@ECHO_N@,|#_!!_#|-n,g
+s,@ECHO_T@,|#_!!_#|,g
+s,@LIBS@,|#_!!_#|,g
+s,@build_alias@,|#_!!_#|,g
+s,@host_alias@,|#_!!_#|,g
+s,@target_alias@,|#_!!_#|,g
+s,@INSTALL_PROGRAM@,|#_!!_#|${INSTALL},g
+s,@INSTALL_SCRIPT@,|#_!!_#|${INSTALL},g
+s,@INSTALL_DATA@,|#_!!_#|${INSTALL} -m 644,g
+s,@am__isrc@,|#_!!_#|,g
+s,@CYGPATH_W@,|#_!!_#|echo,g
+s,@PACKAGE@,|#_!!_#|jscoverage,g
+s,@VERSION@,|#_!!_#|0.4,g
+s,@ACLOCAL@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10,g
+s,@AUTOCONF@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf,g
+s,@AUTOMAKE@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10,g
+s,@AUTOHEADER@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader,g
+s,@MAKEINFO@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo,g
+s,@install_sh@,|#_!!_#|$(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh,g
+s,@STRIP@,|#_!!_#|,g
+s,@INSTALL_STRIP_PROGRAM@,|#_!!_#|$(install_sh) -c -s,g
+s,@mkdir_p@,|#_!!_#|/bin/mkdir -p,g
+s,@AWK@,|#_!!_#|gawk,g
+s,@SET_MAKE@,|#_!!_#|,g
+s,@am__leading_dot@,|#_!!_#|.,g
+s,@AMTAR@,|#_!!_#|${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar,g
+s,@am__tar@,|#_!!_#|${AMTAR} chof - "$$tardir",g
+s,@am__untar@,|#_!!_#|${AMTAR} xf -,g
+s,@build@,|#_!!_#|x86_64-unknown-linux-gnu,g
+s,@build_cpu@,|#_!!_#|x86_64,g
+s,@build_vendor@,|#_!!_#|unknown,g
+s,@build_os@,|#_!!_#|linux-gnu,g
+s,@host@,|#_!!_#|x86_64-unknown-linux-gnu,g
+s,@host_cpu@,|#_!!_#|x86_64,g
+s,@host_vendor@,|#_!!_#|unknown,g
+s,@host_os@,|#_!!_#|linux-gnu,g
+s,@CC@,|#_!!_#|gcc -std=gnu99,g
+s,@CFLAGS@,|#_!!_#|-g -O2,g
+s,@LDFLAGS@,|#_!!_#|,g
+s,@CPPFLAGS@,|#_!!_#|,g
+s,@ac_ct_CC@,|#_!!_#|gcc,g
+s,@EXEEXT@,|#_!!_#|,g
+s,@OBJEXT@,|#_!!_#|o,g
+s,@DEPDIR@,|#_!!_#|.deps,g
+s,@am__include@,|#_!!_#|include,g
+s,@am__quote@,|#_!!_#|,g
+s,@AMDEP_TRUE@,|#_!!_#|,g
+s,@AMDEP_FALSE@,|#_!!_#|#,g
+s,@AMDEPBACKSLASH@,|#_!!_#|\\,g
+s,@CCDEPMODE@,|#_!!_#|depmode=gcc3,g
+s,@am__fastdepCC_TRUE@,|#_!!_#|,g
+s,@am__fastdepCC_FALSE@,|#_!!_#|#,g
+s,@CXX@,|#_!!_#|g++,g
+s,@CXXFLAGS@,|#_!!_#|-g -O2,g
+s,@ac_ct_CXX@,|#_!!_#|g++,g
+s,@CXXDEPMODE@,|#_!!_#|depmode=gcc3,g
+s,@am__fastdepCXX_TRUE@,|#_!!_#|,g
+s,@am__fastdepCXX_FALSE@,|#_!!_#|#,g
+s,@LIBICONV@,|#_!!_#|,g
+s,@LTLIBICONV@,|#_!!_#|,g
+s,@CPP@,|#_!!_#|gcc -std=gnu99 -E,g
+s,@GREP@,|#_!!_#|/bin/grep,g
+s,@EGREP@,|#_!!_#|/bin/grep -E,g
+s,@XP_DEF@,|#_!!_#|-DXP_UNIX,g
+s,@EXTRA_SOCKET_LIBS@,|#_!!_#|,g
+s,@EXTRA_THREAD_LIBS@,|#_!!_#|-lpthread,g
+CEOF
+cat >"$tmp/subs-2.sed" <<\CEOF
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+s,@EXTRA_TIMER_LIBS@,|#_!!_#|,g
+s,@LIBOBJS@,|#_!!_#|,g
+s,@LTLIBOBJS@,|#_!!_#|,g
+:end
+s/|#_!!_#|//g
+CEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ ac_datarootdir_hack='
+ s&@datadir@&${datarootdir}&g
+ s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+ s&@infodir@&${datarootdir}/info&g
+ s&@localedir@&${datarootdir}/locale&g
+ s&@mandir@&${datarootdir}/man&g
+ s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ sed "/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ # First, check the format of the line:
+ cat >"$tmp/defines.sed" <<\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[ ]*$/b def
+/^[ ]*#[ ]*define[ ][ ]*[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*[( ]/b def
+b
+:def
+s/$/ /
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_NAME\)[ (].*,\1define\2 "jscoverage" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_TARNAME\)[ (].*,\1define\2 "jscoverage" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_VERSION\)[ (].*,\1define\2 "0.4" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_STRING\)[ (].*,\1define\2 "jscoverage 0.4" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE_BUGREPORT\)[ (].*,\1define\2 "" ,
+s,^\([ #]*\)[^ ]*\([ ]*PACKAGE\)[ (].*,\1define\2 "jscoverage" ,
+s,^\([ #]*\)[^ ]*\([ ]*VERSION\)[ (].*,\1define\2 "0.4" ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_ICONV\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*ICONV_CONST\)[ (].*,\1define\2 ,
+s,^\([ #]*\)[^ ]*\([ ]*STDC_HEADERS\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_SYS_TYPES_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_SYS_STAT_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STDLIB_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STRING_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_MEMORY_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STRINGS_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_INTTYPES_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STDINT_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_UNISTD_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_PTHREAD_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_ICONV_H\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_GETADDRINFO\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_GETHOSTBYNAME_R\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_INET_ATON\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_STRNDUP\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_VASPRINTF\)[ (].*,\1define\2 1 ,
+s,^\([ #]*\)[^ ]*\([ ]*HAVE_ASPRINTF\)[ (].*,\1define\2 1 ,
+s/ $//
+s,^[ #]*u.*,/* & */,
+CEOF
+ sed -f "$tmp/defines.sed" $ac_file_inputs >"$tmp/out1"
+ac_result="$tmp/out1"
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_arg=$ac_file
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
diff --git a/tools/node_modules/expresso/deps/jscoverage/config.sub b/tools/node_modules/expresso/deps/jscoverage/config.sub
new file mode 100755
index 0000000..6759825
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/config.sub
@@ -0,0 +1,1658 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+# Free Software Foundation, Inc.
+
+timestamp='2008-01-16'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+ uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fido | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | mt \
+ | msp430 \
+ | nios | nios2 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tile*)
+ basic_machine=tile-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/configure b/tools/node_modules/expresso/deps/jscoverage/configure
new file mode 100755
index 0000000..71e6752
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/configure
@@ -0,0 +1,7971 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61 for jscoverage 0.4.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='jscoverage'
+PACKAGE_TARNAME='jscoverage'
+PACKAGE_VERSION='0.4'
+PACKAGE_STRING='jscoverage 0.4'
+PACKAGE_BUGREPORT=''
+
+ac_unique_file="jscoverage.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+am__isrc
+CYGPATH_W
+PACKAGE
+VERSION
+ACLOCAL
+AUTOCONF
+AUTOMAKE
+AUTOHEADER
+MAKEINFO
+install_sh
+STRIP
+INSTALL_STRIP_PROGRAM
+mkdir_p
+AWK
+SET_MAKE
+am__leading_dot
+AMTAR
+am__tar
+am__untar
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+DEPDIR
+am__include
+am__quote
+AMDEP_TRUE
+AMDEP_FALSE
+AMDEPBACKSLASH
+CCDEPMODE
+am__fastdepCC_TRUE
+am__fastdepCC_FALSE
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXDEPMODE
+am__fastdepCXX_TRUE
+am__fastdepCXX_FALSE
+LIBICONV
+LTLIBICONV
+CPP
+GREP
+EGREP
+XP_DEF
+EXTRA_SOCKET_LIBS
+EXTRA_THREAD_LIBS
+EXTRA_TIMER_LIBS
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures jscoverage 0.4 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/jscoverage]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of jscoverage 0.4:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --disable-rpath do not hardcode runtime library paths
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-gnu-ld assume the C compiler uses GNU ld default=no
+ --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
+ --without-libiconv-prefix don't search for libiconv in includedir and libdir
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+jscoverage configure 0.4
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by jscoverage $as_me 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.10'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t $srcdir/configure conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ { { echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm -f conftest.sed
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+ am_missing_run="$MISSING --run "
+else
+ am_missing_run=
+ { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+{ echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+echo $ECHO_N "checking for a thread-safe mkdir -p... $ECHO_C" >&6; }
+if test -z "$MKDIR_P"; then
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+done
+IFS=$as_save_IFS
+
+fi
+
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ test -d ./--version && rmdir ./--version
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+echo "${ECHO_T}$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { echo "$as_me:$LINENO: result: $AWK" >&5
+echo "${ECHO_T}$AWK" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='jscoverage'
+ VERSION='0.4'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+# We need awk for the "check" target. The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+# Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+ @echo done
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# We grep out `Entering directory' and `Leaving directory'
+# messages which can occur if `w' ends up in MAKEFLAGS.
+# In particular we don't look at `^make:' because GNU make might
+# be invoked under some other name (usually "gmake"), in which
+# case it prints its new name instead of `make'.
+if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
+ am__include=include
+ am__quote=
+ _am_result=GNU
+fi
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+ echo '.include "confinc"' > confmf
+ if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
+ am__include=.include
+ am__quote="\""
+ _am_result=BSD
+ fi
+fi
+
+
+{ echo "$as_me:$LINENO: result: $_am_result" >&5
+echo "${ECHO_T}$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+ { echo "$as_me:$LINENO: checking for $CC option to accept ISO C99" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C99... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c99+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+ your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg (args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+}
+
+int
+main ()
+{
+
+ // Check bool.
+ _Bool success = false;
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ test_varargs ("s, d' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+ || dynamic_array[ni.number - 1] != 543);
+
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -std=gnu99 -c99 -qlanglvl=extc99
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c99=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c99"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c99" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ case $depmode in
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ none) break ;;
+ esac
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ if depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+
+# Checks for libraries.
+
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { echo "$as_me:$LINENO: checking for ld used by GCC" >&5
+echo $ECHO_N "checking for ld used by GCC... $ECHO_C" >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${acl_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break ;;
+ *)
+ test "$with_gnu_ld" != yes && break ;;
+ esac
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${acl_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ acl_cv_prog_gnu_ld=yes ;;
+*)
+ acl_cv_prog_gnu_ld=no ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $acl_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$acl_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+
+ { echo "$as_me:$LINENO: checking for shared library run path origin" >&5
+echo $ECHO_N "checking for shared library run path origin... $ECHO_C" >&6; }
+if test "${acl_cv_rpath+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+
+fi
+{ echo "$as_me:$LINENO: result: $acl_cv_rpath" >&5
+echo "${ECHO_T}$acl_cv_rpath" >&6; }
+ wl="$acl_cv_wl"
+ acl_libext="$acl_cv_libext"
+ acl_shlibext="$acl_cv_shlibext"
+ acl_libname_spec="$acl_cv_libname_spec"
+ acl_library_names_spec="$acl_cv_library_names_spec"
+ acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ acl_hardcode_direct="$acl_cv_hardcode_direct"
+ acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ # Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then
+ enableval=$enable_rpath; :
+else
+ enable_rpath=yes
+fi
+
+
+
+ acl_libdirstem=lib
+ searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+
+
+
+
+
+
+
+
+
+ use_additional=yes
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then
+ withval=$with_libiconv_prefix;
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+
+fi
+
+ LIBICONV=
+ LTLIBICONV=
+ INCICONV=
+ LIBICONV_PREFIX=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='iconv '
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+ else
+ :
+ fi
+ else
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
+ if test -n "$acl_shlibext"; then
+ shrext=".$acl_shlibext" # typically: shrext=.so
+ else
+ shrext=
+ fi
+ if test $use_additional = yes; then
+ dir="$additional_libdir"
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ if test "$acl_hardcode_direct" = yes; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+ fi
+ if test "$acl_hardcode_minus_L" != no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+ fi
+ fi
+ additional_includedir=
+ case "$found_dir" in
+ */$acl_libdirstem | */$acl_libdirstem/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+ LIBICONV_PREFIX="$basedir"
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INCICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ if test -n "$found_la"; then
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$acl_hardcode_libdir_separator"; then
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ else
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ for found_dir in $ltrpathdirs; do
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+ done
+ fi
+
+
+
+
+
+
+
+
+ am_save_CPPFLAGS="$CPPFLAGS"
+
+ for element in $INCICONV; do
+ haveit=
+ for x in $CPPFLAGS; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+ fi
+ done
+
+
+ { echo "$as_me:$LINENO: checking for iconv" >&5
+echo $ECHO_N "checking for iconv... $ECHO_C" >&6; }
+if test "${am_cv_func_iconv+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ am_cv_func_iconv=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$am_save_LIBS"
+ fi
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_func_iconv" >&5
+echo "${ECHO_T}$am_cv_func_iconv" >&6; }
+ if test "$am_cv_func_iconv" = yes; then
+ { echo "$as_me:$LINENO: checking for working iconv" >&5
+echo $ECHO_N "checking for working iconv... $ECHO_C" >&6; }
+if test "${am_cv_func_iconv_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ am_save_LIBS="$LIBS"
+ if test $am_cv_lib_iconv = yes; then
+ LIBS="$LIBS $LIBICONV"
+ fi
+ if test "$cross_compiling" = yes; then
+ case "$host_os" in
+ aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+ *) am_cv_func_iconv_works="guessing yes" ;;
+ esac
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <iconv.h>
+#include <string.h>
+int main ()
+{
+ /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+ returns. */
+ {
+ iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+ if (cd_utf8_to_88591 != (iconv_t)(-1))
+ {
+ static const char input[] = "\342\202\254"; /* EURO SIGN */
+ char buf[10];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_utf8_to_88591,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res == 0)
+ return 1;
+ }
+ }
+#if 0 /* This bug could be worked around by the caller. */
+ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
+ {
+ iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+ if (cd_88591_to_utf8 != (iconv_t)(-1))
+ {
+ static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+ char buf[50];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_88591_to_utf8,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if ((int)res > 0)
+ return 1;
+ }
+ }
+#endif
+ /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+ provided. */
+ if (/* Try standardized names. */
+ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+ /* Try IRIX, OSF/1 names. */
+ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+ /* Try AIX names. */
+ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+ /* Try HP-UX names. */
+ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+ return 1;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ am_cv_func_iconv_works=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+am_cv_func_iconv_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+ LIBS="$am_save_LIBS"
+
+fi
+{ echo "$as_me:$LINENO: result: $am_cv_func_iconv_works" >&5
+echo "${ECHO_T}$am_cv_func_iconv_works" >&6; }
+ case "$am_cv_func_iconv_works" in
+ *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+ *) am_func_iconv=yes ;;
+ esac
+ else
+ am_func_iconv=no am_cv_lib_iconv=no
+ fi
+ if test "$am_func_iconv" = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ICONV 1
+_ACEOF
+
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ { echo "$as_me:$LINENO: checking how to link with libiconv" >&5
+echo $ECHO_N "checking how to link with libiconv... $ECHO_C" >&6; }
+ { echo "$as_me:$LINENO: result: $LIBICONV" >&5
+echo "${ECHO_T}$LIBICONV" >&6; }
+ else
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+
+
+
+ if test "$am_cv_func_iconv" = yes; then
+ { echo "$as_me:$LINENO: checking for iconv declaration" >&5
+echo $ECHO_N "checking for iconv declaration... $ECHO_C" >&6; }
+ if test "${am_cv_proto_iconv+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ am_cv_proto_iconv_arg1=""
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ am_cv_proto_iconv_arg1="const"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
+fi
+
+ am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ { echo "$as_me:$LINENO: result: ${ac_t:-
+ }$am_cv_proto_iconv" >&5
+echo "${ECHO_T}${ac_t:-
+ }$am_cv_proto_iconv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+ fi
+
+
+# Checks for header files.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in pthread.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in iconv.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in windows.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+# Checks for library functions.
+
+
+
+
+
+
+for ac_func in getaddrinfo gethostbyname_r inet_aton strndup vasprintf asprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking for MultiByteToWideChar" >&5
+echo $ECHO_N "checking for MultiByteToWideChar... $ECHO_C" >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <windows.h>
+int
+main ()
+{
+MultiByteToWideChar(0,0,0,0,0,0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MULTIBYTETOWIDECHAR 1
+_ACEOF
+
+ jscoverage_have_multibytetowidechar=yes
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ jscoverage_have_multibytetowidechar=no
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+case "$host_os" in
+ mingw*)
+ XP_DEF='-DXP_WIN'
+ ;;
+ *)
+ XP_DEF='-DXP_UNIX'
+ ;;
+esac
+
+
+
+
+case "$host_os" in
+ mingw*)
+ EXTRA_SOCKET_LIBS='-lws2_32'
+ EXTRA_THREAD_LIBS=''
+ EXTRA_TIMER_LIBS='-lwinmm'
+ ;;
+ *)
+ EXTRA_SOCKET_LIBS=''
+ EXTRA_THREAD_LIBS='-lpthread'
+ EXTRA_TIMER_LIBS=''
+ ;;
+esac
+
+if test "$am_cv_func_iconv" != yes && test "$jscoverage_have_multibytetowidechar" != yes
+then
+ echo -ne '\033[1;31m'
+ { echo "$as_me:$LINENO: WARNING: neither iconv nor Windows character encoding conversion functions found" >&5
+echo "$as_me: WARNING: neither iconv nor Windows character encoding conversion functions found" >&2;}
+ { echo "$as_me:$LINENO: WARNING: only ASCII will be supported" >&5
+echo "$as_me: WARNING: only ASCII will be supported" >&2;}
+ echo -ne '\033[0m'
+fi
+
+ac_config_files="$ac_config_files Makefile make-dist.sh make-bin-dist.sh tests/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by jscoverage $as_me 0.4, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+jscoverage config.status 0.4
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "make-dist.sh") CONFIG_FILES="$CONFIG_FILES make-dist.sh" ;;
+ "make-bin-dist.sh") CONFIG_FILES="$CONFIG_FILES make-bin-dist.sh" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+am__isrc!$am__isrc$ac_delim
+CYGPATH_W!$CYGPATH_W$ac_delim
+PACKAGE!$PACKAGE$ac_delim
+VERSION!$VERSION$ac_delim
+ACLOCAL!$ACLOCAL$ac_delim
+AUTOCONF!$AUTOCONF$ac_delim
+AUTOMAKE!$AUTOMAKE$ac_delim
+AUTOHEADER!$AUTOHEADER$ac_delim
+MAKEINFO!$MAKEINFO$ac_delim
+install_sh!$install_sh$ac_delim
+STRIP!$STRIP$ac_delim
+INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim
+mkdir_p!$mkdir_p$ac_delim
+AWK!$AWK$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+am__leading_dot!$am__leading_dot$ac_delim
+AMTAR!$AMTAR$ac_delim
+am__tar!$am__tar$ac_delim
+am__untar!$am__untar$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+DEPDIR!$DEPDIR$ac_delim
+am__include!$am__include$ac_delim
+am__quote!$am__quote$ac_delim
+AMDEP_TRUE!$AMDEP_TRUE$ac_delim
+AMDEP_FALSE!$AMDEP_FALSE$ac_delim
+AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim
+CCDEPMODE!$CCDEPMODE$ac_delim
+am__fastdepCC_TRUE!$am__fastdepCC_TRUE$ac_delim
+am__fastdepCC_FALSE!$am__fastdepCC_FALSE$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXDEPMODE!$CXXDEPMODE$ac_delim
+am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim
+am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim
+LIBICONV!$LIBICONV$ac_delim
+LTLIBICONV!$LTLIBICONV$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+XP_DEF!$XP_DEF$ac_delim
+EXTRA_SOCKET_LIBS!$EXTRA_SOCKET_LIBS$ac_delim
+EXTRA_THREAD_LIBS!$EXTRA_THREAD_LIBS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+EXTRA_TIMER_LIBS!$EXTRA_TIMER_LIBS$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 3; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+# Compute $ac_file's index in $config_headers.
+_am_arg=$ac_file
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do
+ # Strip MF so we end up with the name of the file.
+ mf=`echo "$mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile or not.
+ # We used to match only the files named `Makefile.in', but
+ # some people rename them; so instead we look at the file content.
+ # Grep'ing the first line is not enough: some people post-process
+ # each Makefile.in and add a new line on top of each file to say so.
+ # Grep'ing the whole file is not good either: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+ dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$mf" : 'X\(//\)[^/]' \| \
+ X"$mf" : 'X\(//\)$' \| \
+ X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ else
+ continue
+ fi
+ # Extract the definition of DEPDIR, am__include, and am__quote
+ # from the Makefile without running `make'.
+ DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+ test -z "$DEPDIR" && continue
+ am__include=`sed -n 's/^am__include = //p' < "$mf"`
+ test -z "am__include" && continue
+ am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
+ # Find all dependency output files, they are included files with
+ # $(DEPDIR) in their names. We invoke sed twice because it is the
+ # simplest approach to changing $(DEPDIR) to its actual value in the
+ # expansion.
+ for file in `sed -n "
+ s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+ # Make sure the directory exists.
+ test -f "$dirpart/$file" && continue
+ fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$file" : 'X\(//\)[^/]' \| \
+ X"$file" : 'X\(//\)$' \| \
+ X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir=$dirpart/$fdir
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ # echo "creating $dirpart/$file"
+ echo '# dummy' > "$dirpart/$file"
+ done
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/configure.ac b/tools/node_modules/expresso/deps/jscoverage/configure.ac
new file mode 100644
index 0000000..33aa915
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/configure.ac
@@ -0,0 +1,88 @@
+# configure.ac - configures jscoverage
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+AC_PREREQ(2.61)
+AC_INIT([jscoverage], [0.4])
+AM_INIT_AUTOMAKE([-Wall foreign])
+AC_CONFIG_SRCDIR([jscoverage.c])
+AC_CONFIG_HEADERS([config.h])
+AC_CANONICAL_HOST
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_CC_C99
+AC_PROG_CXX
+
+# Checks for libraries.
+AM_ICONV
+
+# Checks for header files.
+AC_CHECK_HEADERS([pthread.h])
+AC_CHECK_HEADERS([iconv.h])
+AC_CHECK_HEADERS([windows.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_BIGENDIAN
+
+# Checks for library functions.
+AC_CHECK_FUNCS([getaddrinfo gethostbyname_r inet_aton strndup vasprintf asprintf])
+AC_MSG_CHECKING([for MultiByteToWideChar])
+AC_LANG(C)
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[#include <windows.h>]],[[MultiByteToWideChar(0,0,0,0,0,0);]])],
+ [AC_DEFINE([HAVE_MULTIBYTETOWIDECHAR], [1], [Define to 1 if you have the `MultiByteToWideChar' function.])
+ jscoverage_have_multibytetowidechar=yes
+ AC_MSG_RESULT([yes])],
+ [jscoverage_have_multibytetowidechar=no
+ AC_MSG_RESULT([no])])
+
+AC_SUBST([XP_DEF])
+case "$host_os" in
+ mingw*)
+ XP_DEF='-DXP_WIN'
+ ;;
+ *)
+ XP_DEF='-DXP_UNIX'
+ ;;
+esac
+
+AC_SUBST([EXTRA_SOCKET_LIBS])
+AC_SUBST([EXTRA_THREAD_LIBS])
+AC_SUBST([EXTRA_TIMER_LIBS])
+case "$host_os" in
+ mingw*)
+ EXTRA_SOCKET_LIBS='-lws2_32'
+ EXTRA_THREAD_LIBS=''
+ EXTRA_TIMER_LIBS='-lwinmm'
+ ;;
+ *)
+ EXTRA_SOCKET_LIBS=''
+ EXTRA_THREAD_LIBS='-lpthread'
+ EXTRA_TIMER_LIBS=''
+ ;;
+esac
+
+if test "$am_cv_func_iconv" != yes && test "$jscoverage_have_multibytetowidechar" != yes
+then
+ echo -ne '\033@<:@1;31m'
+ AC_MSG_WARN([neither iconv nor Windows character encoding conversion functions found])
+ AC_MSG_WARN([only ASCII will be supported])
+ echo -ne '\033@<:@0m'
+fi
+
+AC_CONFIG_FILES([Makefile make-dist.sh make-bin-dist.sh tests/Makefile])
+AC_OUTPUT
diff --git a/tools/node_modules/expresso/deps/jscoverage/depcomp b/tools/node_modules/expresso/deps/jscoverage/depcomp
new file mode 100755
index 0000000..e5f9736
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/depcomp
@@ -0,0 +1,589 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2007-03-29.01
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software
+# Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by `PROGRAMS ARGS'.
+ object Object file output by `PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputing dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+ tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'. On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like `#:fec' to the end of the
+ # dependency line.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+ tr '
+' ' ' >> $depfile
+ echo >> $depfile
+
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' '
+' < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> $depfile
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts `$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form `foo.o: dependent.h'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ # The sourcefile does not contain any dependencies, so just
+ # store a dummy comment line, to avoid errors with the Makefile
+ # "include basename.Plo" scheme.
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+icc)
+ # Intel's C compiler understands `-MD -MF file'. However on
+ # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+ # ICC 7.0 will fill foo.d with something like
+ # foo.o: sub/foo.c
+ # foo.o: sub/foo.h
+ # which is wrong. We want:
+ # sub/foo.o: sub/foo.c
+ # sub/foo.o: sub/foo.h
+ # sub/foo.c:
+ # sub/foo.h:
+ # ICC 7.1 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using \ :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+ sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add `dependent.h:' lines.
+ sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in `foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+ test "x$dir" = "x$object" && dir=
+ base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+ if test "$libtool" = yes; then
+ # With Tru64 cc, shared objects can also be used to make a
+ # static library. This mechanism is used in libtool 1.4 series to
+ # handle both shared and static libraries in a single compilation.
+ # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+ #
+ # With libtool 1.5 this exception was removed, and libtool now
+ # generates 2 separate objects for the 2 libraries. These two
+ # compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
+ tmpdepfile2=$dir$base.o.d # libtool 1.5
+ tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
+ tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.o.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ tmpdepfile4=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -eq 0; then :
+ else
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+ # That's a tab and a space in the [].
+ sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+ else
+ echo "#dummy" > "$depfile"
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for `:'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+ "$@" $dashmflag |
+ sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no
+ for arg in "$@"; do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix="`echo $object | sed 's/^.*\././'`"
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test $1 != '--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove `-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E |
+ sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+ sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o,
+ # because we must use -o when running libtool.
+ "$@" || exit $?
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
+ echo " " >> "$depfile"
+ . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/demo.html b/tools/node_modules/expresso/deps/jscoverage/doc/demo.html
new file mode 100644
index 0000000..3d7729e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/demo.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - demo</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>Demo</h2>
+ <p>
+ Several examples of JSCoverage in action are available online. For each demo, click the "Summary" tab
+ after the JavaScript code in the "Browser" tab has executed. See the <a href="manual.html">manual</a>
+ for more information.
+ </p>
+ <dl>
+ <dt><a href="instrumented/jscoverage.html?index.html">Simple demo</a></dt>
+ <dd>A trivial demonstration of JSCoverage. Simply choose a number and then click the "Summary" tab.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-mochikit/jscoverage.html?tests/index.html">MochiKit test suite</a></dt>
+ <dd>The <a href="http://mochikit.com/">MochiKit</a> library test suite, instrumented using JSCoverage.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-jquery/jscoverage.html?test/index.html">jQuery test suite</a></dt>
+ <dd>The <a href="http://jquery.com/">jQuery</a> library test suite
+ (which uses the <a href="http://docs.jquery.com/QUnit">QUnit</a> test framework),
+ instrumented using JSCoverage.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-scriptaculous/jscoverage.html?test/run_unit_tests.html">script.aculo.us test suite</a></dt>
+ <dd>The <a href="http://script.aculo.us/">script.aculo.us</a> library test suite, instrumented using JSCoverage. (For this one you
+ will have to click the links in the left frame to run the tests.)</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-mootools/jscoverage.html?Specs/index.html">MooTools test suite</a></dt>
+ <dd>The <a href="http://mootools.net/">MooTools</a> library test suite
+ (which uses the <a href="http://jania.pe.kr/aw/moin.cgi/JSSpec">JSSpec</a> test framework),
+ instrumented using JSCoverage.</dd>
+ </dl>
+ <h3>Inverted mode</h3>
+ <p>
+ The following are examples of running JSCoverage in "inverted mode":
+ for each demo, click the "Coverage report" button after the JavaScript
+ code on the page has executed.
+ </p>
+ <dl>
+ <dt><a href="instrumented-inverted/index.html">Simple inverted mode demo</a></dt>
+ <dd>A trivial demonstration JSCoverage in "inverted mode".
+ Choose a number and then click the "Coverage report" button.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-jsunit/jsunit/testRunner.html?testPage=http://siliconforks.com/jscoverage/instrumented-jsunit/test.html&amp;autoRun=true">Simple JsUnit demo</a></dt>
+ <dd>A trivial demonstration of using JSCoverage with JsUnit. Once the
+ JsUnit unit tests have run, click the "Coverage report" button.</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-jsunit-self/jsunit/testRunner.html?testPage=http://siliconforks.com/jscoverage/instrumented-jsunit-self/jsunit/tests/jsUnitTestSuite.html&amp;autoRun=true">JsUnit test suite</a></dt>
+ <dd>JsUnit's own test suite, instrumented using JSCoverage. (Note: some versions of Safari seem to have trouble with the tests in the latest version of JsUnit.)</dd>
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-yui/tests/YUI.html">YUI test suite</a>
+ <dd>The <a href="http://developer.yahoo.com/yui/">YUI</a> library test suite
+ (which uses the <a href="http://developer.yahoo.com/yui/yuitest/">YUI Test</a> test framework),
+ instrumented using JSCoverage.
+ <dt><a href="http://siliconforks.com/jscoverage/instrumented-dojo/dojo/tests/runTests.html">Dojo test suite</a>
+ <dd>The <a href="http://dojotoolkit.org/">Dojo</a> library test suite
+ (which uses the <a href="http://dojotoolkit.org/book/dojo-book-0-9/part-4-meta-dojo/d-o-h-unit-testing"><acronym title="Dojo Objective Harness">D.O.H.</acronym></a> test framework),
+ instrumented using JSCoverage. (Note: Internet Explorer may generate errors for some tests in this suite.)
+ </dl>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li>Demo
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/doc.css b/tools/node_modules/expresso/deps/jscoverage/doc/doc.css
new file mode 100644
index 0000000..9ac26f4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/doc.css
@@ -0,0 +1,45 @@
+body {
+ margin-left: 3%;
+ margin-right: 3%;
+ font-family: sans-serif;
+}
+
+pre {
+ margin-left: 3%;
+ margin-right: 3%;
+ padding: 1em;
+ border: 1px dotted black;
+ background-color: #eee;
+}
+
+pre.sh_sourceCode {
+ background-color: #eee;
+}
+
+table {
+ margin-left: 3%;
+ margin-right: 3%;
+ border-collapse: collapse;
+}
+
+td {
+ vertical-align: top;
+ border-width: 0;
+ padding: 0;
+}
+
+td.arrow {
+ vertical-align: middle;
+ font-size: xx-large;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+td pre {
+ margin: 0;
+}
+
+img.icon {
+ vertical-align: middle;
+ border-width: 0px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html
new file mode 100644
index 0000000..be0f8ea
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+<button onclick='window.open("jscoverage.html");'>Coverage report</button>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js
new file mode 100644
index 0000000..f36a51d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-inverted/script.js
@@ -0,0 +1,20 @@
+function go(element) {
+ var message;
+ if (element.id === 'radio1') {
+ message = 'You selected the number 1.';
+ }
+ else if (element.id === 'radio2') {
+ message = 'You selected the number 2.';
+ }
+ else if (element.id === 'radio3') {
+ message = 'You selected the number 3.';
+ }
+ else if (element.id === 'radio4') {
+ message = 'You selected the number 4.';
+ }
+ var div = document.getElementById('request');
+ div.className = 'black';
+ div = document.getElementById('result');
+ div.innerHTML = '<p>' + message + '</p>';
+ div.innerHTML += '<p>If you are running the instrumented version of this program, you can click the "Coverage report" button to view a coverage report.</p>';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css
new file mode 100644
index 0000000..358bffe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/jsUnitStyle.css
@@ -0,0 +1,50 @@
+body {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ color: #000;
+ font-size: 0.8em;
+ background-color: #fff;
+}
+
+a:link, a:visited {
+ color: #00F;
+}
+
+a:hover {
+ color: #F00;
+}
+
+h1 {
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-weight: bold;
+ color: #039;
+ text-decoration: underline;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+.jsUnitTestResultSuccess {
+ color: #000;
+}
+
+.jsUnitTestResultNotSuccess {
+ color: #F00;
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme
new file mode 100644
index 0000000..f722210
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/css/readme
@@ -0,0 +1,10 @@
+this file is required due to differences in behavior between Mozilla/Opera
+and Internet Explorer.
+
+main-data.html calls kickOffTests() which calls top.testManager.start()
+in the top most frame. top.testManager.start() initializes the output
+frames using document.write and HTML containing a relative <link> to the
+jsUnitStyle.css file. In MSIE, the base href used to find the CSS file is
+that of the top level frame however in Mozilla/Opera the base href is
+that of main-data.html. This leads to not-found for the jsUnitStyle.css
+in Mozilla/Opera. Creating app/css/jsUnitStyle.css works around this problem.
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html
new file mode 100644
index 0000000..f9729dc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/emptyPage.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>emptyPage</title>
+</head>
+
+<body>
+</body>
+</html>
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js
new file mode 100644
index 0000000..438513e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitCore.js
@@ -0,0 +1,534 @@
+var JSUNIT_UNDEFINED_VALUE;
+var JSUNIT_VERSION = 2.2;
+var isTestPageLoaded = false;
+
+//hack for NS62 bug
+function jsUnitFixTop() {
+ var tempTop = top;
+ if (!tempTop) {
+ tempTop = window;
+ while (tempTop.parent) {
+ tempTop = tempTop.parent;
+ if (tempTop.top && tempTop.top.jsUnitTestSuite) {
+ tempTop = tempTop.top;
+ break;
+ }
+ }
+ }
+ try {
+ window.top = tempTop;
+ } catch (e) {
+ }
+}
+
+jsUnitFixTop();
+
+/**
+ + * A more functional typeof
+ + * @param Object o
+ + * @return String
+ + */
+function _trueTypeOf(something) {
+ var result = typeof something;
+ try {
+ switch (result) {
+ case 'string':
+ case 'boolean':
+ case 'number':
+ break;
+ case 'object':
+ case 'function':
+ switch (something.constructor)
+ {
+ case String:
+ result = 'String';
+ break;
+ case Boolean:
+ result = 'Boolean';
+ break;
+ case Number:
+ result = 'Number';
+ break;
+ case Array:
+ result = 'Array';
+ break;
+ case RegExp:
+ result = 'RegExp';
+ break;
+ case Function:
+ result = 'Function';
+ break;
+ default:
+ var m = something.constructor.toString().match(/function\s*([^( ]+)\(/);
+ if (m)
+ result = m[1];
+ else
+ break;
+ }
+ break;
+ }
+ }
+ finally {
+ result = result.substr(0, 1).toUpperCase() + result.substr(1);
+ return result;
+ }
+}
+
+function _displayStringForValue(aVar) {
+ var result = '<' + aVar + '>';
+ if (!(aVar === null || aVar === top.JSUNIT_UNDEFINED_VALUE)) {
+ result += ' (' + _trueTypeOf(aVar) + ')';
+ }
+ return result;
+}
+
+function fail(failureMessage) {
+ throw new JsUnitException("Call to fail()", failureMessage);
+}
+
+function error(errorMessage) {
+ var errorObject = new Object();
+ errorObject.description = errorMessage;
+ errorObject.stackTrace = getStackTrace();
+ throw errorObject;
+}
+
+function argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) {
+ return args.length == expectedNumberOfNonCommentArgs + 1;
+}
+
+function commentArg(expectedNumberOfNonCommentArgs, args) {
+ if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args))
+ return args[0];
+
+ return null;
+}
+
+function nonCommentArg(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) {
+ return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ?
+ args[desiredNonCommentArgIndex] :
+ args[desiredNonCommentArgIndex - 1];
+}
+
+function _validateArguments(expectedNumberOfNonCommentArgs, args) {
+ if (!( args.length == expectedNumberOfNonCommentArgs ||
+ (args.length == expectedNumberOfNonCommentArgs + 1 && typeof(args[0]) == 'string') ))
+ error('Incorrect arguments passed to assert function');
+}
+
+function _assert(comment, booleanValue, failureMessage) {
+ if (!booleanValue)
+ throw new JsUnitException(comment, failureMessage);
+}
+
+function assert() {
+ _validateArguments(1, arguments);
+ var booleanValue = nonCommentArg(1, 1, arguments);
+
+ if (typeof(booleanValue) != 'boolean')
+ error('Bad argument to assert(boolean)');
+
+ _assert(commentArg(1, arguments), booleanValue === true, 'Call to assert(boolean) with false');
+}
+
+function assertTrue() {
+ _validateArguments(1, arguments);
+ var booleanValue = nonCommentArg(1, 1, arguments);
+
+ if (typeof(booleanValue) != 'boolean')
+ error('Bad argument to assertTrue(boolean)');
+
+ _assert(commentArg(1, arguments), booleanValue === true, 'Call to assertTrue(boolean) with false');
+}
+
+function assertFalse() {
+ _validateArguments(1, arguments);
+ var booleanValue = nonCommentArg(1, 1, arguments);
+
+ if (typeof(booleanValue) != 'boolean')
+ error('Bad argument to assertFalse(boolean)');
+
+ _assert(commentArg(1, arguments), booleanValue === false, 'Call to assertFalse(boolean) with true');
+}
+
+function assertEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ _assert(commentArg(2, arguments), var1 === var2, 'Expected ' + _displayStringForValue(var1) + ' but was ' + _displayStringForValue(var2));
+}
+
+function assertNotEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ _assert(commentArg(2, arguments), var1 !== var2, 'Expected not to be ' + _displayStringForValue(var2));
+}
+
+function assertNull() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar === null, 'Expected ' + _displayStringForValue(null) + ' but was ' + _displayStringForValue(aVar));
+}
+
+function assertNotNull() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar !== null, 'Expected not to be ' + _displayStringForValue(null));
+}
+
+function assertUndefined() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar === top.JSUNIT_UNDEFINED_VALUE, 'Expected ' + _displayStringForValue(top.JSUNIT_UNDEFINED_VALUE) + ' but was ' + _displayStringForValue(aVar));
+}
+
+function assertNotUndefined() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), aVar !== top.JSUNIT_UNDEFINED_VALUE, 'Expected not to be ' + _displayStringForValue(top.JSUNIT_UNDEFINED_VALUE));
+}
+
+function assertNaN() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), isNaN(aVar), 'Expected NaN');
+}
+
+function assertNotNaN() {
+ _validateArguments(1, arguments);
+ var aVar = nonCommentArg(1, 1, arguments);
+ _assert(commentArg(1, arguments), !isNaN(aVar), 'Expected not NaN');
+}
+
+function assertObjectEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ var type;
+ var msg = commentArg(2, arguments)?commentArg(2, arguments):'';
+ var isSame = (var1 === var2);
+ //shortpath for references to same object
+ var isEqual = ( (type = _trueTypeOf(var1)) == _trueTypeOf(var2) );
+ if (isEqual && !isSame) {
+ switch (type) {
+ case 'String':
+ case 'Number':
+ isEqual = (var1 == var2);
+ break;
+ case 'Boolean':
+ case 'Date':
+ isEqual = (var1 === var2);
+ break;
+ case 'RegExp':
+ case 'Function':
+ isEqual = (var1.toString() === var2.toString());
+ break;
+ default: //Object | Array
+ var i;
+ if (isEqual = (var1.length === var2.length))
+ for (i in var1)
+ assertObjectEquals(msg + ' found nested ' + type + '@' + i + '\n', var1[i], var2[i]);
+ }
+ _assert(msg, isEqual, 'Expected ' + _displayStringForValue(var1) + ' but was ' + _displayStringForValue(var2));
+ }
+}
+
+assertArrayEquals = assertObjectEquals;
+
+function assertEvaluatesToTrue() {
+ _validateArguments(1, arguments);
+ var value = nonCommentArg(1, 1, arguments);
+ if (!value)
+ fail(commentArg(1, arguments));
+}
+
+function assertEvaluatesToFalse() {
+ _validateArguments(1, arguments);
+ var value = nonCommentArg(1, 1, arguments);
+ if (value)
+ fail(commentArg(1, arguments));
+}
+
+function assertHTMLEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ var var1Standardized = standardizeHTML(var1);
+ var var2Standardized = standardizeHTML(var2);
+
+ _assert(commentArg(2, arguments), var1Standardized === var2Standardized, 'Expected ' + _displayStringForValue(var1Standardized) + ' but was ' + _displayStringForValue(var2Standardized));
+}
+
+function assertHashEquals() {
+ _validateArguments(2, arguments);
+ var var1 = nonCommentArg(1, 2, arguments);
+ var var2 = nonCommentArg(2, 2, arguments);
+ for (var key in var1) {
+ assertNotUndefined("Expected hash had key " + key + " that was not found", var2[key]);
+ assertEquals(
+ "Value for key " + key + " mismatch - expected = " + var1[key] + ", actual = " + var2[key],
+ var1[key], var2[key]
+ );
+ }
+ for (var key in var2) {
+ assertNotUndefined("Actual hash had key " + key + " that was not expected", var1[key]);
+ }
+}
+
+function assertRoughlyEquals() {
+ _validateArguments(3, arguments);
+ var expected = nonCommentArg(1, 3, arguments);
+ var actual = nonCommentArg(2, 3, arguments);
+ var tolerance = nonCommentArg(3, 3, arguments);
+ assertTrue(
+ "Expected " + expected + ", but got " + actual + " which was more than " + tolerance + " away",
+ Math.abs(expected - actual) < tolerance
+ );
+}
+
+function assertContains() {
+ _validateArguments(2, arguments);
+ var contained = nonCommentArg(1, 2, arguments);
+ var container = nonCommentArg(2, 2, arguments);
+ assertTrue(
+ "Expected '" + container + "' to contain '" + contained + "'",
+ container.indexOf(contained) != -1
+ );
+}
+
+function standardizeHTML(html) {
+ var translator = document.createElement("DIV");
+ translator.innerHTML = html;
+ return translator.innerHTML;
+}
+
+function isLoaded() {
+ return isTestPageLoaded;
+}
+
+function setUp() {
+}
+
+function tearDown() {
+}
+
+function getFunctionName(aFunction) {
+ var regexpResult = aFunction.toString().match(/function(\s*)(\w*)/);
+ if (regexpResult && regexpResult.length >= 2 && regexpResult[2]) {
+ return regexpResult[2];
+ }
+ return 'anonymous';
+}
+
+function getStackTrace() {
+ var result = '';
+
+ if (typeof(arguments.caller) != 'undefined') { // IE, not ECMA
+ for (var a = arguments.caller; a != null; a = a.caller) {
+ result += '> ' + getFunctionName(a.callee) + '\n';
+ if (a.caller == a) {
+ result += '*';
+ break;
+ }
+ }
+ }
+ else { // Mozilla, not ECMA
+ // fake an exception so we can get Mozilla's error stack
+ var testExcp;
+ try
+ {
+ foo.bar;
+ }
+ catch(testExcp)
+ {
+ var stack = parseErrorStack(testExcp);
+ for (var i = 1; i < stack.length; i++)
+ {
+ result += '> ' + stack[i] + '\n';
+ }
+ }
+ }
+
+ return result;
+}
+
+function parseErrorStack(excp)
+{
+ var stack = [];
+ var name;
+
+ if (!excp || !excp.stack)
+ {
+ return stack;
+ }
+
+ var stacklist = excp.stack.split('\n');
+
+ for (var i = 0; i < stacklist.length - 1; i++)
+ {
+ var framedata = stacklist[i];
+
+ name = framedata.match(/^(\w*)/)[1];
+ if (!name) {
+ name = 'anonymous';
+ }
+
+ stack[stack.length] = name;
+ }
+ // remove top level anonymous functions to match IE
+
+ while (stack.length && stack[stack.length - 1] == 'anonymous')
+ {
+ stack.length = stack.length - 1;
+ }
+ return stack;
+}
+
+function JsUnitException(comment, message) {
+ this.isJsUnitException = true;
+ this.comment = comment;
+ this.jsUnitMessage = message;
+ this.stackTrace = getStackTrace();
+}
+
+function warn() {
+ if (top.tracer != null)
+ top.tracer.warn(arguments[0], arguments[1]);
+}
+
+function inform() {
+ if (top.tracer != null)
+ top.tracer.inform(arguments[0], arguments[1]);
+}
+
+function info() {
+ inform(arguments[0], arguments[1]);
+}
+
+function debug() {
+ if (top.tracer != null)
+ top.tracer.debug(arguments[0], arguments[1]);
+}
+
+function setJsUnitTracer(aJsUnitTracer) {
+ top.tracer = aJsUnitTracer;
+}
+
+function trim(str) {
+ if (str == null)
+ return null;
+
+ var startingIndex = 0;
+ var endingIndex = str.length - 1;
+
+ while (str.substring(startingIndex, startingIndex + 1) == ' ')
+ startingIndex++;
+
+ while (str.substring(endingIndex, endingIndex + 1) == ' ')
+ endingIndex--;
+
+ if (endingIndex < startingIndex)
+ return '';
+
+ return str.substring(startingIndex, endingIndex + 1);
+}
+
+function isBlank(str) {
+ return trim(str) == '';
+}
+
+// the functions push(anArray, anObject) and pop(anArray)
+// exist because the JavaScript Array.push(anObject) and Array.pop()
+// functions are not available in IE 5.0
+
+function push(anArray, anObject) {
+ anArray[anArray.length] = anObject;
+}
+function pop(anArray) {
+ if (anArray.length >= 1) {
+ delete anArray[anArray.length - 1];
+ anArray.length--;
+ }
+}
+
+function jsUnitGetParm(name)
+{
+ if (typeof(top.jsUnitParmHash[name]) != 'undefined')
+ {
+ return top.jsUnitParmHash[name];
+ }
+ return null;
+}
+
+if (top && typeof(top.xbDEBUG) != 'undefined' && top.xbDEBUG.on && top.testManager)
+{
+ top.xbDebugTraceObject('top.testManager.containerTestFrame', 'JSUnitException');
+ // asserts
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_displayStringForValue');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'error');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'argumentsIncludeComments');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'commentArg');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'nonCommentArg');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_validateArguments');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', '_assert');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assert');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertTrue');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertEquals');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotEquals');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNull');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotNull');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertUndefined');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotUndefined');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNaN');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'assertNotNaN');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'isLoaded');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'setUp');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'tearDown');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'getFunctionName');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'getStackTrace');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'warn');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'inform');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'debug');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'setJsUnitTracer');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'trim');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'isBlank');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'newOnLoadEvent');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'push');
+ top.xbDebugTraceFunction('top.testManager.containerTestFrame', 'pop');
+}
+
+function newOnLoadEvent() {
+ isTestPageLoaded = true;
+}
+
+function jsUnitSetOnLoad(windowRef, onloadHandler)
+{
+ var isKonqueror = navigator.userAgent.indexOf('Konqueror/') != -1 ||
+ navigator.userAgent.indexOf('Safari/') != -1;
+
+ if (typeof(windowRef.attachEvent) != 'undefined') {
+ // Internet Explorer, Opera
+ windowRef.attachEvent("onload", onloadHandler);
+ } else if (typeof(windowRef.addEventListener) != 'undefined' && !isKonqueror) {
+ // Mozilla, Konqueror
+ // exclude Konqueror due to load issues
+ windowRef.addEventListener("load", onloadHandler, false);
+ } else if (typeof(windowRef.document.addEventListener) != 'undefined' && !isKonqueror) {
+ // DOM 2 Events
+ // exclude Mozilla, Konqueror due to load issues
+ windowRef.document.addEventListener("load", onloadHandler, false);
+ } else if (typeof(windowRef.onload) != 'undefined' && windowRef.onload) {
+ windowRef.jsunit_original_onload = windowRef.onload;
+ windowRef.onload = function() {
+ windowRef.jsunit_original_onload();
+ onloadHandler();
+ };
+ } else {
+ // browsers that do not support windowRef.attachEvent or
+ // windowRef.addEventListener will override a page's own onload event
+ windowRef.onload = onloadHandler;
+ }
+}
+
+jsUnitSetOnLoad(window, newOnLoadEvent); \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js
new file mode 100644
index 0000000..99a4bf1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitMockTimeout.js
@@ -0,0 +1,81 @@
+// Mock setTimeout, clearTimeout
+// Contributed by Pivotal Computer Systems, www.pivotalsf.com
+
+var Clock = {
+ timeoutsMade: 0,
+ scheduledFunctions: {},
+ nowMillis: 0,
+ reset: function() {
+ this.scheduledFunctions = {};
+ this.nowMillis = 0;
+ this.timeoutsMade = 0;
+ },
+ tick: function(millis) {
+ var oldMillis = this.nowMillis;
+ var newMillis = oldMillis + millis;
+ this.runFunctionsWithinRange(oldMillis, newMillis);
+ this.nowMillis = newMillis;
+ },
+ runFunctionsWithinRange: function(oldMillis, nowMillis) {
+ var scheduledFunc;
+ var funcsToRun = [];
+ for (var timeoutKey in this.scheduledFunctions) {
+ scheduledFunc = this.scheduledFunctions[timeoutKey];
+ if (scheduledFunc != undefined &&
+ scheduledFunc.runAtMillis >= oldMillis &&
+ scheduledFunc.runAtMillis <= nowMillis) {
+ funcsToRun.push(scheduledFunc);
+ this.scheduledFunctions[timeoutKey] = undefined;
+ }
+ }
+
+ if (funcsToRun.length > 0) {
+ funcsToRun.sort(function(a, b) {
+ return a.runAtMillis - b.runAtMillis;
+ });
+ for (var i = 0; i < funcsToRun.length; ++i) {
+ try {
+ this.nowMillis = funcsToRun[i].runAtMillis;
+ funcsToRun[i].funcToCall();
+ if (funcsToRun[i].recurring) {
+ Clock.scheduleFunction(funcsToRun[i].timeoutKey,
+ funcsToRun[i].funcToCall,
+ funcsToRun[i].millis,
+ true);
+ }
+ } catch(e) {
+ }
+ }
+ this.runFunctionsWithinRange(oldMillis, nowMillis);
+ }
+ },
+ scheduleFunction: function(timeoutKey, funcToCall, millis, recurring) {
+ Clock.scheduledFunctions[timeoutKey] = {
+ runAtMillis: Clock.nowMillis + millis,
+ funcToCall: funcToCall,
+ recurring: recurring,
+ timeoutKey: timeoutKey,
+ millis: millis
+ };
+ }
+};
+
+function setTimeout(funcToCall, millis) {
+ Clock.timeoutsMade = Clock.timeoutsMade + 1;
+ Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, false);
+ return Clock.timeoutsMade;
+}
+
+function setInterval(funcToCall, millis) {
+ Clock.timeoutsMade = Clock.timeoutsMade + 1;
+ Clock.scheduleFunction(Clock.timeoutsMade, funcToCall, millis, true);
+ return Clock.timeoutsMade;
+}
+
+function clearTimeout(timeoutKey) {
+ Clock.scheduledFunctions[timeoutKey] = undefined;
+}
+
+function clearInterval(timeoutKey) {
+ Clock.scheduledFunctions[timeoutKey] = undefined;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js
new file mode 100644
index 0000000..7d5bf0f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestManager.js
@@ -0,0 +1,705 @@
+function jsUnitTestManager() {
+ this._windowForAllProblemMessages = null;
+
+ this.container = top.frames.testContainer
+ this.documentLoader = top.frames.documentLoader;
+ this.mainFrame = top.frames.mainFrame;
+
+ this.containerController = this.container.frames.testContainerController;
+ this.containerTestFrame = this.container.frames.testFrame;
+
+ var mainData = this.mainFrame.frames.mainData;
+
+ // form elements on mainData frame
+ this.testFileName = mainData.document.testRunnerForm.testFileName;
+ this.runButton = mainData.document.testRunnerForm.runButton;
+ this.traceLevel = mainData.document.testRunnerForm.traceLevel;
+ this.closeTraceWindowOnNewRun = mainData.document.testRunnerForm.closeTraceWindowOnNewRun;
+ this.timeout = mainData.document.testRunnerForm.timeout;
+ this.setUpPageTimeout = mainData.document.testRunnerForm.setUpPageTimeout;
+
+ // image output
+ this.progressBar = this.mainFrame.frames.mainProgress.document.progress;
+
+ this.problemsListField = this.mainFrame.frames.mainErrors.document.testRunnerForm.problemsList;
+ this.testCaseResultsField = this.mainFrame.frames.mainResults.document.resultsForm.testCases;
+ this.resultsTimeField = this.mainFrame.frames.mainResults.document.resultsForm.time;
+
+ // 'layer' output frames
+ this.uiFrames = new Object();
+ this.uiFrames.mainStatus = this.mainFrame.frames.mainStatus;
+
+ var mainCounts = this.mainFrame.frames.mainCounts;
+
+ this.uiFrames.mainCountsErrors = mainCounts.frames.mainCountsErrors;
+ this.uiFrames.mainCountsFailures = mainCounts.frames.mainCountsFailures;
+ this.uiFrames.mainCountsRuns = mainCounts.frames.mainCountsRuns;
+ this._baseURL = "";
+
+ this.setup();
+}
+
+// seconds to wait for each test page to load
+jsUnitTestManager.TESTPAGE_WAIT_SEC = 120;
+jsUnitTestManager.TIMEOUT_LENGTH = 20;
+
+// seconds to wait for setUpPage to complete
+jsUnitTestManager.SETUPPAGE_TIMEOUT = 120;
+
+// milliseconds to wait between polls on setUpPages
+jsUnitTestManager.SETUPPAGE_INTERVAL = 100;
+
+jsUnitTestManager.RESTORED_HTML_DIV_ID = "jsUnitRestoredHTML";
+
+jsUnitTestManager.prototype.setup = function () {
+ this.totalCount = 0;
+ this.errorCount = 0;
+ this.failureCount = 0;
+ this._suiteStack = Array();
+
+ var initialSuite = new top.jsUnitTestSuite();
+ push(this._suiteStack, initialSuite);
+}
+
+jsUnitTestManager.prototype.start = function () {
+ this._baseURL = this.resolveUserEnteredTestFileName();
+ var firstQuery = this._baseURL.indexOf("?");
+ if (firstQuery >= 0) {
+ this._baseURL = this._baseURL.substring(0, firstQuery);
+ }
+ var lastSlash = this._baseURL.lastIndexOf("/");
+ var lastRevSlash = this._baseURL.lastIndexOf("\\");
+ if (lastRevSlash > lastSlash) {
+ lastSlash = lastRevSlash;
+ }
+ if (lastSlash > 0) {
+ this._baseURL = this._baseURL.substring(0, lastSlash + 1);
+ }
+
+ this._timeRunStarted = new Date();
+ this.initialize();
+ setTimeout('top.testManager._nextPage();', jsUnitTestManager.TIMEOUT_LENGTH);
+}
+
+jsUnitTestManager.prototype.getBaseURL = function () {
+ return this._baseURL;
+}
+
+jsUnitTestManager.prototype.doneLoadingPage = function (pageName) {
+ //this.containerTestFrame.setTracer(top.tracer);
+ this._testFileName = pageName;
+ if (this.isTestPageSuite())
+ this._handleNewSuite();
+ else
+ {
+ this._testIndex = 0;
+ this._testsInPage = this.getTestFunctionNames();
+ this._numberOfTestsInPage = this._testsInPage.length;
+ this._runTest();
+ }
+}
+
+jsUnitTestManager.prototype._handleNewSuite = function () {
+ var allegedSuite = this.containerTestFrame.suite();
+ if (allegedSuite.isjsUnitTestSuite) {
+ var newSuite = allegedSuite.clone();
+ if (newSuite.containsTestPages())
+ push(this._suiteStack, newSuite);
+ this._nextPage();
+ }
+ else {
+ this.fatalError('Invalid test suite in file ' + this._testFileName);
+ this.abort();
+ }
+}
+
+jsUnitTestManager.prototype._runTest = function () {
+ if (this._testIndex + 1 > this._numberOfTestsInPage)
+ {
+ // execute tearDownPage *synchronously*
+ // (unlike setUpPage which is asynchronous)
+ if (typeof this.containerTestFrame.tearDownPage == 'function') {
+ this.containerTestFrame.tearDownPage();
+ }
+
+ this._nextPage();
+ return;
+ }
+
+ if (this._testIndex == 0) {
+ this.storeRestoredHTML();
+ if (typeof(this.containerTestFrame.setUpPage) == 'function') {
+ // first test for this page and a setUpPage is defined
+ if (typeof(this.containerTestFrame.setUpPageStatus) == 'undefined') {
+ // setUpPage() not called yet, so call it
+ this.containerTestFrame.setUpPageStatus = false;
+ this.containerTestFrame.startTime = new Date();
+ this.containerTestFrame.setUpPage();
+ // try test again later
+ setTimeout('top.testManager._runTest()', jsUnitTestManager.SETUPPAGE_INTERVAL);
+ return;
+ }
+
+ if (this.containerTestFrame.setUpPageStatus != 'complete') {
+ top.status = 'setUpPage not completed... ' + this.containerTestFrame.setUpPageStatus + ' ' + (new Date());
+ if ((new Date() - this.containerTestFrame.startTime) / 1000 > this.getsetUpPageTimeout()) {
+ this.fatalError('setUpPage timed out without completing.');
+ if (!this.userConfirm('Retry Test Run?')) {
+ this.abort();
+ return;
+ }
+ this.containerTestFrame.startTime = (new Date());
+ }
+ // try test again later
+ setTimeout('top.testManager._runTest()', jsUnitTestManager.SETUPPAGE_INTERVAL);
+ return;
+ }
+ }
+ }
+
+ top.status = '';
+ // either not first test, or no setUpPage defined, or setUpPage completed
+ this.executeTestFunction(this._testsInPage[this._testIndex]);
+ this.totalCount++;
+ this.updateProgressIndicators();
+ this._testIndex++;
+ setTimeout('top.testManager._runTest()', jsUnitTestManager.TIMEOUT_LENGTH);
+}
+
+jsUnitTestManager.prototype._done = function () {
+ var secondsSinceRunBegan = (new Date() - this._timeRunStarted) / 1000;
+ this.setStatus('Done (' + secondsSinceRunBegan + ' seconds)');
+ this._cleanUp();
+ if (top.shouldSubmitResults()) {
+ this.resultsTimeField.value = secondsSinceRunBegan;
+ top.submitResults();
+ }
+}
+
+jsUnitTestManager.prototype._nextPage = function () {
+ this._restoredHTML = null;
+ if (this._currentSuite().hasMorePages()) {
+ this.loadPage(this._currentSuite().nextPage());
+ }
+ else {
+ pop(this._suiteStack);
+ if (this._currentSuite() == null)
+ this._done();
+ else
+ this._nextPage();
+ }
+}
+
+jsUnitTestManager.prototype._currentSuite = function () {
+ var suite = null;
+
+ if (this._suiteStack && this._suiteStack.length > 0)
+ suite = this._suiteStack[this._suiteStack.length - 1];
+
+ return suite;
+}
+
+jsUnitTestManager.prototype.calculateProgressBarProportion = function () {
+ if (this.totalCount == 0)
+ return 0;
+ var currentDivisor = 1;
+ var result = 0;
+
+ for (var i = 0; i < this._suiteStack.length; i++) {
+ var aSuite = this._suiteStack[i];
+ currentDivisor *= aSuite.testPages.length;
+ result += (aSuite.pageIndex - 1) / currentDivisor;
+ }
+ result += (this._testIndex + 1) / (this._numberOfTestsInPage * currentDivisor);
+ return result;
+}
+
+jsUnitTestManager.prototype._cleanUp = function () {
+ this.containerController.setTestPage('./app/emptyPage.html');
+ this.finalize();
+ top.tracer.finalize();
+}
+
+jsUnitTestManager.prototype.abort = function () {
+ this.setStatus('Aborted');
+ this._cleanUp();
+}
+
+jsUnitTestManager.prototype.getTimeout = function () {
+ var result = jsUnitTestManager.TESTPAGE_WAIT_SEC;
+ try {
+ result = eval(this.timeout.value);
+ }
+ catch (e) {
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype.getsetUpPageTimeout = function () {
+ var result = jsUnitTestManager.SETUPPAGE_TIMEOUT;
+ try {
+ result = eval(this.setUpPageTimeout.value);
+ }
+ catch (e) {
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype.isTestPageSuite = function () {
+ var result = false;
+ if (typeof(this.containerTestFrame.suite) == 'function')
+ {
+ result = true;
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype.getTestFunctionNames = function () {
+ var testFrame = this.containerTestFrame;
+ var testFunctionNames = new Array();
+ var i;
+
+ if (testFrame && typeof(testFrame.exposeTestFunctionNames) == 'function')
+ return testFrame.exposeTestFunctionNames();
+
+ if (testFrame &&
+ testFrame.document &&
+ typeof(testFrame.document.scripts) != 'undefined' &&
+ testFrame.document.scripts.length > 0) { // IE5 and up
+ var scriptsInTestFrame = testFrame.document.scripts;
+
+ for (i = 0; i < scriptsInTestFrame.length; i++) {
+ var someNames = this._extractTestFunctionNamesFromScript(scriptsInTestFrame[i]);
+ if (someNames)
+ testFunctionNames = testFunctionNames.concat(someNames);
+ }
+ }
+ else {
+ for (i in testFrame) {
+ if (i.substring(0, 4) == 'test' && typeof(testFrame[i]) == 'function')
+ push(testFunctionNames, i);
+ }
+ }
+ return testFunctionNames;
+}
+
+jsUnitTestManager.prototype._extractTestFunctionNamesFromScript = function (aScript) {
+ var result;
+ var remainingScriptToInspect = aScript.text;
+ var currentIndex = this._indexOfTestFunctionIn(remainingScriptToInspect);
+ while (currentIndex != -1) {
+ if (!result)
+ result = new Array();
+
+ var fragment = remainingScriptToInspect.substring(currentIndex, remainingScriptToInspect.length);
+ result = result.concat(fragment.substring('function '.length, fragment.indexOf('(')));
+ remainingScriptToInspect = remainingScriptToInspect.substring(currentIndex + 12, remainingScriptToInspect.length);
+ currentIndex = this._indexOfTestFunctionIn(remainingScriptToInspect);
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype._indexOfTestFunctionIn = function (string) {
+ return string.indexOf('function test');
+}
+
+jsUnitTestManager.prototype.loadPage = function (testFileName) {
+ this._testFileName = testFileName;
+ this._loadAttemptStartTime = new Date();
+ this.setStatus('Opening Test Page "' + this._testFileName + '"');
+ this.containerController.setTestPage(this._testFileName);
+ this._callBackWhenPageIsLoaded();
+}
+
+jsUnitTestManager.prototype._callBackWhenPageIsLoaded = function () {
+ if ((new Date() - this._loadAttemptStartTime) / 1000 > this.getTimeout()) {
+ this.fatalError('Reading Test Page ' + this._testFileName + ' timed out.\nMake sure that the file exists and is a Test Page.');
+ if (this.userConfirm('Retry Test Run?')) {
+ this.loadPage(this._testFileName);
+ return;
+ } else {
+ this.abort();
+ return;
+ }
+ }
+ if (!this._isTestFrameLoaded()) {
+ setTimeout('top.testManager._callBackWhenPageIsLoaded();', jsUnitTestManager.TIMEOUT_LENGTH);
+ return;
+ }
+ this.doneLoadingPage(this._testFileName);
+}
+
+jsUnitTestManager.prototype._isTestFrameLoaded = function () {
+ try {
+ return this.containerController.isPageLoaded();
+ }
+ catch (e) {
+ }
+ return false;
+}
+
+jsUnitTestManager.prototype.executeTestFunction = function (functionName) {
+ this._testFunctionName = functionName;
+ this.setStatus('Running test "' + this._testFunctionName + '"');
+ var excep = null;
+ var timeBefore = new Date();
+ try {
+ if (this._restoredHTML)
+ top.testContainer.testFrame.document.getElementById(jsUnitTestManager.RESTORED_HTML_DIV_ID).innerHTML = this._restoredHTML;
+ if (this.containerTestFrame.setUp !== JSUNIT_UNDEFINED_VALUE)
+ this.containerTestFrame.setUp();
+ this.containerTestFrame[this._testFunctionName]();
+ }
+ catch (e1) {
+ excep = e1;
+ }
+ finally {
+ try {
+ if (this.containerTestFrame.tearDown !== JSUNIT_UNDEFINED_VALUE)
+ this.containerTestFrame.tearDown();
+ }
+ catch (e2) {
+ //Unlike JUnit, only assign a tearDown exception to excep if there is not already an exception from the test body
+ if (excep == null)
+ excep = e2;
+ }
+ }
+ var timeTaken = (new Date() - timeBefore) / 1000;
+ if (excep != null)
+ this._handleTestException(excep);
+ var serializedTestCaseString = this._currentTestFunctionNameWithTestPageName(true) + "|" + timeTaken + "|";
+ if (excep == null)
+ serializedTestCaseString += "S||";
+ else {
+ if (typeof(excep.isJsUnitException) != 'undefined' && excep.isJsUnitException)
+ serializedTestCaseString += "F|";
+ else {
+ serializedTestCaseString += "E|";
+ }
+ serializedTestCaseString += this._problemDetailMessageFor(excep);
+ }
+ this._addOption(this.testCaseResultsField,
+ serializedTestCaseString,
+ serializedTestCaseString);
+}
+
+jsUnitTestManager.prototype._currentTestFunctionNameWithTestPageName = function(useFullyQualifiedTestPageName) {
+ var testURL = this.containerTestFrame.location.href;
+ var testQuery = testURL.indexOf("?");
+ if (testQuery >= 0) {
+ testURL = testURL.substring(0, testQuery);
+ }
+ if (!useFullyQualifiedTestPageName) {
+ if (testURL.substring(0, this._baseURL.length) == this._baseURL)
+ testURL = testURL.substring(this._baseURL.length);
+ }
+ return testURL + ':' + this._testFunctionName;
+}
+
+jsUnitTestManager.prototype._addOption = function(listField, problemValue, problemMessage) {
+ if (typeof(listField.ownerDocument) != 'undefined'
+ && typeof(listField.ownerDocument.createElement) != 'undefined') {
+ // DOM Level 2 HTML method.
+ // this is required for Opera 7 since appending to the end of the
+ // options array does not work, and adding an Option created by new Option()
+ // and appended by listField.options.add() fails due to WRONG_DOCUMENT_ERR
+ var problemDocument = listField.ownerDocument;
+ var errOption = problemDocument.createElement('option');
+ errOption.setAttribute('value', problemValue);
+ errOption.appendChild(problemDocument.createTextNode(problemMessage));
+ listField.appendChild(errOption);
+ }
+ else {
+ // new Option() is DOM 0
+ errOption = new Option(problemMessage, problemValue);
+ if (typeof(listField.add) != 'undefined') {
+ // DOM 2 HTML
+ listField.add(errOption, null);
+ }
+ else if (typeof(listField.options.add) != 'undefined') {
+ // DOM 0
+ listField.options.add(errOption, null);
+ }
+ else {
+ // DOM 0
+ listField.options[listField.length] = errOption;
+ }
+ }
+}
+
+jsUnitTestManager.prototype._handleTestException = function (excep) {
+ var problemMessage = this._currentTestFunctionNameWithTestPageName(false) + ' ';
+ var errOption;
+ if (typeof(excep.isJsUnitException) == 'undefined' || !excep.isJsUnitException) {
+ problemMessage += 'had an error';
+ this.errorCount++;
+ }
+ else {
+ problemMessage += 'failed';
+ this.failureCount++;
+ }
+ var listField = this.problemsListField;
+ this._addOption(listField,
+ this._problemDetailMessageFor(excep),
+ problemMessage);
+}
+
+jsUnitTestManager.prototype._problemDetailMessageFor = function (excep) {
+ var result = null;
+ if (typeof(excep.isJsUnitException) != 'undefined' && excep.isJsUnitException) {
+ result = '';
+ if (excep.comment != null)
+ result += ('"' + excep.comment + '"\n');
+
+ result += excep.jsUnitMessage;
+
+ if (excep.stackTrace)
+ result += '\n\nStack trace follows:\n' + excep.stackTrace;
+ }
+ else {
+ result = 'Error message is:\n"';
+ result +=
+ (typeof(excep.description) == 'undefined') ?
+ excep :
+ excep.description;
+ result += '"';
+ if (typeof(excep.stack) != 'undefined') // Mozilla only
+ result += '\n\nStack trace follows:\n' + excep.stack;
+ }
+ return result;
+}
+
+jsUnitTestManager.prototype._setTextOnLayer = function (layerName, str) {
+ try {
+ var content;
+ if (content = this.uiFrames[layerName].document.getElementById('content'))
+ content.innerHTML = str;
+ else
+ throw 'No content div found.';
+ }
+ catch (e) {
+ var html = '';
+ html += '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
+ html += '<html><head><link rel="stylesheet" type="text/css" href="css/jsUnitStyle.css"><\/head>';
+ html += '<body><div id="content">';
+ html += str;
+ html += '<\/div><\/body>';
+ html += '<\/html>';
+ this.uiFrames[layerName].document.write(html);
+ this.uiFrames[layerName].document.close();
+ }
+}
+
+jsUnitTestManager.prototype.setStatus = function (str) {
+ this._setTextOnLayer('mainStatus', '<b>Status:<\/b> ' + str);
+}
+
+jsUnitTestManager.prototype._setErrors = function (n) {
+ this._setTextOnLayer('mainCountsErrors', '<b>Errors: <\/b>' + n);
+}
+
+jsUnitTestManager.prototype._setFailures = function (n) {
+ this._setTextOnLayer('mainCountsFailures', '<b>Failures:<\/b> ' + n);
+}
+
+jsUnitTestManager.prototype._setTotal = function (n) {
+ this._setTextOnLayer('mainCountsRuns', '<b>Runs:<\/b> ' + n);
+}
+
+jsUnitTestManager.prototype._setProgressBarImage = function (imgName) {
+ this.progressBar.src = imgName;
+}
+
+jsUnitTestManager.prototype._setProgressBarWidth = function (w) {
+ this.progressBar.width = w;
+}
+
+jsUnitTestManager.prototype.updateProgressIndicators = function () {
+ this._setTotal(this.totalCount);
+ this._setErrors(this.errorCount);
+ this._setFailures(this.failureCount);
+ this._setProgressBarWidth(300 * this.calculateProgressBarProportion());
+
+ if (this.errorCount > 0 || this.failureCount > 0)
+ this._setProgressBarImage('../images/red.gif');
+ else
+ this._setProgressBarImage('../images/green.gif');
+}
+
+jsUnitTestManager.prototype.showMessageForSelectedProblemTest = function () {
+ var problemTestIndex = this.problemsListField.selectedIndex;
+ if (problemTestIndex != -1)
+ this.fatalError(this.problemsListField[problemTestIndex].value);
+}
+
+jsUnitTestManager.prototype.showMessagesForAllProblemTests = function () {
+ if (this.problemsListField.length == 0)
+ return;
+
+ try {
+ if (this._windowForAllProblemMessages && !this._windowForAllProblemMessages.closed)
+ this._windowForAllProblemMessages.close();
+ }
+ catch(e) {
+ }
+
+ this._windowForAllProblemMessages = window.open('', '', 'width=600, height=350,status=no,resizable=yes,scrollbars=yes');
+ var resDoc = this._windowForAllProblemMessages.document;
+ resDoc.write('<html><head><link rel="stylesheet" href="../css/jsUnitStyle.css"><title>Tests with problems - JsUnit<\/title><head><body>');
+ resDoc.write('<p class="jsUnitSubHeading">Tests with problems (' + this.problemsListField.length + ' total) - JsUnit<\/p>');
+ resDoc.write('<p class="jsUnitSubSubHeading"><i>Running on ' + navigator.userAgent + '</i></p>');
+ for (var i = 0; i < this.problemsListField.length; i++)
+ {
+ resDoc.write('<p class="jsUnitDefault">');
+ resDoc.write('<b>' + (i + 1) + '. ');
+ resDoc.write(this.problemsListField[i].text);
+ resDoc.write('<\/b><\/p><p><pre>');
+ resDoc.write(this._makeHTMLSafe(this.problemsListField[i].value));
+ resDoc.write('<\/pre><\/p>');
+ }
+
+ resDoc.write('<\/body><\/html>');
+ resDoc.close();
+}
+
+jsUnitTestManager.prototype._makeHTMLSafe = function (string) {
+ string = string.replace(/&/g, '&amp;');
+ string = string.replace(/</g, '&lt;');
+ string = string.replace(/>/g, '&gt;');
+ return string;
+}
+
+jsUnitTestManager.prototype._clearProblemsList = function () {
+ var listField = this.problemsListField;
+ var initialLength = listField.options.length;
+
+ for (var i = 0; i < initialLength; i++)
+ listField.remove(0);
+}
+
+jsUnitTestManager.prototype.initialize = function () {
+ this.setStatus('Initializing...');
+ this._setRunButtonEnabled(false);
+ this._clearProblemsList();
+ this.updateProgressIndicators();
+ this.setStatus('Done initializing');
+}
+
+jsUnitTestManager.prototype.finalize = function () {
+ this._setRunButtonEnabled(true);
+}
+
+jsUnitTestManager.prototype._setRunButtonEnabled = function (b) {
+ this.runButton.disabled = !b;
+}
+
+jsUnitTestManager.prototype.getTestFileName = function () {
+ var rawEnteredFileName = this.testFileName.value;
+ var result = rawEnteredFileName;
+
+ while (result.indexOf('\\') != -1)
+ result = result.replace('\\', '/');
+
+ return result;
+}
+
+jsUnitTestManager.prototype.getTestFunctionName = function () {
+ return this._testFunctionName;
+}
+
+jsUnitTestManager.prototype.resolveUserEnteredTestFileName = function (rawText) {
+ var userEnteredTestFileName = top.testManager.getTestFileName();
+
+ // only test for file:// since Opera uses a different format
+ if (userEnteredTestFileName.indexOf('http://') == 0 || userEnteredTestFileName.indexOf('https://') == 0 || userEnteredTestFileName.indexOf('file://') == 0)
+ return userEnteredTestFileName;
+
+ return getTestFileProtocol() + this.getTestFileName();
+}
+
+jsUnitTestManager.prototype.storeRestoredHTML = function () {
+ if (document.getElementById && top.testContainer.testFrame.document.getElementById(jsUnitTestManager.RESTORED_HTML_DIV_ID))
+ this._restoredHTML = top.testContainer.testFrame.document.getElementById(jsUnitTestManager.RESTORED_HTML_DIV_ID).innerHTML;
+}
+
+jsUnitTestManager.prototype.fatalError = function(aMessage) {
+ if (top.shouldSubmitResults())
+ this.setStatus(aMessage);
+ else
+ alert(aMessage);
+}
+
+jsUnitTestManager.prototype.userConfirm = function(aMessage) {
+ if (top.shouldSubmitResults())
+ return false;
+ else
+ return confirm(aMessage);
+}
+
+function getTestFileProtocol() {
+ return getDocumentProtocol();
+}
+
+function getDocumentProtocol() {
+ var protocol = top.document.location.protocol;
+
+ if (protocol == "file:")
+ return "file:///";
+
+ if (protocol == "http:")
+ return "http://";
+
+ if (protocol == 'https:')
+ return 'https://';
+
+ if (protocol == "chrome:")
+ return "chrome://";
+
+ return null;
+}
+
+function browserSupportsReadingFullPathFromFileField() {
+ return !isOpera() && !isIE7();
+}
+
+function isOpera() {
+ return navigator.userAgent.toLowerCase().indexOf("opera") != -1;
+}
+
+function isIE7() {
+ return navigator.userAgent.toLowerCase().indexOf("msie 7") != -1;
+}
+
+function isBeingRunOverHTTP() {
+ return getDocumentProtocol() == "http://";
+}
+
+function getWebserver() {
+ if (isBeingRunOverHTTP()) {
+ var myUrl = location.href;
+ var myUrlWithProtocolStripped = myUrl.substring(myUrl.indexOf("/") + 2);
+ return myUrlWithProtocolStripped.substring(0, myUrlWithProtocolStripped.indexOf("/"));
+ }
+ return null;
+}
+
+// the functions push(anArray, anObject) and pop(anArray)
+// exist because the JavaScript Array.push(anObject) and Array.pop()
+// functions are not available in IE 5.0
+
+function push(anArray, anObject) {
+ anArray[anArray.length] = anObject;
+}
+
+function pop(anArray) {
+ if (anArray.length >= 1) {
+ delete anArray[anArray.length - 1];
+ anArray.length--;
+ }
+}
+
+if (xbDEBUG.on) {
+ xbDebugTraceObject('window', 'jsUnitTestManager');
+ xbDebugTraceFunction('window', 'getTestFileProtocol');
+ xbDebugTraceFunction('window', 'getDocumentProtocol');
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js
new file mode 100644
index 0000000..3f3eb8c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTestSuite.js
@@ -0,0 +1,44 @@
+function jsUnitTestSuite() {
+ this.isjsUnitTestSuite = true;
+ this.testPages = Array();
+ this.pageIndex = 0;
+}
+
+jsUnitTestSuite.prototype.addTestPage = function (pageName)
+{
+ this.testPages[this.testPages.length] = pageName;
+}
+
+jsUnitTestSuite.prototype.addTestSuite = function (suite)
+{
+ for (var i = 0; i < suite.testPages.length; i++)
+ this.addTestPage(suite.testPages[i]);
+}
+
+jsUnitTestSuite.prototype.containsTestPages = function ()
+{
+ return this.testPages.length > 0;
+}
+
+jsUnitTestSuite.prototype.nextPage = function ()
+{
+ return this.testPages[this.pageIndex++];
+}
+
+jsUnitTestSuite.prototype.hasMorePages = function ()
+{
+ return this.pageIndex < this.testPages.length;
+}
+
+jsUnitTestSuite.prototype.clone = function ()
+{
+ var clone = new jsUnitTestSuite();
+ clone.testPages = this.testPages;
+ return clone;
+}
+
+if (xbDEBUG.on)
+{
+ xbDebugTraceObject('window', 'jsUnitTestSuite');
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js
new file mode 100644
index 0000000..b120e39
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitTracer.js
@@ -0,0 +1,102 @@
+var TRACE_LEVEL_NONE = new JsUnitTraceLevel(0, null);
+var TRACE_LEVEL_WARNING = new JsUnitTraceLevel(1, "#FF0000");
+var TRACE_LEVEL_INFO = new JsUnitTraceLevel(2, "#009966");
+var TRACE_LEVEL_DEBUG = new JsUnitTraceLevel(3, "#0000FF");
+
+function JsUnitTracer(testManager) {
+ this._testManager = testManager;
+ this._traceWindow = null;
+ this.popupWindowsBlocked = false;
+}
+
+JsUnitTracer.prototype.initialize = function() {
+ if (this._traceWindow != null && top.testManager.closeTraceWindowOnNewRun.checked)
+ this._traceWindow.close();
+ this._traceWindow = null;
+}
+
+JsUnitTracer.prototype.finalize = function() {
+ if (this._traceWindow != null) {
+ this._traceWindow.document.write('<\/body>\n<\/html>');
+ this._traceWindow.document.close();
+ }
+}
+
+JsUnitTracer.prototype.warn = function() {
+ this._trace(arguments[0], arguments[1], TRACE_LEVEL_WARNING);
+}
+
+JsUnitTracer.prototype.inform = function() {
+ this._trace(arguments[0], arguments[1], TRACE_LEVEL_INFO);
+}
+
+JsUnitTracer.prototype.debug = function() {
+ this._trace(arguments[0], arguments[1], TRACE_LEVEL_DEBUG);
+}
+
+JsUnitTracer.prototype._trace = function(message, value, traceLevel) {
+ if (!top.shouldSubmitResults() && this._getChosenTraceLevel().matches(traceLevel)) {
+ var traceString = message;
+ if (value)
+ traceString += ': ' + value;
+ var prefix = this._testManager.getTestFileName() + ":" +
+ this._testManager.getTestFunctionName() + " - ";
+ this._writeToTraceWindow(prefix, traceString, traceLevel);
+ }
+}
+
+JsUnitTracer.prototype._getChosenTraceLevel = function() {
+ var levelNumber = eval(top.testManager.traceLevel.value);
+ return traceLevelByLevelNumber(levelNumber);
+}
+
+JsUnitTracer.prototype._writeToTraceWindow = function(prefix, traceString, traceLevel) {
+ var htmlToAppend = '<p class="jsUnitDefault">' + prefix + '<font color="' + traceLevel.getColor() + '">' + traceString + '</font><\/p>\n';
+ this._getTraceWindow().document.write(htmlToAppend);
+}
+
+JsUnitTracer.prototype._getTraceWindow = function() {
+ if (this._traceWindow == null && !top.shouldSubmitResults() && !this.popupWindowsBlocked) {
+ this._traceWindow = window.open('', '', 'width=600, height=350,status=no,resizable=yes,scrollbars=yes');
+ if (!this._traceWindow)
+ this.popupWindowsBlocked = true;
+ else {
+ var resDoc = this._traceWindow.document;
+ resDoc.write('<html>\n<head>\n<link rel="stylesheet" href="css/jsUnitStyle.css">\n<title>Tracing - JsUnit<\/title>\n<head>\n<body>');
+ resDoc.write('<h2>Tracing - JsUnit<\/h2>\n');
+ resDoc.write('<p class="jsUnitDefault"><i>(Traces are color coded: ');
+ resDoc.write('<font color="' + TRACE_LEVEL_WARNING.getColor() + '">Warning</font> - ');
+ resDoc.write('<font color="' + TRACE_LEVEL_INFO.getColor() + '">Information</font> - ');
+ resDoc.write('<font color="' + TRACE_LEVEL_DEBUG.getColor() + '">Debug</font>');
+ resDoc.write(')</i></p>');
+ }
+ }
+ return this._traceWindow;
+}
+
+if (xbDEBUG.on) {
+ xbDebugTraceObject('window', 'JsUnitTracer');
+}
+
+function JsUnitTraceLevel(levelNumber, color) {
+ this._levelNumber = levelNumber;
+ this._color = color;
+}
+
+JsUnitTraceLevel.prototype.matches = function(anotherTraceLevel) {
+ return this._levelNumber >= anotherTraceLevel._levelNumber;
+}
+
+JsUnitTraceLevel.prototype.getColor = function() {
+ return this._color;
+}
+
+function traceLevelByLevelNumber(levelNumber) {
+ switch (levelNumber) {
+ case 0: return TRACE_LEVEL_NONE;
+ case 1: return TRACE_LEVEL_WARNING;
+ case 2: return TRACE_LEVEL_INFO;
+ case 3: return TRACE_LEVEL_DEBUG;
+ }
+ return null;
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js
new file mode 100644
index 0000000..41c8862
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/jsUnitVersionCheck.js
@@ -0,0 +1,59 @@
+var versionRequest;
+
+function isOutOfDate(newVersionNumber) {
+ return JSUNIT_VERSION < newVersionNumber;
+}
+
+function sendRequestForLatestVersion(url) {
+ versionRequest = createXmlHttpRequest();
+ if (versionRequest) {
+ versionRequest.onreadystatechange = requestStateChanged;
+ versionRequest.open("GET", url, true);
+ versionRequest.send(null);
+ }
+}
+
+function createXmlHttpRequest() {
+ if (window.XMLHttpRequest)
+ return new XMLHttpRequest();
+ else if (window.ActiveXObject)
+ return new ActiveXObject("Microsoft.XMLHTTP");
+}
+
+function requestStateChanged() {
+ if (versionRequest && versionRequest.readyState == 4) {
+ if (versionRequest.status == 200) {
+ var latestVersion = versionRequest.responseText;
+ if (isOutOfDate(latestVersion))
+ versionNotLatest(latestVersion);
+ else
+ versionLatest();
+ } else
+ versionCheckError();
+ }
+}
+
+function checkForLatestVersion(url) {
+ setLatestVersionDivHTML("Checking for newer version...");
+ try {
+ sendRequestForLatestVersion(url);
+ } catch (e) {
+ setLatestVersionDivHTML("An error occurred while checking for a newer version: " + e.message);
+ }
+}
+
+function versionNotLatest(latestVersion) {
+ setLatestVersionDivHTML('<font color="red">A newer version of JsUnit, version ' + latestVersion + ', is available.</font>');
+}
+
+function versionLatest() {
+ setLatestVersionDivHTML("You are running the latest version of JsUnit.");
+}
+
+function setLatestVersionDivHTML(string) {
+ document.getElementById("versionCheckDiv").innerHTML = string;
+}
+
+function versionCheckError() {
+ setLatestVersionDivHTML("An error occurred while checking for a newer version.");
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html
new file mode 100644
index 0000000..ca726b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-errors.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Errors:</b> 0</div>
+</body>
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html
new file mode 100644
index 0000000..861c78b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-failures.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Failures:</b> 0</div>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html
new file mode 100644
index 0000000..5429f8f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts-runs.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Runs:</b> 0</div>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html
new file mode 100644
index 0000000..0431eae
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-counts.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title></title>
+</head>
+
+<frameset cols="200,190,*" border="0">
+ <frame name="mainCountsRuns" src="main-counts-runs.html" scrolling="no" frameborder="0">
+ <frame name="mainCountsErrors" src="main-counts-errors.html" scrolling="no" frameborder="0">
+ <frame name="mainCountsFailures" src="main-counts-failures.html" scrolling="no" frameborder="0">
+
+ <noframes>
+ <body>
+ <p>jsUnit uses frames in order to remove dependencies upon a browser's implementation of document.getElementById
+ and HTMLElement.innerHTML.</p>
+ </body>
+ </noframes>
+</frameset>
+</html>
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html
new file mode 100644
index 0000000..8a15b97
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-data.html
@@ -0,0 +1,189 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-data.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+ <script language="JavaScript" type="text/javascript" src="jsUnitCore.js"></script>
+ <script language="JavaScript" type="text/javascript" src="jsUnitVersionCheck.js"></script>
+ <script language="JavaScript" type="text/javascript">
+
+ function pageLoaded() {
+ giveFocusToTestFileNameField();
+ }
+
+ function giveFocusToTestFileNameField() {
+ if (document.testRunnerForm.testFileName.type != "hidden")
+ document.testRunnerForm.testFileName.focus();
+ }
+
+ function kickOffTests() {
+ //
+ // Check if Init was called by onload handler
+ //
+ if (typeof(top.testManager) == 'undefined') {
+ top.init();
+ }
+
+ if (isBlank(top.testManager.getTestFileName())) {
+ top.testManager.fatalError('No Test Page specified.');
+ return;
+ }
+
+ top.testManager.setup();
+
+ top.testManager._currentSuite().addTestPage(top.testManager.resolveUserEnteredTestFileName());
+ top.tracer.initialize();
+
+ var traceLevel = document.forms.testRunnerForm.traceLevel;
+ if (traceLevel.value != '0')
+ {
+ var traceWindow = top.tracer._getTraceWindow();
+ if (traceWindow) {
+ traceWindow.focus();
+ }
+ else {
+ top.testManager.fatalError('Tracing requires popup windows, and popups are blocked in your browser.\n\nPlease enable popups if you wish to use tracing.');
+ }
+ }
+
+ top.testManager.start();
+ }
+
+ </script>
+</head>
+
+<body onload="pageLoaded();">
+<table width="100%" cellpadding="0" cellspacing="0" border="0" summary="jsUnit Information" bgcolor="#DDDDDD">
+ <tr>
+ <td width="1"><a href="http://www.jsunit.net" target="_blank"><img src="../images/logo_jsunit.gif" alt="JsUnit" border="0"/></a></td>
+ <td width="50">&nbsp;</td>
+ <th nowrap align="left">
+ <h4>JsUnit <script language="javascript">document.write(JSUNIT_VERSION);</script> TestRunner</h4>
+ <font size="-2"><i>Running on <script language="javascript" type="text/javascript">document.write(navigator.userAgent);</script>
+ </i></font>
+ </th>
+
+ <td nowrap align="right" valign="middle">
+ <font size="-2">
+ <b><a href="http://www.jsunit.net/" target="_blank">www.jsunit.net</a></b>&nbsp;&nbsp;<br>
+ </font>
+ <a href="http://www.pivotalsf.com/" target="top">
+ <img border="0" src="../images/powerby-transparent.gif" alt="Powered By Pivotal">
+ </a>
+ </td>
+ </tr>
+</table>
+
+<form name="testRunnerForm" action="">
+ <script type="text/javascript" language="javascript">
+ if (!jsUnitGetParm('testpage')) {
+ document.write("<p>Enter the filename of the Test Page to be run:</p>");
+ } else {
+ document.write("<br>");
+ };
+ </script>
+
+ <table cellpadding="0" cellspacing="0" border="0" summary="Form for entering test case location">
+ <tr>
+ <td align="center" valign="middle">
+ <script language="JavaScript" type="text/javascript">
+ document.write(top.getDocumentProtocol());
+ </script>
+ </td>
+
+ <td nowrap align="center" valign="bottom">
+ &nbsp;
+ <script language="JavaScript" type="text/javascript">
+ var specifiedTestPage = jsUnitGetParm('testpage');
+ if (specifiedTestPage) {
+ var html = '<input type="hidden" name="testFileName" value="';
+ var valueString = '';
+ if ((top.getDocumentProtocol() == 'http://' || top.getDocumentProtocol() == 'https://') && jsUnitGetParm('testpage').indexOf('/') == 0)
+ valueString += top.location.host;
+ valueString += specifiedTestPage;
+ var testParms = top.jsUnitConstructTestParms();
+ if (testParms != '') {
+ valueString += '?';
+ valueString += testParms;
+ }
+ html += valueString;
+ html += '">';
+ html += valueString;
+ document.write(html);
+ } else {
+ if (top.getDocumentProtocol() == 'file:///' && top.browserSupportsReadingFullPathFromFileField())
+ document.write('<input type="file" name="testFileName" size="60">');
+ else
+ document.write('<input type="text" name="testFileName" size="60">');
+ }
+ </script>
+ <input type="button" name="runButton" value="Run" onclick="kickOffTests()">
+ <script type="text/javascript">
+ function jscoverageWindow() {
+ /*
+ the path may have to be adjusted: it should point to the
+ jscoverage.html file (relative to the jsunit/app
+ directory)
+ */
+ window.open("../../jscoverage.html");
+ }
+ </script>
+ <button onclick="jscoverageWindow();">Coverage report</button>
+ </td>
+ </tr>
+ </table>
+ <br>
+ <hr>
+
+ <table cellpadding="0" cellspacing="0" border="0" summary="Choose Trace Level">
+ <tr>
+ <td nowrap>Trace level:</td>
+
+ <td><select name="traceLevel">
+ <option value="0" selected>
+ no tracing
+ </option>
+
+ <option value="1">
+ warning (lowest)
+ </option>
+
+ <option value="2">
+ info
+ </option>
+
+ <option value="3">
+ debug (highest)
+ </option>
+ </select></td>
+
+ <td>&nbsp;&nbsp;&nbsp;</td>
+
+ <td><input type="checkbox" name="closeTraceWindowOnNewRun" checked></td>
+ <td nowrap>Close old trace window on new run</td>
+
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+
+ <td nowrap>Page load timeout:</td>
+ <td>&nbsp;
+ <script language="javascript" type="text/javascript">
+ document.write('<input type="text" size="2" name="timeout" value="' + top.jsUnitTestManager.TESTPAGE_WAIT_SEC + '">');
+ </script>
+ </td>
+
+ <td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
+
+ <td nowrap>Setup page timeout:</td>
+ <td>&nbsp;
+ <script language="javascript" type="text/javascript">
+ document.write('<input type="text" size="2" name="setUpPageTimeout" value="' + top.jsUnitTestManager.SETUPPAGE_TIMEOUT + '">');
+ </script>
+ </td>
+ </tr>
+ </table>
+ <hr>
+</form>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html
new file mode 100644
index 0000000..cc76ff0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-errors.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-errors.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<hr>
+
+<form name="testRunnerForm" action="javascript:top.testManager.showMessageForSelectedProblemTest()">
+ <p>Errors and failures:&nbsp;</p>
+ <select size="5" ondblclick="top.testManager.showMessageForSelectedProblemTest()" name="problemsList">
+ <option>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</option>
+ </select>
+ <br>
+ <input type="button" value="Show selected" onclick="top.testManager.showMessageForSelectedProblemTest()">
+ &nbsp;&nbsp;&nbsp;
+ <input type="button" value="Show all" onclick="top.testManager.showMessagesForAllProblemTests()">
+</form>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html
new file mode 100644
index 0000000..af0dc7a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-frame.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+<head>
+ <title>jsUnit Main Frame</title>
+</head>
+<frameset rows="230,30,30,30,0,*" border="0">>
+ <frame name="mainData" src="main-data.html" scrolling="no" frameborder="0">
+ <frame name="mainStatus" src="main-status.html" scrolling="no" frameborder="0">
+ <frame name="mainProgress" src="main-progress.html" scrolling="no" frameborder="0">
+ <frame name="mainCounts" src="main-counts.html" scrolling="no" frameborder="0">
+ <frame name="mainResults" src="main-results.html" scrolling="no" frameborder="0">
+ <frame name="mainErrors" src="main-errors.html" scrolling="no" frameborder="0">
+ <noframes>
+ <body>
+ <p>Sorry, JsUnit requires frames.</p>
+ </body>
+ </noframes>
+</frameset>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html
new file mode 100644
index 0000000..302c084
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-loader.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>jsUnit External Data Document loader</title>
+ <script language="JavaScript" type="text/javascript">
+
+ var loadStatus;
+ var callback = function () {
+ };
+
+ function buffer() {
+ return window.frames.documentBuffer;
+ }
+
+ function load(uri) {
+ loadStatus = 'loading';
+ buffer().document.location.href = uri;
+ }
+
+ function loadComplete() {
+ top.xbDEBUG.dump('main-loader.html:loadComplete(): loadStatus = ' + loadStatus + ' href=' + buffer().document.location.href);
+ if (loadStatus == 'loading') {
+ loadStatus = 'complete';
+ callback();
+ callback = function () {
+ };
+ }
+ }
+
+ if (top.xbDEBUG.on) {
+ var scopeName = 'main_loader_' + (new Date()).getTime();
+ top[scopeName] = window;
+ top.xbDebugTraceFunction(scopeName, 'buffer');
+ top.xbDebugTraceFunction(scopeName, 'load');
+ top.xbDebugTraceFunction(scopeName, 'loadComplete');
+ }
+
+ </script>
+</head>
+
+<body>
+<iframe name="documentBuffer" onload="loadComplete()"></iframe>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html
new file mode 100644
index 0000000..5ca52f6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-progress.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-progress.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<table width="375" cellpadding="0" cellspacing="0" border="0" summary="Test progress indicator">
+ <tr>
+ <td width="65" valign="top"><b>Progress:</b></td>
+
+ <td width="300" height="14" valign="middle">
+ <table width="300" cellpadding="0" cellspacing="0" border="1" summary="Progress image">
+ <tr>
+ <td width="300" height="14" valign="top"><img name="progress" height="14" width="0"
+ alt="progress image" src="../images/green.gif"></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html
new file mode 100644
index 0000000..5a904cd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-results.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-results.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<script language="javascript" type="text/javascript">
+ var DEFAULT_SUBMIT_WEBSERVER = "localhost:8080";
+
+ function submitUrlFromSpecifiedUrl() {
+ var result = "";
+ var specifiedUrl = top.getSpecifiedResultUrl();
+ if (specifiedUrl.indexOf("http://") != 0)
+ result = "http://";
+ result += specifiedUrl;
+ return result;
+ }
+
+ function submitUrlFromTestRunnerLocation() {
+ var result = "http://";
+ var webserver = top.getWebserver();
+ if (webserver == null) // running over file:///
+ webserver = DEFAULT_SUBMIT_WEBSERVER;
+ result += webserver;
+ result += "/jsunit/acceptor";
+ return result;
+ }
+
+ var submitUrl = "";
+ if (top.wasResultUrlSpecified()) {
+ submitUrl = submitUrlFromSpecifiedUrl();
+ } else {
+ submitUrl = submitUrlFromTestRunnerLocation();
+ }
+
+ var formString = "<form name=\"resultsForm\" action=\"" + submitUrl + "\" method=\"post\" target=\"_top\">";
+ document.write(formString);
+</script>
+<input type="hidden" name="id">
+<input type="hidden" name="userAgent">
+<input type="hidden" name="jsUnitVersion">
+<input type="hidden" name="time">
+<input type="hidden" name="url">
+<input type="hidden" name="cacheBuster">
+<select size="5" name="testCases" multiple></select>
+</form>
+<script language="javascript" type="text/javascript">
+ function populateHeaderFields(id, userAgent, jsUnitVersion, baseURL) {
+ document.resultsForm.id.value = id;
+ document.resultsForm.userAgent.value = userAgent;
+ document.resultsForm.jsUnitVersion.value = jsUnitVersion;
+ document.resultsForm.url.value = baseURL;
+ document.resultsForm.cacheBuster.value = new Date().getTime();
+ }
+ function submitResults() {
+ var testCasesField = document.resultsForm.testCases;
+ for (var i = 0; i < testCasesField.length; i++) {
+ testCasesField[i].selected = true;
+ }
+ document.resultsForm.submit();
+ }
+</script>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html
new file mode 100644
index 0000000..1053f5d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/main-status.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit main-status.html</title>
+ <link rel="stylesheet" type="text/css" href="../css/jsUnitStyle.css">
+</head>
+
+<body>
+<div id="content"><b>Status:</b> (Idle)</div>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html
new file mode 100644
index 0000000..df6a997
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainer.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit Test Container</title>
+</head>
+<frameset rows="0, *" border="0">
+ <frame name="testContainerController" src="testContainerController.html">
+ <frame name="testFrame" src="emptyPage.html">
+ <noframes>
+ <body>
+ <p>Sorry, JsUnit requires frames.</p>
+ </body>
+ </noframes>
+</frameset>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html
new file mode 100644
index 0000000..3130d76
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/testContainerController.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>JsUnit Test Container Controller</title>
+ <script language="javascript" type="text/javascript">
+ var containerReady = false;
+
+ function init() {
+ containerReady = true;
+ }
+
+ function isPageLoaded() {
+ if (!containerReady)
+ return false;
+
+ var isTestPageLoaded = false;
+
+ try {
+ // attempt to access the var isTestPageLoaded in the testFrame
+ if (typeof(top.testManager.containerTestFrame.isTestPageLoaded) != 'undefined') {
+ isTestPageLoaded = top.testManager.containerTestFrame.isTestPageLoaded;
+ }
+
+ // ok, if the above did not throw an exception, then the
+ // variable is defined. If the onload has not fired in the
+ // testFrame then isTestPageLoaded is still false. Otherwise
+ // the testFrame has set it to true
+ }
+ catch (e) {
+ // an error occured while attempting to access the isTestPageLoaded
+ // in the testFrame, therefore the testFrame has not loaded yet
+ isTestPageLoaded = false;
+ }
+ return isTestPageLoaded;
+ }
+
+ function isContainerReady() {
+ return containerReady;
+ }
+
+ function setNotReady() {
+ try {
+ // attempt to set the isTestPageLoaded variable
+ // in the test frame to false.
+ top.testManager.containerTestFrame.isTestPageLoaded = false;
+ }
+ catch (e) {
+ // testFrame.isTestPageLoaded not available... ignore
+ }
+ }
+ function setTestPage(testPageURI) {
+ setNotReady();
+ top.jsUnitParseParms(testPageURI);
+ testPageURI = appendCacheBusterParameterTo(testPageURI);
+ try {
+ top.testManager.containerTestFrame.location.href = testPageURI;
+ } catch (e) {
+ }
+ }
+
+ function appendCacheBusterParameterTo(testPageURI) {
+ if (testPageURI.indexOf("?") == -1)
+ testPageURI += "?";
+ else
+ testPageURI += "&";
+ testPageURI += "cacheBuster=";
+ testPageURI += new Date().getTime();
+ return testPageURI;
+ }
+ </script>
+</head>
+
+<body onload="init()">
+Test Container Controller
+</body>
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js
new file mode 100644
index 0000000..b7167ec
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/app/xbDebug.js
@@ -0,0 +1,306 @@
+// xbDebug.js revision: 0.003 2002-02-26
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ * Full Terms at /xbProjects-srce/license/mpl-tri-license.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Netscape code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Bob Clary <bclary@netscape.com>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ChangeLog:
+
+2002-02-25: bclary - modified xbDebugTraceOject to make sure
+ that original versions of wrapped functions were not
+ rewrapped. This had caused an infinite loop in IE.
+
+2002-02-07: bclary - modified xbDebug.prototype.close to not null
+ the debug window reference. This can cause problems with
+ Internet Explorer if the page is refreshed. These issues will
+ be addressed at a later date.
+*/
+
+function xbDebug()
+{
+ this.on = false;
+ this.stack = new Array();
+ this.debugwindow = null;
+ this.execprofile = new Object();
+}
+
+xbDebug.prototype.push = function ()
+{
+ this.stack[this.stack.length] = this.on;
+ this.on = true;
+}
+
+xbDebug.prototype.pop = function ()
+{
+ this.on = this.stack[this.stack.length - 1];
+ --this.stack.length;
+}
+
+xbDebug.prototype.open = function ()
+{
+ if (this.debugwindow && !this.debugwindow.closed)
+ this.close();
+
+ this.debugwindow = window.open('about:blank', 'DEBUGWINDOW', 'height=400,width=600,resizable=yes,scrollbars=yes');
+
+ this.debugwindow.title = 'xbDebug Window';
+ this.debugwindow.document.write('<html><head><title>xbDebug Window</title></head><body><h3>Javascript Debug Window</h3></body></html>');
+ this.debugwindow.focus();
+}
+
+xbDebug.prototype.close = function ()
+{
+ if (!this.debugwindow)
+ return;
+
+ if (!this.debugwindow.closed)
+ this.debugwindow.close();
+
+ // bc 2002-02-07, other windows may still hold a reference to this: this.debugwindow = null;
+}
+
+xbDebug.prototype.dump = function (msg)
+{
+ if (!this.on)
+ return;
+
+ if (!this.debugwindow || this.debugwindow.closed)
+ this.open();
+
+ this.debugwindow.document.write(msg + '<br>');
+
+ return;
+}
+
+var xbDEBUG = new xbDebug();
+
+window.onunload = function () {
+ xbDEBUG.close();
+}
+
+function xbDebugGetFunctionName(funcref)
+{
+
+ if (!funcref)
+ {
+ return '';
+ }
+
+ if (funcref.name)
+ return funcref.name;
+
+ var name = funcref + '';
+ name = name.substring(name.indexOf(' ') + 1, name.indexOf('('));
+ funcref.name = name;
+
+ if (!name) alert('name not defined');
+ return name;
+}
+
+// emulate functionref.apply for IE mac and IE win < 5.5
+function xbDebugApplyFunction(funcname, funcref, thisref, argumentsref)
+{
+ var rv;
+
+ if (!funcref)
+ {
+ alert('xbDebugApplyFunction: funcref is null');
+ }
+
+ if (typeof(funcref.apply) != 'undefined')
+ return funcref.apply(thisref, argumentsref);
+
+ var applyexpr = 'thisref.xbDebug_orig_' + funcname + '(';
+ var i;
+
+ for (i = 0; i < argumentsref.length; i++)
+ {
+ applyexpr += 'argumentsref[' + i + '],';
+ }
+
+ if (argumentsref.length > 0)
+ {
+ applyexpr = applyexpr.substring(0, applyexpr.length - 1);
+ }
+
+ applyexpr += ')';
+
+ return eval(applyexpr);
+}
+
+function xbDebugCreateFunctionWrapper(scopename, funcname, precall, postcall)
+{
+ var wrappedfunc;
+ var scopeobject = eval(scopename);
+ var funcref = scopeobject[funcname];
+
+ scopeobject['xbDebug_orig_' + funcname] = funcref;
+
+ wrappedfunc = function ()
+ {
+ var rv;
+
+ precall(scopename, funcname, arguments);
+ rv = xbDebugApplyFunction(funcname, funcref, scopeobject, arguments);
+ postcall(scopename, funcname, arguments, rv);
+ return rv;
+ };
+
+ if (typeof(funcref.constructor) != 'undefined')
+ wrappedfunc.constructor = funcref.constuctor;
+
+ if (typeof(funcref.prototype) != 'undefined')
+ wrappedfunc.prototype = funcref.prototype;
+
+ scopeobject[funcname] = wrappedfunc;
+}
+
+function xbDebugCreateMethodWrapper(contextname, classname, methodname, precall, postcall)
+{
+ var context = eval(contextname);
+ var methodref = context[classname].prototype[methodname];
+
+ context[classname].prototype['xbDebug_orig_' + methodname] = methodref;
+
+ var wrappedmethod = function ()
+ {
+ var rv;
+ // eval 'this' at method run time to pick up reference to the object's instance
+ var thisref = eval('this');
+ // eval 'arguments' at method run time to pick up method's arguments
+ var argsref = arguments;
+
+ precall(contextname + '.' + classname, methodname, argsref);
+ rv = xbDebugApplyFunction(methodname, methodref, thisref, argsref);
+ postcall(contextname + '.' + classname, methodname, argsref, rv);
+ return rv;
+ };
+
+ return wrappedmethod;
+}
+
+function xbDebugPersistToString(obj)
+{
+ var s = '';
+ var p;
+
+ if (obj == null)
+ return 'null';
+
+ switch (typeof(obj))
+ {
+ case 'number':
+ return obj;
+ case 'string':
+ return '"' + obj + '"';
+ case 'undefined':
+ return 'undefined';
+ case 'boolean':
+ return obj + '';
+ }
+
+ if (obj.constructor)
+ return '[' + xbDebugGetFunctionName(obj.constructor) + ']';
+
+ return null;
+}
+
+function xbDebugTraceBefore(scopename, funcname, funcarguments)
+{
+ var i;
+ var s = '';
+ var execprofile = xbDEBUG.execprofile[scopename + '.' + funcname];
+ if (!execprofile)
+ execprofile = xbDEBUG.execprofile[scopename + '.' + funcname] = { started: 0, time: 0, count: 0 };
+
+ for (i = 0; i < funcarguments.length; i++)
+ {
+ s += xbDebugPersistToString(funcarguments[i]);
+ if (i < funcarguments.length - 1)
+ s += ', ';
+ }
+
+ xbDEBUG.dump('enter ' + scopename + '.' + funcname + '(' + s + ')');
+ execprofile.started = (new Date()).getTime();
+}
+
+function xbDebugTraceAfter(scopename, funcname, funcarguments, rv)
+{
+ var i;
+ var s = '';
+ var execprofile = xbDEBUG.execprofile[scopename + '.' + funcname];
+ if (!execprofile)
+ xbDEBUG.dump('xbDebugTraceAfter: execprofile not created for ' + scopename + '.' + funcname);
+ else if (execprofile.started == 0)
+ xbDEBUG.dump('xbDebugTraceAfter: execprofile.started == 0 for ' + scopename + '.' + funcname);
+ else
+ {
+ execprofile.time += (new Date()).getTime() - execprofile.started;
+ execprofile.count++;
+ execprofile.started = 0;
+ }
+
+ for (i = 0; i < funcarguments.length; i++)
+ {
+ s += xbDebugPersistToString(funcarguments[i]);
+ if (i < funcarguments.length - 1)
+ s += ', ';
+ }
+
+ xbDEBUG.dump('exit ' + scopename + '.' + funcname + '(' + s + ')==' + xbDebugPersistToString(rv));
+}
+
+function xbDebugTraceFunction(scopename, funcname)
+{
+ xbDebugCreateFunctionWrapper(scopename, funcname, xbDebugTraceBefore, xbDebugTraceAfter);
+}
+
+function xbDebugTraceObject(contextname, classname)
+{
+ var classref = eval(contextname + '.' + classname);
+ var p;
+ var sp;
+
+ if (!classref || !classref.prototype)
+ return;
+
+ for (p in classref.prototype)
+ {
+ sp = p + '';
+ if (typeof(classref.prototype[sp]) == 'function' && (sp).indexOf('xbDebug_orig') == -1)
+ {
+ classref.prototype[sp] = xbDebugCreateMethodWrapper(contextname, classname, sp, xbDebugTraceBefore, xbDebugTraceAfter);
+ }
+ }
+}
+
+function xbDebugDumpProfile()
+{
+ var p;
+ var execprofile;
+ var avg;
+
+ for (p in xbDEBUG.execprofile)
+ {
+ execprofile = xbDEBUG.execprofile[p];
+ avg = Math.round(100 * execprofile.time / execprofile.count) / 100;
+ xbDEBUG.dump('Execution profile ' + p + ' called ' + execprofile.count + ' times. Total time=' + execprofile.time + 'ms. Avg Time=' + avg + 'ms.');
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css
new file mode 100644
index 0000000..cee6849
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/css/jsUnitStyle.css
@@ -0,0 +1,83 @@
+body {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ color: #000;
+ font-size: 0.8em;
+ background-color: #fff;
+}
+
+a:link, a:visited {
+ color: #00F;
+}
+
+a:hover {
+ color: #F00;
+}
+
+h1 {
+ font-size: 1.2em;
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h2 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h3 {
+ font-weight: bold;
+ color: #039;
+ text-decoration: underline;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+h4 {
+ font-weight: bold;
+ color: #039;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+}
+
+.jsUnitTestResultSuccess {
+ color: #000;
+}
+
+.jsUnitTestResultNotSuccess {
+ color: #F00;
+}
+
+.unselectedTab {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ height: 26px;
+ background: #FFFFFF;
+ border-style: solid;
+ border-bottom-width: 1px;
+ border-top-width: 1px;
+ border-left-width: 1px;
+ border-right-width: 1px;
+}
+
+.selectedTab {
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ height: 26px;
+ background: #DDDDDD;
+ font-weight: bold;
+ border-style: solid;
+ border-bottom-width: 0px;
+ border-top-width: 1px;
+ border-left-width: 1px;
+ border-right-width: 1px;
+}
+
+.tabHeaderSeparator {
+ height: 26px;
+ background: #FFFFFF;
+ border-style: solid;
+ border-bottom-width: 1px;
+ border-top-width: 0px;
+ border-left-width: 0px;
+ border-right-width: 0px;
+} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif
new file mode 100644
index 0000000..b57ca34
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/green.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif
new file mode 100644
index 0000000..65b4bda
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/logo_jsunit.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif
new file mode 100644
index 0000000..69c7d9d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/powerby-transparent.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif
new file mode 100644
index 0000000..262550d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/images/red.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt
new file mode 100644
index 0000000..86e1d54
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/JDOM_license.txt
@@ -0,0 +1,56 @@
+/*--
+
+ $Id: JDOM_license.txt 81 2003-07-24 04:44:54Z edwardhieatt $
+
+ Copyright (C) 2000-2003 Jason Hunter & Brett McLaughlin.
+ 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 disclaimer that follows
+ these conditions in the documentation and/or other materials
+ provided with the distribution.
+
+ 3. The name "JDOM" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact <license AT jdom DOT org>.
+
+ 4. Products derived from this software may not be called "JDOM", nor
+ may "JDOM" appear in their name, without prior written permission
+ from the JDOM Project Management <pm AT jdom DOT org>.
+
+ In addition, we request (but do not require) that you include in the
+ end-user documentation provided with the redistribution and/or in the
+ software itself an acknowledgement equivalent to the following:
+ "This product includes software developed by the
+ JDOM Project (http://www.jdom.org/)."
+ Alternatively, the acknowledgment may be graphical using the logos
+ available at http://www.jdom.org/images/logos.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 JDOM AUTHORS OR THE PROJECT
+ 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.
+
+ This software consists of voluntary contributions made by many
+ individuals on behalf of the JDOM Project and was originally
+ created by Jason Hunter <jhunter AT jdom DOT org> and
+ Brett McLaughlin <brett AT jdom DOT org>. For more information on
+ the JDOM Project, please see <http://www.jdom.org/>.
+
+ */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html
new file mode 100644
index 0000000..9e470e3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/Jetty_license.html
@@ -0,0 +1,213 @@
+<HTML>
+<HEAD>
+ <TITLE>Jetty License</TITLE>
+</HEAD>
+
+<BODY BGCOLOR="#FFFFFF">
+<FONT FACE=ARIAL,HELVETICA>
+<CENTER><FONT SIZE=+3><B>Jetty License</B></FONT></CENTER>
+<CENTER><FONT SIZE=-1><B>$Revision$</B></FONT></CENTER>
+
+<B>Preamble:</B>
+
+<p>
+
+ The intent of this document is to state the conditions under which the
+ Jetty Package may be copied, such that the Copyright Holder maintains some
+ semblance of control over the development of the package, while giving the
+ users of the package the right to use, distribute and make reasonable
+ modifications to the Package in accordance with the goals and ideals of
+ the Open Source concept as described at
+ <A HREF="http://www.opensource.org">http://www.opensource.org</A>.
+
+<P>
+ It is the intent of this license to allow commercial usage of the Jetty
+ package, so long as the source code is distributed or suitable visible
+ credit given or other arrangements made with the copyright holders.
+
+<P><B>Definitions:</B>
+
+<P>
+
+<UL>
+ <LI> "Jetty" refers to the collection of Java classes that are
+ distributed as a HTTP server with servlet capabilities and
+ associated utilities.
+
+ <p>
+
+ <LI> "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ <P>
+
+ <LI> "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder.
+
+ <P>
+
+ <LI> "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package. <BR>
+ Mort Bay Consulting Pty. Ltd. (Australia) is the "Copyright
+ Holder" for the Jetty package.
+
+ <P>
+
+ <LI> "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ <P>
+
+ <LI> "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ <P>
+
+ <LI> "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+ <P>
+</UL>
+
+0. The Jetty Package is Copyright (c) Mort Bay Consulting Pty. Ltd.
+(Australia) and others. Individual files in this package may contain
+additional copyright notices. The javax.servlet packages are copyright
+Sun Microsystems Inc. <P>
+
+ 1. The Standard Version of the Jetty package is
+ available from <A HREF=http://jetty.mortbay.org>http://jetty.mortbay.org</A>.
+
+<P>
+
+ 2. You may make and distribute verbatim copies of the source form
+ of the Standard Version of this Package without restriction, provided that
+ you include this license and all of the original copyright notices
+ and associated disclaimers.
+
+<P>
+
+ 3. You may make and distribute verbatim copies of the compiled form of the
+ Standard Version of this Package without restriction, provided that you
+ include this license.
+
+<P>
+
+ 4. You may apply bug fixes, portability fixes and other modifications
+ derived from the Public Domain or from the Copyright Holder. A Package
+ modified in such a way shall still be considered the Standard Version.
+
+<P>
+
+ 5. You may otherwise modify your copy of this Package in any way, provided
+ that you insert a prominent notice in each changed file stating how and
+ when you changed that file, and provided that you do at least ONE of the
+ following:
+
+<P>
+
+<BLOCKQUOTE>
+ a) Place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as ftp.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.<P>
+
+ b) Use the modified Package only within your corporation or organization.
+
+ <P>
+
+ c) Rename any non-standard classes so the names do not conflict
+ with standard classes, which must also be provided, and provide
+ a separate manual page for each non-standard class that clearly
+ documents how it differs from the Standard Version.
+
+ <P>
+
+ d) Make other arrangements with the Copyright Holder.
+
+ <P>
+</BLOCKQUOTE>
+
+6. You may distribute modifications or subsets of this Package in source
+code or compiled form, provided that you do at least ONE of the following:<P>
+
+<BLOCKQUOTE>
+ a) Distribute this license and all original copyright messages, together
+ with instructions (in the about dialog, manual page or equivalent) on where
+ to get the complete Standard Version.<P>
+
+ b) Accompany the distribution with the machine-readable source of
+ the Package with your modifications. The modified package must include
+ this license and all of the original copyright notices and associated
+ disclaimers, together with instructions on where to get the complete
+ Standard Version.
+
+ <P>
+
+ c) Make other arrangements with the Copyright Holder.
+
+ <P>
+</BLOCKQUOTE>
+
+7. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this Package.
+You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you meet the other distribution requirements
+of this license.<P>
+
+ 8. Input to or the output produced from the programs of this Package
+ do not automatically fall under the copyright of this Package, but
+ belong to whomever generated them, and may be sold commercially, and
+ may be aggregated with this Package.
+
+<P>
+
+ 9. Any program subroutines supplied by you and linked into this Package
+ shall not be considered part of this Package.
+
+<P>
+
+ 10. The name of the Copyright Holder may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+<P>
+
+ 11. This license may change with each release of a Standard Version of
+ the Package. You may choose to use the license associated with version
+ you are using or the license of the latest Standard Version.
+
+<P>
+
+ 12. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+<P>
+
+ 13. If any superior law implies a warranty, the sole remedy under such shall
+ be , at the Copyright Holders option either a) return of any price paid or
+ b) use or reasonable endeavours to repair or replace the software.
+
+<P>
+
+ 14. This license shall be read under the laws of Australia.
+
+<P>
+
+<center>The End</center>
+
+<center><FONT size=-1>This license was derived from the <I>Artistic</I> license published
+ on <a href=http://www.opensource.org>http://www.opensource.com</a></font></center>
+</FONT>
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt
new file mode 100644
index 0000000..7a45bfe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/MPL-1.1.txt
@@ -0,0 +1,470 @@
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (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.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is ______________________________________.
+
+ The Initial Developer of the Original Code is ________________________.
+ Portions created by ______________________ are Copyright (C) ______
+ _______________________. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt
new file mode 100644
index 0000000..45645b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/gpl-2.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html
new file mode 100644
index 0000000..7df3cfb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/index.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<!-- JsUnit -->
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (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.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Edward Hieatt code.
+ -
+ - The Initial Developer of the Original Code is
+ - Edward Hieatt, edward@jsunit.net.
+ - Portions created by the Initial Developer are Copyright (C) 2001
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ - Edward Hieatt, edward@jsunit.net (original author)
+ - Bob Clary, bc@bclary.comn
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Licensing</title>
+ <link rel="stylesheet" type="text/css" href="../app/css/jsUnitStyle.css">
+</head>
+
+<body>
+<table width="100%" cellpadding="0" cellspacing="0" border="1" summary="jsUnit Information">
+ <tr>
+ <th align="center" valign="top"><h1>JsUnit Licenses</h1></th>
+
+ <td align="right" valign="top">
+ <a href="http://www.jsunit.net/" target="_blank">JsUnit Home</a><br>
+ <a href="mailto:edward@jsunit.net">edward@jsunit.net</a><br>
+ </tr>
+</table>
+
+<p><h2>Third-party licenses:</h2>
+ <ul>
+ <li>JDOM: Portions of this software are copyright Copyright (C) 2000-2003 Jason Hunter & Brett McLaughlin. All
+ rights reserved. See <a href="JDOM_license.txt">JDOM_license.txt</a>.
+ <li>Jetty: Portions of this software are copyright � Mort Bay Consulting Pty. Ltd. (Australia) and others. All
+ Rights Reserved. See <a href="Jetty_license.html">Jetty_license.html</a>.
+ <li>Individual files in this package may contain additional copyright notices. The javax.servlet packages are
+ copyright Sun Microsystems Inc. All Rights Reserved.
+ </ul>
+</p>
+
+<p><h2>JsUnit licenses:</h2>
+ JsUnit is licensed under 3 different licenses giving you the freedom
+ to use, modify and distribute JsUnit in a variety of fashions.
+</p>
+
+<ol>
+ <li>
+ <p><a href="MPL-1.1.txt">Mozilla Public License 1.1</a></p>
+
+ <p>See <a href="http://www.mozilla.org/MPL/">mozilla.org</a>
+ for more details.</p>
+ </li>
+
+ <li>
+ <p><a href="gpl-2.txt">GNU Public License 2</a></p>
+
+ <p>See <a href="http://www.gnu.org/licenses/licenses.html">www.gnu.org</a>
+ for more details.</p>
+ </li>
+
+ <li>
+ <p><a href="lgpl-2.1.txt">GNU Lesser Public License 2.1</a></p>
+
+ <p>See <a href="http://www.gnu.org/licenses/licenses.html">www.gnu.org</a>
+ for more details.</p>
+ </li>
+</ol>
+
+<p>
+ Every Java and JavaScript source file in this distribution should be considered to be under the following licensing
+ terms.
+ <pre>
+ ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (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.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Edward Hieatt code.
+ -
+ - The Initial Developer of the Original Code is
+ - Edward Hieatt, edward@jsunit.net.
+ - Portions created by the Initial Developer are Copyright (C) 2003
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Author Edward Hieatt, edward@jsunit.net
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK *****
+ </pre>
+</p>
+</body>
+</html>
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt
new file mode 100644
index 0000000..cbee875
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/lgpl-2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt
new file mode 100644
index 0000000..bd3ad22
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-c.txt
@@ -0,0 +1,35 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is __________________________________________.
+ *
+ * The Initial Developer of the Original Code is
+ * ____________________________________________.
+ * Portions created by the Initial Developer are Copyright (C) 2___
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt
new file mode 100644
index 0000000..33f0980
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/licenses/mpl-tri-license-html.txt
@@ -0,0 +1,35 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (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.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is __________________________________________.
+ -
+ - The Initial Developer of the Original Code is
+ - ____________________________________________.
+ - Portions created by the Initial Developer are Copyright (C) 2___
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either the GNU General Public License Version 2 or later (the "GPL"), or
+ - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the LGPL or the GPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt
new file mode 100644
index 0000000..d260774
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/readme.txt
@@ -0,0 +1,19 @@
+JsUnit
+Copyright (C) 2001-6 Edward Hieatt, edward@jsunit.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Please see http://www.jsunit.net/ for JsUnit documentation and
+the "licenses" directory for license information. \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html
new file mode 100644
index 0000000..71a0c1a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/jsunit/testRunner.html
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>JsUnit Test Runner</title>
+<script language="JavaScript" type="text/javascript" src="app/xbDebug.js"></script>
+<script language="JavaScript" type="text/javascript" src="app/jsUnitCore.js"></script>
+<script language="JavaScript" type="text/javascript">
+ var DEFAULT_TEST_FRAME_HEIGHT = 250;
+
+ function jsUnitParseParms(string) {
+ var i;
+ var searchString = unescape(string);
+ var parameterHash = new Object();
+
+ if (!searchString) {
+ return parameterHash;
+ }
+
+ i = searchString.indexOf('?');
+ if (i != -1) {
+ searchString = searchString.substring(i + 1);
+ }
+
+ var parmList = searchString.split('&');
+ var a;
+ for (i = 0; i < parmList.length; i++) {
+ a = parmList[i].split('=');
+ a[0] = a[0].toLowerCase();
+ if (a.length > 1) {
+ parameterHash[a[0]] = a[1];
+ }
+ else {
+ parameterHash[a[0]] = true;
+ }
+ }
+ return parameterHash;
+ }
+
+ function jsUnitConstructTestParms() {
+ var p;
+ var parms = '';
+
+ for (p in jsUnitParmHash) {
+ var value = jsUnitParmHash[p];
+
+ if (!value ||
+ p == 'testpage' ||
+ p == 'autorun' ||
+ p == 'submitresults' ||
+ p == 'showtestframe' ||
+ p == 'resultid') {
+ continue;
+ }
+
+ if (parms) {
+ parms += '&';
+ }
+
+ parms += p;
+
+ if (typeof(value) != 'boolean') {
+ parms += '=' + value;
+ }
+ }
+ return escape(parms);
+ }
+
+ var jsUnitParmHash = jsUnitParseParms(document.location.search);
+
+ // set to true to turn debugging code on, false to turn it off.
+ xbDEBUG.on = jsUnitGetParm('debug') ? true : false;
+</script>
+
+<script language="JavaScript" type="text/javascript" src="app/jsUnitTestManager.js"></script>
+<script language="JavaScript" type="text/javascript" src="app/jsUnitTracer.js"></script>
+<script language="JavaScript" type="text/javascript" src="app/jsUnitTestSuite.js"></script>
+<script language="JavaScript" type="text/javascript">
+
+ var testManager;
+ var utility;
+ var tracer;
+
+
+ if (!Array.prototype.push) {
+ Array.prototype.push = function (anObject) {
+ this[this.length] = anObject;
+ }
+ }
+
+ if (!Array.prototype.pop) {
+ Array.prototype.pop = function () {
+ if (this.length > 0) {
+ delete this[this.length - 1];
+ this.length--;
+ }
+ }
+ }
+
+ function shouldKickOffTestsAutomatically() {
+ return jsUnitGetParm('autorun') == "true";
+ }
+
+ function shouldShowTestFrame() {
+ return jsUnitGetParm('showtestframe');
+ }
+
+ function shouldSubmitResults() {
+ return jsUnitGetParm('submitresults');
+ }
+
+ function getResultId() {
+ if (jsUnitGetParm('resultid'))
+ return jsUnitGetParm('resultid');
+ return "";
+ }
+
+ function submitResults() {
+ window.mainFrame.mainData.document.testRunnerForm.runButton.disabled = true;
+ window.mainFrame.mainResults.populateHeaderFields(getResultId(), navigator.userAgent, JSUNIT_VERSION, testManager.resolveUserEnteredTestFileName());
+ window.mainFrame.mainResults.submitResults();
+ }
+
+ function wasResultUrlSpecified() {
+ return shouldSubmitResults() && jsUnitGetParm('submitresults') != 'true';
+ }
+
+ function getSpecifiedResultUrl() {
+ return jsUnitGetParm('submitresults');
+ }
+
+ function init() {
+ var testRunnerFrameset = document.getElementById('testRunnerFrameset');
+ if (shouldShowTestFrame() && testRunnerFrameset) {
+ var testFrameHeight;
+ if (jsUnitGetParm('showtestframe') == 'true')
+ testFrameHeight = DEFAULT_TEST_FRAME_HEIGHT;
+ else
+ testFrameHeight = jsUnitGetParm('showtestframe');
+ testRunnerFrameset.rows = '*,0,' + testFrameHeight;
+ }
+ testManager = new jsUnitTestManager();
+ tracer = new JsUnitTracer(testManager);
+ if (shouldKickOffTestsAutomatically()) {
+ window.mainFrame.mainData.kickOffTests();
+ }
+ }
+
+
+</script>
+</head>
+
+<frameset id="testRunnerFrameset" rows="*,0,0" border="0" onload="init()">
+
+ <frame frameborder="0" name="mainFrame" src="./app/main-frame.html">
+ <frame frameborder="0" name="documentLoader" src="./app/main-loader.html">
+ <frame frameborder="0" name="testContainer" src="./app/testContainer.html">
+
+ <noframes>
+ <body>
+ <p>Sorry, JsUnit requires support for frames.</p>
+ </body>
+ </noframes>
+</frameset>
+
+</html> \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js
new file mode 100644
index 0000000..8120054
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/script.js
@@ -0,0 +1,7 @@
+function f() {
+ return true;
+}
+
+function g() {
+ return true;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html
new file mode 100644
index 0000000..0d4d9bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example-jsunit/test.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+<title>Test</title>
+
+<script type="text/javascript" src="jsunit/app/jsUnitCore.js"></script>
+<script type="text/javascript" src="script.js"></script>
+<script type="text/javascript">
+function test_f() {
+ assert(f());
+}
+
+/*
+This code automatically stores coverage reports when running under
+jscoverage-server.
+*/
+function tearDownPage() {
+ if (window.jscoverage_report) {
+ jscoverage_report();
+ }
+}
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/example/index.html
new file mode 100644
index 0000000..e7230b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/example/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/example/script.js
new file mode 100644
index 0000000..0589c76
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/example/script.js
@@ -0,0 +1,20 @@
+function go(element) {
+ var message;
+ if (element.id === 'radio1') {
+ message = 'You selected the number 1.';
+ }
+ else if (element.id === 'radio2') {
+ message = 'You selected the number 2.';
+ }
+ else if (element.id === 'radio3') {
+ message = 'You selected the number 3.';
+ }
+ else if (element.id === 'radio4') {
+ message = 'You selected the number 4.';
+ }
+ var div = document.getElementById('request');
+ div.className = 'black';
+ div = document.getElementById('result');
+ div.innerHTML = '<p>' + message + '</p>';
+ div.innerHTML += '<p>If you are running the instrumented version of this program, you can click the "Summary" tab to view a coverage report.</p>';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/faq.html b/tools/node_modules/expresso/deps/jscoverage/doc/faq.html
new file mode 100644
index 0000000..7b783a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/faq.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - FAQ</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2><abbr title="Frequently Asked Questions">FAQ</abbr></h2>
+
+ <h3>Can I use JSCoverage to measure code coverage for a page on <code>http://example.com/</code>?</h3>
+
+ <p>
+ In order to measure the code coverage of a page on <code>http://example.com/</code>,
+ you must run <code>jscoverage</code> to create a <code>jscoverage.html</code> file on the
+ <code>example.com</code> server. You cannot use <code>http://example.org/jscoverage.html</code>
+ to measure the code coverage of a page located on <code>http://example.com/</code>.
+ </p>
+
+ <p>
+ The fundamental reason for this limitation is the
+ <a href="http://www.mozilla.org/projects/security/components/same-origin.html">Same Origin Policy</a>
+ for untrusted JavaScript.
+ </p>
+
+ <p>
+ (In fact, the current version of JSCoverage is slightly more restrictive
+ than this: it requires that the JavaScript being measured reside under the
+ same <strong>directory</strong> as the <code>jscoverage.html</code> file.)
+ </p>
+
+ <h3>Why doesn't my test suite run under JSCoverage in Firefox 3?</h3>
+
+ <p>
+ Firefox 3 introduces <a
+ href="http://tech.groups.yahoo.com/group/jsunit/message/1075">new
+ security restrictions</a> on local files. Depending on the way your
+ test suite is organized, this may cause problems for JSCoverage.
+ (You may get the error "uncaught exception: Permission denied to get property Window._$jscoverage".)
+ There are several workarounds:
+ </p>
+
+ <ul class="list">
+ <li><p>Place your files on a web server instead of loading them from the file system.
+ This is usually the simplest solution.</p>
+ <li><p>Organize your HTML files in your test suite in a flat directory structure. For example, suppose that
+ you instrument your test suite with this command:</p>
+<pre>
+jscoverage src instrumented
+</pre>
+ <p>If all your HTML files are located directly under the <code>src/</code> directory (i.e., not in a
+ subdirectory of <code>src/</code>), then you should not have any problems using Firefox 3.</p>
+ <li><p>Set the <a href="http://kb.mozillazine.org/Editing_configuration">Firefox preference</a> named
+ <code><a href="http://kb.mozillazine.org/Security.fileuri.origin_policy">security.fileuri.origin_policy</a></code>
+ to 3.</p>
+ </ul>
+
+ <h3>I'm trying to load my code with the URL
+ <code>file:///C:/foo/bar/jscoverage.html?foo/bar.html</code>
+ and I'm getting all kinds of JavaScript errors.</h3>
+
+ <p>
+ Internet Explorer 6 seems to have problems with a <code>file:</code> URL
+ that has a query string with a slash in it.
+ </p>
+ <p>
+ As a workaround:
+ </p>
+ <ul class="list">
+ <li><p>Place your files on a web server instead of loading them from the file system.
+ (<code>http:</code> URLs work fine.)</p>
+ <li><p>Do not use a query string; enter your URL in the "URL" field in the "Browser" tab.</p>
+ <li><p>Rearrange your directory structure so that <code>bar.html</code>
+ ends up in the same directory as <code>jscoverage.html</code>; then
+ you can use the URL
+ <code>file:///C:/foo/bar/jscoverage.html?bar.html</code>
+ with no slash in the query string.</p>
+ <li><p>Use a different browser. (IE 7 seems to work.)</p>
+ </ul>
+
+ <h3>JSCoverage changes my cursor to a busy cursor, and it never changes back!</h3>
+
+ <p>
+ Certain browsers (<i>e. g</i>., Internet Explorer 6, Opera, Safari) have trouble changing
+ the cursor. Try moving the mouse and your cursor should change back to normal.
+ </p>
+
+ <p>
+ See <a href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/631908bd63241136/783c307480f95d8c">this discussion</a> for more information.
+ </p>
+
+ <h3>JSCoverage hangs sometimes when rendering the coverage report.</h3>
+
+ <p>
+ With Internet Explorer 6 (I think I see a pattern here), garbage collection can cause performance problems.
+ (More information <a href="http://ajaxian.com/archives/garbage-collection-in-ie6">here</a>.)
+ </p>
+
+ <h3 id="jsunit">Can JSCoverage be used with <a href="http://www.jsunit.net/">JsUnit</a>?</h3>
+
+ <p>
+ It is necessary to run JSCoverage in <dfn>inverted mode</dfn>. You will have to
+ modify JsUnit to launch JSCoverage.
+ </p>
+
+ <p>
+ See the directory <code>doc/example-jsunit</code> for an example. It
+ contains a copy of JsUnit version 2.2alpha11, with the file
+ <code>jsunit/app/main-data.html</code> slightly modified to add a button
+ which launches JSCoverage. It also contains a simple unit test file <code>test.html</code>. You
+ can instrument this example as follows:
+ </p>
+
+<pre>
+jscoverage --no-instrument=jsunit doc/example-jsunit doc/instrumented-jsunit
+</pre>
+
+ <p>
+ You can then run the <code>test.html</code> file in JsUnit's <code>jsunit/testRunner.html</code>.
+ The simplest way to do this is probably to copy the contents of <code>doc/instrumented-jsunit</code>
+ to the root of a web server and then access the URL
+ </p>
+
+<pre>
+http://127.0.0.1/jsunit/testRunner.html?testPage=http://127.0.0.1/test.html&amp;autoRun=true
+</pre>
+
+ <p>
+ After the test suite has been run, click on the "Coverage report" button
+ to get a coverage report.
+ </p>
+
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li>FAQ
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.png b/tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.png
new file mode 100644
index 0000000..b3c949d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/feed-icon-14x14.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/help.html b/tools/node_modules/expresso/deps/jscoverage/doc/help.html
new file mode 100644
index 0000000..00463e0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/help.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - help</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>Help</h2>
+ <p>
+ Questions, problems, suggestions, bug reports, and so on can be posted at the
+ online <a href="http://siliconforks.com/forum/viewforum.php?f=1">forum</a>.
+ </p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li>Help
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/index.html
new file mode 100644
index 0000000..7deca7e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/index.html
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - code coverage for JavaScript</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><span class="h1">JSCoverage</span><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <p>
+ JSCoverage is a tool that measures code coverage for
+ JavaScript programs.
+ </p>
+ <p>
+ <dfn>Code coverage</dfn> statistics show which lines of a program have
+ been executed (and which have been missed). This information is useful
+ for constructing comprehensive test suites (hence, it is often called
+ <dfn>test coverage</dfn>).
+ </p>
+ <p>
+ JSCoverage works by instrumenting the JavaScript code used in web
+ pages. Code coverage statistics are collected while the instrumented
+ JavaScript code is executed in a web browser.
+ </p>
+ <p>
+ JSCoverage supports the complete language syntax described in the
+ <cite>ECMAScript Language Specification</cite> (ECMA-262, 3rd edition).
+ JSCoverage works with any modern standards-compliant web browser -
+ including Internet Explorer (IE 6 and IE 7), Firefox (FF 2 and FF 3),
+ Opera, Safari, and Google Chrome - on Microsoft Windows and GNU/Linux.
+ </p>
+ <p>
+ JSCoverage is free software, distributed under the
+ <a href="license.html">GNU General Public License version 2</a>.
+ </p>
+
+ <h2>Latest News <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a></h2>
+
+ <h3><a name="20081211">December 11, 2008 - JSCoverage 0.4</a></h3>
+ <p>
+ JSCoverage 0.4 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release includes many new features:
+ </p>
+ <ul class="list">
+ <li>
+ The new <code>jscoverage-server</code> program is provided as an
+ alternative to the <code>jscoverage</code> program. The
+ <code>jscoverage-server</code> program is a simple HTTP server which
+ instruments JavaScript code as it is served; this allows you to execute
+ JavaScript and gather code coverage statistics without a preliminary
+ step of creating instrumented code. The <code>jscoverage-server</code>
+ program can either serve files directly from the filesystem or run as a
+ proxy server (with the <code>--proxy</code> option), instrumenting
+ JavaScript provided by another web server.
+ <li>
+ Using <code>jscoverage-server</code>, coverage reports can now be stored
+ to the filesystem.
+ </li>
+ <li>
+ JSCoverage now recognizes special JavaScript comments which specify that
+ certain lines of code should be ignored in coverage reports.
+ </li>
+ <li>
+ The new <code>--encoding</code> option provides better support for
+ different character encodings.
+ </li>
+ <li>
+ The JSCoverage user interface is now faster and more responsive.
+ </li>
+ <li>
+ The new <code>--no-highlight</code> option can be used to disable syntax
+ highlighting (giving better performance for large JavaScript files).
+ </li>
+ <li>
+ The build system has been modified so that <code>make install</code>
+ only installs the <code>jscoverage</code> and
+ <code>jscoverage-server</code> executables and their manual pages.
+ (Previous versions installed SpiderMonkey library and executable files,
+ which could conflict with other versions of SpiderMonkey installed on
+ your system.)
+ </li>
+ <li>
+ JSCoverage now supports several features beyond those found in the
+ <cite>ECMAScript Language Specification</cite>, including the following:
+ <ul class="list">
+ <li>getters and setters
+ <li><code>for each</code> loops
+ <li>generators and iterators
+ <li>the <code>let</code> keyword
+ <li>destructuring assignment
+ <li>array comprehensions
+ <li>expression closures
+ <li>generator expressions
+ </ul>
+ Use the new <code>--js-version</code> option to enable these features.
+ </li>
+ </ul>
+ <p>
+ The GCC C++ compiler (<code>g++</code>) is now required to compile
+ JSCoverage. (Previously, only the C compiler was needed.)
+ </p>
+ <p>
+ Please report any bugs you find using the new <a href="http://siliconforks.com/jscoverage/bugs/">bug tracker</a>.
+ </p>
+
+ <h3><a name="20080331">March 31, 2008 - JSCoverage and Firefox 3</a></h3>
+ <p>
+ The <a href="faq.html">JSCoverage FAQ</a> has been updated to address problems using JSCoverage with Firefox 3.
+ </p>
+
+ <h3><a name="20080324">March 24, 2008 - JSCoverage in Debian GNU/Linux</a></h3>
+ <p>
+ JSCoverage is now <a href="http://packages.debian.org/sid/jscoverage">available</a> in the Debian unstable distribution.
+ </p>
+
+ <p>
+ <a href="news.html">All news items...</a>
+ </p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li>Home
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html
new file mode 100644
index 0000000..be0f8ea
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/index.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+<button onclick='window.open("jscoverage.html");'>Coverage report</button>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css
new file mode 100644
index 0000000..31a4695
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-highlight.css
@@ -0,0 +1,38 @@
+/*
+ jscoverage-highlight.css - JSCoverage syntax highlighting style sheet
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* keyword, type, symbol, cbracket */
+#sourceTable .k {
+ font-weight: bold;
+}
+
+/* string, regexp, number */
+#sourceTable .s {
+ color: #006400;
+}
+
+/* specialchar */
+#sourceTable .t {
+ color: #2e8b57;
+}
+
+/* comment */
+#sourceTable .c {
+ font-style: italic;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css
new file mode 100644
index 0000000..afb2b80
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-ie.css
@@ -0,0 +1,89 @@
+#headingDiv {
+ position: static;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 0.5em;
+}
+
+#tabs {
+ clear: all;
+ position: static;
+ top: auto;
+ left: auto;
+ right: auto;
+ height: auto;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+#tabs div {
+ position: relative;
+ height: auto;
+ line-height: normal;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+#tabs div.selected {
+ padding-bottom: 6px;
+ z-index: 2;
+}
+
+.TabPage {
+ position: relative;
+ top: -1px;
+ left: auto;
+ right: auto;
+ bottom: auto;
+ clear: left;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 10px;
+ z-index: 1;
+}
+
+#locationDiv {
+ margin-bottom: 10px;
+}
+
+#iframeDiv {
+ position: static;
+ width: 100%;
+}
+
+#summaryDiv {
+ position: static;
+ width: 100%;
+}
+
+#fileDiv {
+ margin-bottom: 10px;
+}
+
+#sourceDiv {
+ position: static;
+ width: 100%;
+}
+
+#storeDiv {
+ position: static;
+ width: 100%;
+}
+
+/* some defaults */
+
+.TabPage {
+ height: 650px;
+}
+
+#iframeDiv {
+ height: 600px;
+}
+
+#summaryDiv {
+ height: 600px;
+}
+
+#sourceDiv {
+ height: 600px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif
new file mode 100644
index 0000000..f13c0b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage-throbber.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css
new file mode 100644
index 0000000..98af69b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.css
@@ -0,0 +1,328 @@
+/*
+ jscoverage.css - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+body {
+ background-color: #bfffbf;
+ font-family: sans-serif;
+ font-size: 100%;
+ margin: 0;
+}
+
+#mainDiv {
+ font-size: 0.8125em;
+}
+
+#headingDiv {
+ position: absolute;
+ top: 0.5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 0;
+ line-height: 1.5em;
+}
+
+h1 {
+ float: left;
+ margin: 0;
+ padding-bottom: 0.5em;
+ font-size: 1.3em;
+}
+
+.ProgressBar {
+ float: left;
+ visibility: hidden;
+}
+
+.ProgressPercentage {
+ display: block;
+ float: left;
+ width: 5em;
+ text-align: right;
+}
+
+.ProgressGraph {
+ float: left;
+ width: 100px;
+ height: 10px;
+ border: 1px solid black;
+ margin-top: 0.3em;
+ background-color: #d4d0c8;
+ overflow: hidden;
+}
+
+.ProgressCovered {
+ /* windows system color ActiveCaption or Highlight */
+ background-color: #0a246a;
+ width: 0;
+ height: 10px;
+ overflow: hidden;
+}
+
+#progressLabel {
+ display: block;
+ float: left;
+ padding-left: 0.3em;
+}
+
+/*******************************************************************************
+browser tab
+*/
+
+input#location, button {
+ border: 1px solid black;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+#iframeDiv {
+ position: absolute;
+ top: 3.5em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+}
+
+iframe {
+ width: 100%;
+ height: 100%;
+}
+
+/*******************************************************************************
+summary tab
+*/
+
+#summaryDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#summaryTable {
+ width: 100%;
+ margin-left: 0px;
+ margin-right: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+table#summaryTable th, table#summaryTable td {
+ border-left: 1px solid #d9d9d9;
+}
+
+table#summaryTable th.leftColumn, table#summaryTable td.leftColumn {
+ border-left-width: 0px;
+}
+
+table#summaryTable th, table#summaryTable td {
+ padding: 2px;
+}
+
+th {
+ background-color: #e6ffe6;
+}
+
+td.numeric {
+ text-align: right;
+}
+
+abbr {
+ cursor: help;
+}
+
+tr#summaryTotals td.leftColumn span {
+ float: right;
+}
+tr#summaryTotals td.leftColumn span.title {
+ float: left;
+ font-weight: bold;
+}
+tr#summaryTotals td {
+ background-color: #ffd;
+}
+td.coverage {
+ width: 150px;
+}
+td.coverage span {
+ float: right;
+ margin-right: 5px;
+}
+.pctGraph {
+ width: 100px;
+ height: 10px;
+ float: right;
+ border: 1px solid #000;
+ background-color: #e00000;
+ overflow: hidden;
+ margin-top: 4px;
+}
+.pctGraph .covered {
+ background-color: #00f000;
+ width: 0;
+ height: 10px;
+}
+.pctGraph .skipped {
+ background-color: #d4d0c8;
+ width: 100px;
+ height: 10px;
+}
+tbody#summaryTbody tr.even td {
+ background-color: #e6ffe6;
+}
+
+/*******************************************************************************
+source tab
+*/
+
+#fileDiv {
+ font-size: large;
+ font-weight: bold;
+}
+
+#sourceDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#sourceTable {
+ border: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+/*
+IE default behavior is to make <pre> smaller than surrounding text. Because
+the table already has font-size small, this would make the font-size within the
+<pre> x-small. So we don't rely on the default.
+*/
+table#sourceTable pre {
+ font-size: medium;
+}
+
+table#sourceTable td {
+ border: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table#sourceTable pre {
+ border: 0px;
+ margin: 0px;
+}
+
+.g {
+ background-color: #bfffbf;
+}
+
+.y {
+ background-color: #ffffbf;
+}
+
+.r {
+ background-color: #ffbfbf;
+}
+
+/*******************************************************************************
+store tab
+*/
+
+#storeDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+/*******************************************************************************
+about tab
+*/
+
+p {
+ margin-top: 0;
+}
+
+/*******************************************************************************
+tabs
+*/
+
+#tabs {
+ position: absolute;
+ top: 3em;
+ left: 1.5em;
+ right: 1.5em;
+ height: 2em;
+}
+
+#tabs div {
+ background-color: white;
+ position: relative;
+ float: left;
+ border: 1px solid black;
+ border-bottom-width: 0;
+ cursor: pointer;
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ height: 2em;
+ z-index: 1;
+ line-height: 1.8em;
+}
+
+#tabs div.selected {
+ z-index: 3;
+ cursor: default;
+}
+
+#tabs div.disabled {
+ /* windows system color GrayText */
+ color: #808080;
+ cursor: default;
+}
+
+.TabPage {
+ background-color: white;
+ border: 1px solid black;
+ position: absolute;
+ top: 5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 1.5em;
+ z-index: 2;
+ padding: 1em;
+ display: none;
+}
+
+#tabPages div.selected {
+ display: block;
+}
+
+img {
+ visibility: hidden;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html
new file mode 100644
index 0000000..601f62a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+ jscoverage.html - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<html>
+<head>
+<title>JSCoverage</title>
+<link rel="stylesheet" type="text/css" href="jscoverage-highlight.css">
+<link rel="stylesheet" type="text/css" href="jscoverage.css">
+<!--[if IE]>
+<link rel="stylesheet" type="text/css" href="jscoverage-ie.css">
+<![endif]-->
+<script type="text/javascript" src="jscoverage.js"></script>
+</head>
+
+<body onload="jscoverage_body_load();" onresize="jscoverage_body_resize();">
+<div id="mainDiv">
+<div id="headingDiv">
+<h1>JSCoverage</h1>
+<div class="ProgressBar" id="progressBar"><span class="ProgressPercentage"></span><div class="ProgressGraph"><div class="ProgressCovered"></div></div></div>
+<span id="progressLabel"></span>
+</div>
+
+<div id="tabs" class="Tabs">
+ <div id="browserTab"><img src="jscoverage-throbber.gif" alt=""> Browser <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="summaryTab"><img id="summaryThrobber" src="jscoverage-throbber.gif" alt=""> Summary <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="sourceTab" class="disabled"><img src="jscoverage-throbber.gif" alt=""> Source <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="storeTab"><img id="storeThrobber" src="jscoverage-throbber.gif" alt=""> Store <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="aboutTab"><img src="jscoverage-throbber.gif" alt=""> About <img src="jscoverage-throbber.gif" alt=""></div>
+</div>
+<div id="tabPages" class="TabPages">
+ <div class="TabPage" id="browserTabPage">
+ <div id="locationDiv">
+ URL: <input id="location" type="text" size="70" onkeypress="jscoverage_input_keypress(event)">
+ <button onclick="jscoverage_button_click();">Go</button>
+ </div>
+ <div id="iframeDiv">
+ <iframe id="browserIframe" onload="jscoverage_browser_load();"></iframe>
+ </div>
+ </div>
+ <div class="TabPage">
+ <input type="checkbox" id="checkbox" onclick="return jscoverage_checkbox_click();"> <label for="checkbox">Show missing statements column</label>
+ <div id="summaryDiv">
+ <div id="summaryErrorDiv"></div>
+ <table id="summaryTable">
+ <thead>
+ <tr id="headerRow">
+ <th class="leftColumn">File</th>
+ <th><abbr title="The total number of executable statements">Statements</abbr></th>
+ <th><abbr title="The number of statements actually executed">Executed</abbr></th>
+ <th><abbr title="Number of executed statements as a percentage of total number of statements">Coverage</abbr></th>
+ </tr>
+ <tr id="summaryTotals">
+ <td class="leftColumn">
+ <span class="title">Total:</span>
+ <span>0</span>
+ </td>
+ <td class="numeric">0</td>
+ <td class="numeric">0</td>
+ <td class="coverage">
+ <div class="pctGraph">
+ <div class="covered"></div>
+ </div>
+ <span class="pct">0%</span>
+ </td>
+ </tr>
+
+ </thead>
+ <tbody id="summaryTbody">
+
+ <!--
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ <td>0</td>
+ <td>0%</td>
+ <td>0</td>
+ </tr>
+ -->
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="TabPage">
+ <div id="fileDiv"></div>
+ <div id="sourceDiv"></div>
+ </div>
+ <div class="TabPage" id="storeTabPage">
+ <button id="storeButton" onclick="jscoverage_storeButton_click();">Store Report</button>
+ <img id="storeImg" src="jscoverage-throbber.gif" alt="loading...">
+ <div id="storeDiv"></div>
+ </div>
+ <div class="TabPage">
+ <p>
+ This is version 0.4 of JSCoverage, a program that calculates code
+ coverage statistics for JavaScript.
+ </p>
+ <p>
+ See <a href="http://siliconforks.com/jscoverage/">http://siliconforks.com/jscoverage/</a> for more information.
+ </p>
+ <p>
+ Copyright &copy; 2007, 2008 siliconforks.com
+ </p>
+ </div>
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js
new file mode 100644
index 0000000..9e2ea5b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/jscoverage.js
@@ -0,0 +1,1024 @@
+/*
+ jscoverage.js - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/**
+Initializes the _$jscoverage object in a window. This should be the first
+function called in the page.
+@param w this should always be the global window object
+*/
+function jscoverage_init(w) {
+ try {
+ // in Safari, "import" is a syntax error
+ Components.utils['import']('resource://gre/modules/jscoverage.jsm');
+ jscoverage_isInvertedMode = true;
+ return;
+ }
+ catch (e) {}
+
+ if (w.opener && w.opener.top._$jscoverage) {
+ // we are in inverted mode
+ jscoverage_isInvertedMode = true;
+ if (! w._$jscoverage) {
+ w._$jscoverage = w.opener.top._$jscoverage;
+ }
+ }
+ else {
+ // we are not in inverted mode
+ jscoverage_isInvertedMode = false;
+ if (! w._$jscoverage) {
+ w._$jscoverage = {};
+ }
+ }
+}
+
+var jscoverage_currentFile = null;
+var jscoverage_currentLine = null;
+
+var jscoverage_inLengthyOperation = false;
+
+/*
+Possible states:
+ isInvertedMode isServer isReport tabs
+normal false false false Browser
+inverted true false false
+server, normal false true false Browser, Store
+server, inverted true true false Store
+report false false true
+*/
+var jscoverage_isInvertedMode = false;
+var jscoverage_isServer = false;
+var jscoverage_isReport = false;
+
+jscoverage_init(window);
+
+function jscoverage_createRequest() {
+ // Note that the IE7 XMLHttpRequest does not support file URL's.
+ // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html
+ // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ return new XMLHttpRequest();
+ }
+}
+
+// http://www.quirksmode.org/js/findpos.html
+function jscoverage_findPos(obj) {
+ var result = 0;
+ do {
+ result += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ while (obj);
+ return result;
+}
+
+// http://www.quirksmode.org/viewport/compatibility.html
+function jscoverage_getViewportHeight() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ if (self.innerHeight) {
+ // all except Explorer
+ return self.innerHeight;
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ // Explorer 6 Strict Mode
+ return document.documentElement.clientHeight;
+ }
+ else if (document.body) {
+ // other Explorers
+ return document.body.clientHeight;
+ }
+ else {
+ throw "Couldn't calculate viewport height";
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Indicates visually that a lengthy operation has begun. The progress bar is
+displayed, and the cursor is changed to busy (on browsers which support this).
+*/
+function jscoverage_beginLengthyOperation() {
+ jscoverage_inLengthyOperation = true;
+
+ var progressBar = document.getElementById('progressBar');
+ progressBar.style.visibility = 'visible';
+ ProgressBar.setPercentage(progressBar, 0);
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'visible';
+
+ /* blacklist buggy browsers */
+//#JSCOVERAGE_IF
+ if (! /Opera|WebKit/.test(navigator.userAgent)) {
+ /*
+ Change the cursor style of each element. Note that changing the class of the
+ element (to one with a busy cursor) is buggy in IE.
+ */
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = 'wait';
+ }
+ }
+}
+
+/**
+Removes the progress bar and busy cursor.
+*/
+function jscoverage_endLengthyOperation() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 100);
+ setTimeout(function() {
+ jscoverage_inLengthyOperation = false;
+ progressBar.style.visibility = 'hidden';
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'hidden';
+ progressLabel.innerHTML = '';
+
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = '';
+ }
+ }, 50);
+}
+
+function jscoverage_setSize() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ var viewportHeight = jscoverage_getViewportHeight();
+
+ /*
+ border-top-width: 1px
+ padding-top: 10px
+ padding-bottom: 10px
+ border-bottom-width: 1px
+ margin-bottom: 10px
+ ----
+ 32px
+ */
+ var tabPages = document.getElementById('tabPages');
+ var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px';
+ var nodeList = tabPages.childNodes;
+ var length = nodeList.length;
+ for (var i = 0; i < length; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ node.style.height = tabPageHeight;
+ }
+
+ var iframeDiv = document.getElementById('iframeDiv');
+ // may not exist if we have removed the first tab
+ if (iframeDiv) {
+ iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px';
+ }
+
+ var summaryDiv = document.getElementById('summaryDiv');
+ summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px';
+
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px';
+
+ var storeDiv = document.getElementById('storeDiv');
+ if (storeDiv) {
+ storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px';
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off',
+and '0' (upper or lower case) are false.
+@param s the string
+@return a boolean value
+*/
+function jscoverage_getBooleanValue(s) {
+ s = s.toLowerCase();
+ if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') {
+ return false;
+ }
+ return true;
+}
+
+function jscoverage_removeTab(id) {
+ var tab = document.getElementById(id + 'Tab');
+ tab.parentNode.removeChild(tab);
+ var tabPage = document.getElementById(id + 'TabPage');
+ tabPage.parentNode.removeChild(tabPage);
+}
+
+/**
+Initializes the contents of the tabs. This sets the initial values of the
+input field and iframe in the "Browser" tab and the checkbox in the "Summary"
+tab.
+@param queryString this should always be location.search
+*/
+function jscoverage_initTabContents(queryString) {
+ var showMissingColumn = false;
+ var parameters, parameter, i, index, url, name, value;
+ if (queryString.length > 0) {
+ // chop off the question mark
+ queryString = queryString.substring(1);
+ parameters = queryString.split(/&|;/);
+ for (i = 0; i < parameters.length; i++) {
+ parameter = parameters[i];
+ index = parameter.indexOf('=');
+ if (index === -1) {
+ // still works with old syntax
+ url = parameter;
+ }
+ else {
+ name = parameter.substr(0, index);
+ value = parameter.substr(index + 1);
+ if (name === 'missing' || name === 'm') {
+ showMissingColumn = jscoverage_getBooleanValue(value);
+ }
+ else if (name === 'url' || name === 'u') {
+ url = value;
+ }
+ }
+ }
+ }
+
+ var checkbox = document.getElementById('checkbox');
+ checkbox.checked = showMissingColumn;
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+
+ // this will automatically propagate to the input field
+ if (url) {
+ frames[0].location = url;
+ }
+
+ // if the browser tab is absent, we have to initialize the summary tab
+ if (! document.getElementById('browserTab')) {
+ jscoverage_recalculateSummaryTab();
+ }
+}
+
+function jscoverage_body_load() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.init(progressBar);
+
+ function reportError(e) {
+ jscoverage_endLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'hidden';
+ var div = document.getElementById('summaryErrorDiv');
+ div.innerHTML = 'Error: ' + e;
+ }
+
+ if (jscoverage_isReport) {
+ jscoverage_beginLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'visible';
+ var request = jscoverage_createRequest();
+ try {
+ request.open('GET', 'jscoverage.json', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ try {
+ if (request.status !== 0 && request.status !== 200) {
+ throw request.status;
+ }
+ var response = request.responseText;
+ if (response === '') {
+ throw 404;
+ }
+ var json = eval('(' + response + ')');
+ var file;
+ for (file in json) {
+ var fileCoverage = json[file];
+ _$jscoverage[file] = fileCoverage.coverage;
+ _$jscoverage[file].source = fileCoverage.source;
+ }
+ jscoverage_recalculateSummaryTab();
+ summaryThrobber.style.visibility = 'hidden';
+ }
+ catch (e) {
+ reportError(e);
+ }
+ }
+ };
+ request.send(null);
+ }
+ catch (e) {
+ reportError(e);
+ }
+
+ jscoverage_removeTab('browser');
+ jscoverage_removeTab('store');
+ }
+ else {
+ if (jscoverage_isInvertedMode) {
+ jscoverage_removeTab('browser');
+ }
+
+ if (! jscoverage_isServer) {
+ jscoverage_removeTab('store');
+ }
+ }
+
+ jscoverage_initTabControl();
+
+ jscoverage_initTabContents(location.search);
+}
+
+function jscoverage_body_resize() {
+ if (/MSIE/.test(navigator.userAgent)) {
+ jscoverage_setSize();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 1
+
+function jscoverage_updateBrowser() {
+ var input = document.getElementById("location");
+ frames[0].location = input.value;
+}
+
+function jscoverage_input_keypress(e) {
+ if (e.keyCode === 13) {
+ jscoverage_updateBrowser();
+ }
+}
+
+function jscoverage_button_click() {
+ jscoverage_updateBrowser();
+}
+
+function jscoverage_browser_load() {
+ /* update the input box */
+ var input = document.getElementById("location");
+
+ /* sometimes IE seems to fire this after the tab has been removed */
+ if (input) {
+ input.value = frames[0].location;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 2
+
+function jscoverage_createLink(file, line) {
+ var link = document.createElement("a");
+
+ var url;
+ var call;
+ var text;
+ if (line) {
+ url = file + ".jscoverage.html?" + line;
+ call = "jscoverage_get('" + file + "', " + line + ");";
+ text = line.toString();
+ }
+ else {
+ url = file + ".jscoverage.html";
+ call = "jscoverage_get('" + file + "');";
+ text = file;
+ }
+
+ link.setAttribute('href', 'javascript:' + call);
+ link.appendChild(document.createTextNode(text));
+
+ return link;
+}
+
+function jscoverage_recalculateSummaryTab(cc) {
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+
+ if (! cc) {
+ cc = window._$jscoverage;
+ }
+ if (! cc) {
+//#JSCOVERAGE_IF 0
+ throw "No coverage information found.";
+//#JSCOVERAGE_ENDIF
+ }
+
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+
+ var totals = { files:0, statements:0, executed:0, coverage:0, skipped:0 };
+
+ var file;
+ var files = [];
+ for (file in cc) {
+ files.push(file);
+ }
+ files.sort();
+
+ var rowCounter = 0;
+ for (var f = 0; f < files.length; f++) {
+ file = files[f];
+ var lineNumber;
+ var num_statements = 0;
+ var num_executed = 0;
+ var missing = [];
+ var fileCC = cc[file];
+ var length = fileCC.length;
+ var currentConditionalEnd = 0;
+ var conditionals = null;
+ if (fileCC.conditionals) {
+ conditionals = fileCC.conditionals;
+ }
+ for (lineNumber = 0; lineNumber < length; lineNumber++) {
+ var n = fileCC[lineNumber];
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) {
+ currentConditionalEnd = conditionals[lineNumber];
+ }
+
+ if (currentConditionalEnd !== 0) {
+ continue;
+ }
+
+ if (n === undefined || n === null) {
+ continue;
+ }
+
+ if (n === 0) {
+ missing.push(lineNumber);
+ }
+ else {
+ num_executed++;
+ }
+ num_statements++;
+ }
+
+ var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
+
+ var row = document.createElement("tr");
+ row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" );
+
+ var cell = document.createElement("td");
+ cell.className = 'leftColumn';
+ var link = jscoverage_createLink(file);
+ cell.appendChild(link);
+
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_statements));
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_executed));
+ row.appendChild(cell);
+
+ // new coverage td containing a bar graph
+ cell = document.createElement("td");
+ cell.className = 'coverage';
+ var pctGraph = document.createElement("div"),
+ covered = document.createElement("div"),
+ pct = document.createElement("span");
+ pctGraph.className = "pctGraph";
+ if( num_statements === 0 ) {
+ covered.className = "skipped";
+ pct.appendChild(document.createTextNode("N/A"));
+ } else {
+ covered.className = "covered";
+ covered.style.width = percentage + "px";
+ pct.appendChild(document.createTextNode(percentage + '%'));
+ }
+ pct.className = "pct";
+ pctGraph.appendChild(covered);
+ cell.appendChild(pctGraph);
+ cell.appendChild(pct);
+ row.appendChild(cell);
+
+ if (showMissingColumn) {
+ cell = document.createElement("td");
+ for (var i = 0; i < missing.length; i++) {
+ if (i !== 0) {
+ cell.appendChild(document.createTextNode(", "));
+ }
+ link = jscoverage_createLink(file, missing[i]);
+ cell.appendChild(link);
+ }
+ row.appendChild(cell);
+ }
+
+ tbody.appendChild(row);
+
+ totals['files'] ++;
+ totals['statements'] += num_statements;
+ totals['executed'] += num_executed;
+ totals['coverage'] += percentage;
+ if( num_statements === 0 ) {
+ totals['skipped']++;
+ }
+
+ // write totals data into summaryTotals row
+ var tr = document.getElementById("summaryTotals");
+ if (tr) {
+ var tds = tr.getElementsByTagName("td");
+ tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files'];
+ tds[1].firstChild.nodeValue = totals['statements'];
+ tds[2].firstChild.nodeValue = totals['executed'];
+
+ var coverage = parseInt(totals['coverage'] / ( totals['files'] - totals['skipped'] ) );
+ if( isNaN( coverage ) ) {
+ coverage = 0;
+ }
+ tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%';
+ tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px';
+ }
+
+ }
+ jscoverage_endLengthyOperation();
+}
+
+function jscoverage_appendMissingColumn() {
+ var headerRow = document.getElementById('headerRow');
+ var missingHeader = document.createElement('th');
+ missingHeader.id = 'missingHeader';
+ missingHeader.innerHTML = '<abbr title="List of statements missed during execution">Missing</abbr>';
+ headerRow.appendChild(missingHeader);
+ var summaryTotals = document.getElementById('summaryTotals');
+ var empty = document.createElement('td');
+ empty.id = 'missingCell';
+ summaryTotals.appendChild(empty);
+}
+
+function jscoverage_removeMissingColumn() {
+ var missingNode;
+ missingNode = document.getElementById('missingHeader');
+ missingNode.parentNode.removeChild(missingNode);
+ missingNode = document.getElementById('missingCell');
+ missingNode.parentNode.removeChild(missingNode);
+}
+
+function jscoverage_checkbox_click() {
+ if (jscoverage_inLengthyOperation) {
+ return false;
+ }
+ jscoverage_beginLengthyOperation();
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+ setTimeout(function() {
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+ else {
+ jscoverage_removeMissingColumn();
+ }
+ jscoverage_recalculateSummaryTab();
+ }, 50);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// tab 3
+
+function jscoverage_makeTable() {
+ var coverage = _$jscoverage[jscoverage_currentFile];
+ var lines = coverage.source;
+
+ // this can happen if there is an error in the original JavaScript file
+ if (! lines) {
+ lines = [];
+ }
+
+ var rows = ['<table id="sourceTable">'];
+ var i = 0;
+ var progressBar = document.getElementById('progressBar');
+ var tableHTML;
+ var currentConditionalEnd = 0;
+
+ function joinTableRows() {
+ tableHTML = rows.join('');
+ ProgressBar.setPercentage(progressBar, 60);
+ /*
+ This may be a long delay, so set a timeout of 100 ms to make sure the
+ display is updated.
+ */
+ setTimeout(appendTable, 100);
+ }
+
+ function appendTable() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = tableHTML;
+ ProgressBar.setPercentage(progressBar, 80);
+ setTimeout(jscoverage_scrollToLine, 0);
+ }
+
+ while (i < lines.length) {
+ var lineNumber = i + 1;
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) {
+ currentConditionalEnd = coverage.conditionals[lineNumber];
+ }
+
+ var row = '<tr>';
+ row += '<td class="numeric">' + lineNumber + '</td>';
+ var timesExecuted = coverage[lineNumber];
+ if (timesExecuted !== undefined && timesExecuted !== null) {
+ if (currentConditionalEnd !== 0) {
+ row += '<td class="y numeric">';
+ }
+ else if (timesExecuted === 0) {
+ row += '<td class="r numeric" id="line-' + lineNumber + '">';
+ }
+ else {
+ row += '<td class="g numeric">';
+ }
+ row += timesExecuted;
+ row += '</td>';
+ }
+ else {
+ row += '<td></td>';
+ }
+ row += '<td><pre>' + lines[i] + '</pre></td>';
+ row += '</tr>';
+ row += '\n';
+ rows[lineNumber] = row;
+ i++;
+ }
+ rows[i + 1] = '</table>';
+ ProgressBar.setPercentage(progressBar, 40);
+ setTimeout(joinTableRows, 0);
+}
+
+function jscoverage_scrollToLine() {
+ jscoverage_selectTab('sourceTab');
+ if (! window.jscoverage_currentLine) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var div = document.getElementById('sourceDiv');
+ if (jscoverage_currentLine === 1) {
+ div.scrollTop = 0;
+ }
+ else {
+ var cell = document.getElementById('line-' + jscoverage_currentLine);
+
+ // this might not be there if there is an error in the original JavaScript
+ if (cell) {
+ var divOffset = jscoverage_findPos(div);
+ var cellOffset = jscoverage_findPos(cell);
+ div.scrollTop = cellOffset - divOffset;
+ }
+ }
+ jscoverage_currentLine = 0;
+ jscoverage_endLengthyOperation();
+}
+
+/**
+Loads the given file (and optional line) in the source tab.
+*/
+function jscoverage_get(file, line) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ jscoverage_selectTab('sourceTab');
+ if (file === jscoverage_currentFile) {
+ jscoverage_currentLine = line;
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ if (jscoverage_currentFile === null) {
+ var tab = document.getElementById('sourceTab');
+ tab.className = '';
+ tab.onclick = jscoverage_tab_click;
+ }
+ jscoverage_currentFile = file;
+ jscoverage_currentLine = line || 1; // when changing the source, always scroll to top
+ var fileDiv = document.getElementById('fileDiv');
+ fileDiv.innerHTML = jscoverage_currentFile;
+ jscoverage_recalculateSourceTab();
+ return;
+ }
+ }, 50);
+}
+
+/**
+Calculates coverage statistics for the current source file.
+*/
+function jscoverage_recalculateSourceTab() {
+ if (! jscoverage_currentFile) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.innerHTML = 'Calculating coverage ...';
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 20);
+ setTimeout(jscoverage_makeTable, 0);
+}
+
+// -----------------------------------------------------------------------------
+// tabs
+
+/**
+Initializes the tab control. This function must be called when the document is
+loaded.
+*/
+function jscoverage_initTabControl() {
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child.className !== 'disabled') {
+ child.onclick = jscoverage_tab_click;
+ }
+ tabNum++;
+ }
+ }
+ jscoverage_selectTab(0);
+}
+
+/**
+Selects a tab.
+@param tab the integer index of the tab (0, 1, 2, or 3)
+ OR
+ the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_selectTab(tab) {
+ if (typeof tab !== 'number') {
+ tab = jscoverage_tabIndexOf(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var tabPages = document.getElementById('tabPages');
+ var nodeList;
+ var tabNum;
+ var i;
+ var node;
+
+ nodeList = tabs.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (node.className !== 'disabled') {
+ if (tabNum === tab) {
+ node.className = 'selected';
+ }
+ else {
+ node.className = '';
+ }
+ }
+ tabNum++;
+ }
+
+ nodeList = tabPages.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (tabNum === tab) {
+ node.className = 'selected TabPage';
+ }
+ else {
+ node.className = 'TabPage';
+ }
+ tabNum++;
+ }
+}
+
+/**
+Returns an integer (0, 1, 2, or 3) representing the index of a given tab.
+@param tab the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_tabIndexOf(tab) {
+ if (typeof tab === 'string') {
+ tab = document.getElementById(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child === tab) {
+ return tabNum;
+ }
+ tabNum++;
+ }
+ }
+//#JSCOVERAGE_IF 0
+ throw "Tab not found";
+//#JSCOVERAGE_ENDIF
+}
+
+function jscoverage_tab_click(e) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ var target;
+//#JSCOVERAGE_IF
+ if (e) {
+ target = e.target;
+ }
+ else if (window.event) {
+ // IE
+ target = window.event.srcElement;
+ }
+ if (target.className === 'selected') {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ if (target.id === 'summaryTab') {
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+ }
+ else if (target.id === 'sourceTab') {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ }
+ jscoverage_selectTab(target);
+ if (target.id === 'summaryTab') {
+ jscoverage_recalculateSummaryTab();
+ }
+ else if (target.id === 'sourceTab') {
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ jscoverage_endLengthyOperation();
+ }
+ }, 50);
+}
+
+// -----------------------------------------------------------------------------
+// progress bar
+
+var ProgressBar = {
+ init: function(element) {
+ element._percentage = 0;
+
+ /* doing this via JavaScript crashes Safari */
+/*
+ var pctGraph = document.createElement('div');
+ pctGraph.className = 'pctGraph';
+ element.appendChild(pctGraph);
+ var covered = document.createElement('div');
+ covered.className = 'covered';
+ pctGraph.appendChild(covered);
+ var pct = document.createElement('span');
+ pct.className = 'pct';
+ element.appendChild(pct);
+*/
+
+ ProgressBar._update(element);
+ },
+ setPercentage: function(element, percentage) {
+ element._percentage = percentage;
+ ProgressBar._update(element);
+ },
+ _update: function(element) {
+ var pctGraph = element.getElementsByTagName('div').item(0);
+ var covered = pctGraph.getElementsByTagName('div').item(0);
+ var pct = element.getElementsByTagName('span').item(0);
+ pct.innerHTML = element._percentage.toString() + '%';
+ covered.style.width = element._percentage + 'px';
+ }
+};
+
+// -----------------------------------------------------------------------------
+// reports
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_serializeCoverageToJSON() {
+ var json = [];
+ for (var file in _$jscoverage) {
+ var coverage = _$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(jscoverage_quote(file) + ':[' + array.join(',') + ']');
+ }
+ return '{' + json.join(',') + '}';
+}
+
+function jscoverage_storeButton_click() {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+
+ jscoverage_beginLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'visible';
+
+ var request = jscoverage_createRequest();
+ request.open('POST', '/jscoverage-store', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ var message;
+ try {
+ if (request.status !== 200 && request.status !== 201 && request.status !== 204) {
+ throw request.status;
+ }
+ message = request.responseText;
+ }
+ catch (e) {
+ if (e.toString().search(/^\d{3}$/) === 0) {
+ message = e + ': ' + request.responseText;
+ }
+ else {
+ message = 'Could not connect to server: ' + e;
+ }
+ }
+
+ jscoverage_endLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'hidden';
+
+ var div = document.getElementById('storeDiv');
+ div.appendChild(document.createTextNode(new Date() + ': ' + message));
+ div.appendChild(document.createElement('br'));
+ }
+ };
+ request.setRequestHeader('Content-Type', 'application/json');
+ var json = jscoverage_serializeCoverageToJSON();
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js
new file mode 100644
index 0000000..5ea28fc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented-inverted/script.js
@@ -0,0 +1,65 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['script.js']) {
+ _$jscoverage['script.js'] = [];
+ _$jscoverage['script.js'][1] = 0;
+ _$jscoverage['script.js'][2] = 0;
+ _$jscoverage['script.js'][3] = 0;
+ _$jscoverage['script.js'][4] = 0;
+ _$jscoverage['script.js'][6] = 0;
+ _$jscoverage['script.js'][7] = 0;
+ _$jscoverage['script.js'][9] = 0;
+ _$jscoverage['script.js'][10] = 0;
+ _$jscoverage['script.js'][12] = 0;
+ _$jscoverage['script.js'][13] = 0;
+ _$jscoverage['script.js'][15] = 0;
+ _$jscoverage['script.js'][16] = 0;
+ _$jscoverage['script.js'][17] = 0;
+ _$jscoverage['script.js'][18] = 0;
+ _$jscoverage['script.js'][19] = 0;
+}
+_$jscoverage['script.js'][1]++;
+function go(element) {
+ _$jscoverage['script.js'][2]++;
+ var message;
+ _$jscoverage['script.js'][3]++;
+ if (element.id === "radio1") {
+ _$jscoverage['script.js'][4]++;
+ message = "You selected the number 1.";
+ }
+ else {
+ _$jscoverage['script.js'][6]++;
+ if (element.id === "radio2") {
+ _$jscoverage['script.js'][7]++;
+ message = "You selected the number 2.";
+ }
+ else {
+ _$jscoverage['script.js'][9]++;
+ if (element.id === "radio3") {
+ _$jscoverage['script.js'][10]++;
+ message = "You selected the number 3.";
+ }
+ else {
+ _$jscoverage['script.js'][12]++;
+ if (element.id === "radio4") {
+ _$jscoverage['script.js'][13]++;
+ message = "You selected the number 4.";
+ }
+ }
+ }
+ }
+ _$jscoverage['script.js'][15]++;
+ var div = document.getElementById("request");
+ _$jscoverage['script.js'][16]++;
+ div.className = "black";
+ _$jscoverage['script.js'][17]++;
+ div = document.getElementById("result");
+ _$jscoverage['script.js'][18]++;
+ div.innerHTML = "<p>" + message + "</p>";
+ _$jscoverage['script.js'][19]++;
+ div.innerHTML += "<p>If you are running the instrumented version of this program, you can click the \"Coverage report\" button to view a coverage report.</p>";
+}
+_$jscoverage['script.js'].source = ["<span class=\"k\">function</span> go<span class=\"k\">(</span>element<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> message<span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio1'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 1.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio2'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 2.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio3'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 3.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio4'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 4.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">var</span> div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'request'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>className <span class=\"k\">=</span> <span class=\"s\">'black'</span><span class=\"k\">;</span>"," div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'result'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">=</span> <span class=\"s\">'&lt;p&gt;'</span> <span class=\"k\">+</span> message <span class=\"k\">+</span> <span class=\"s\">'&lt;/p&gt;'</span><span class=\"k\">;</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">+=</span> <span class=\"s\">'&lt;p&gt;If you are running the instrumented version of this program, you can click the \"Coverage report\" button to view a coverage report.&lt;/p&gt;'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html
new file mode 100644
index 0000000..e7230b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Example</title>
+<script type="text/javascript" src="script.js"></script>
+<style>
+div.black {
+ color: black;
+}
+div.red {
+ color: red;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="request" class="red">Please select your favorite number:</div>
+<input type="radio" name="number" id="radio1" onclick="go(this);"><label for="radio1">One</label><br>
+<input type="radio" name="number" id="radio2" onclick="go(this);"><label for="radio2">Two</label><br>
+<input type="radio" name="number" id="radio3" onclick="go(this);"><label for="radio3">Three</label><br>
+<input type="radio" name="number" id="radio4" onclick="go(this);"><label for="radio4">Four</label><br>
+<div id="result" class="red"></div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css
new file mode 100644
index 0000000..31a4695
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-highlight.css
@@ -0,0 +1,38 @@
+/*
+ jscoverage-highlight.css - JSCoverage syntax highlighting style sheet
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* keyword, type, symbol, cbracket */
+#sourceTable .k {
+ font-weight: bold;
+}
+
+/* string, regexp, number */
+#sourceTable .s {
+ color: #006400;
+}
+
+/* specialchar */
+#sourceTable .t {
+ color: #2e8b57;
+}
+
+/* comment */
+#sourceTable .c {
+ font-style: italic;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css
new file mode 100644
index 0000000..afb2b80
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-ie.css
@@ -0,0 +1,89 @@
+#headingDiv {
+ position: static;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 0.5em;
+}
+
+#tabs {
+ clear: all;
+ position: static;
+ top: auto;
+ left: auto;
+ right: auto;
+ height: auto;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+#tabs div {
+ position: relative;
+ height: auto;
+ line-height: normal;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+#tabs div.selected {
+ padding-bottom: 6px;
+ z-index: 2;
+}
+
+.TabPage {
+ position: relative;
+ top: -1px;
+ left: auto;
+ right: auto;
+ bottom: auto;
+ clear: left;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 10px;
+ z-index: 1;
+}
+
+#locationDiv {
+ margin-bottom: 10px;
+}
+
+#iframeDiv {
+ position: static;
+ width: 100%;
+}
+
+#summaryDiv {
+ position: static;
+ width: 100%;
+}
+
+#fileDiv {
+ margin-bottom: 10px;
+}
+
+#sourceDiv {
+ position: static;
+ width: 100%;
+}
+
+#storeDiv {
+ position: static;
+ width: 100%;
+}
+
+/* some defaults */
+
+.TabPage {
+ height: 650px;
+}
+
+#iframeDiv {
+ height: 600px;
+}
+
+#summaryDiv {
+ height: 600px;
+}
+
+#sourceDiv {
+ height: 600px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif
new file mode 100644
index 0000000..f13c0b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage-throbber.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css
new file mode 100644
index 0000000..98af69b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.css
@@ -0,0 +1,328 @@
+/*
+ jscoverage.css - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+body {
+ background-color: #bfffbf;
+ font-family: sans-serif;
+ font-size: 100%;
+ margin: 0;
+}
+
+#mainDiv {
+ font-size: 0.8125em;
+}
+
+#headingDiv {
+ position: absolute;
+ top: 0.5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 0;
+ line-height: 1.5em;
+}
+
+h1 {
+ float: left;
+ margin: 0;
+ padding-bottom: 0.5em;
+ font-size: 1.3em;
+}
+
+.ProgressBar {
+ float: left;
+ visibility: hidden;
+}
+
+.ProgressPercentage {
+ display: block;
+ float: left;
+ width: 5em;
+ text-align: right;
+}
+
+.ProgressGraph {
+ float: left;
+ width: 100px;
+ height: 10px;
+ border: 1px solid black;
+ margin-top: 0.3em;
+ background-color: #d4d0c8;
+ overflow: hidden;
+}
+
+.ProgressCovered {
+ /* windows system color ActiveCaption or Highlight */
+ background-color: #0a246a;
+ width: 0;
+ height: 10px;
+ overflow: hidden;
+}
+
+#progressLabel {
+ display: block;
+ float: left;
+ padding-left: 0.3em;
+}
+
+/*******************************************************************************
+browser tab
+*/
+
+input#location, button {
+ border: 1px solid black;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+#iframeDiv {
+ position: absolute;
+ top: 3.5em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+}
+
+iframe {
+ width: 100%;
+ height: 100%;
+}
+
+/*******************************************************************************
+summary tab
+*/
+
+#summaryDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#summaryTable {
+ width: 100%;
+ margin-left: 0px;
+ margin-right: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+table#summaryTable th, table#summaryTable td {
+ border-left: 1px solid #d9d9d9;
+}
+
+table#summaryTable th.leftColumn, table#summaryTable td.leftColumn {
+ border-left-width: 0px;
+}
+
+table#summaryTable th, table#summaryTable td {
+ padding: 2px;
+}
+
+th {
+ background-color: #e6ffe6;
+}
+
+td.numeric {
+ text-align: right;
+}
+
+abbr {
+ cursor: help;
+}
+
+tr#summaryTotals td.leftColumn span {
+ float: right;
+}
+tr#summaryTotals td.leftColumn span.title {
+ float: left;
+ font-weight: bold;
+}
+tr#summaryTotals td {
+ background-color: #ffd;
+}
+td.coverage {
+ width: 150px;
+}
+td.coverage span {
+ float: right;
+ margin-right: 5px;
+}
+.pctGraph {
+ width: 100px;
+ height: 10px;
+ float: right;
+ border: 1px solid #000;
+ background-color: #e00000;
+ overflow: hidden;
+ margin-top: 4px;
+}
+.pctGraph .covered {
+ background-color: #00f000;
+ width: 0;
+ height: 10px;
+}
+.pctGraph .skipped {
+ background-color: #d4d0c8;
+ width: 100px;
+ height: 10px;
+}
+tbody#summaryTbody tr.even td {
+ background-color: #e6ffe6;
+}
+
+/*******************************************************************************
+source tab
+*/
+
+#fileDiv {
+ font-size: large;
+ font-weight: bold;
+}
+
+#sourceDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#sourceTable {
+ border: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+/*
+IE default behavior is to make <pre> smaller than surrounding text. Because
+the table already has font-size small, this would make the font-size within the
+<pre> x-small. So we don't rely on the default.
+*/
+table#sourceTable pre {
+ font-size: medium;
+}
+
+table#sourceTable td {
+ border: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table#sourceTable pre {
+ border: 0px;
+ margin: 0px;
+}
+
+.g {
+ background-color: #bfffbf;
+}
+
+.y {
+ background-color: #ffffbf;
+}
+
+.r {
+ background-color: #ffbfbf;
+}
+
+/*******************************************************************************
+store tab
+*/
+
+#storeDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+/*******************************************************************************
+about tab
+*/
+
+p {
+ margin-top: 0;
+}
+
+/*******************************************************************************
+tabs
+*/
+
+#tabs {
+ position: absolute;
+ top: 3em;
+ left: 1.5em;
+ right: 1.5em;
+ height: 2em;
+}
+
+#tabs div {
+ background-color: white;
+ position: relative;
+ float: left;
+ border: 1px solid black;
+ border-bottom-width: 0;
+ cursor: pointer;
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ height: 2em;
+ z-index: 1;
+ line-height: 1.8em;
+}
+
+#tabs div.selected {
+ z-index: 3;
+ cursor: default;
+}
+
+#tabs div.disabled {
+ /* windows system color GrayText */
+ color: #808080;
+ cursor: default;
+}
+
+.TabPage {
+ background-color: white;
+ border: 1px solid black;
+ position: absolute;
+ top: 5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 1.5em;
+ z-index: 2;
+ padding: 1em;
+ display: none;
+}
+
+#tabPages div.selected {
+ display: block;
+}
+
+img {
+ visibility: hidden;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html
new file mode 100644
index 0000000..601f62a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+ jscoverage.html - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<html>
+<head>
+<title>JSCoverage</title>
+<link rel="stylesheet" type="text/css" href="jscoverage-highlight.css">
+<link rel="stylesheet" type="text/css" href="jscoverage.css">
+<!--[if IE]>
+<link rel="stylesheet" type="text/css" href="jscoverage-ie.css">
+<![endif]-->
+<script type="text/javascript" src="jscoverage.js"></script>
+</head>
+
+<body onload="jscoverage_body_load();" onresize="jscoverage_body_resize();">
+<div id="mainDiv">
+<div id="headingDiv">
+<h1>JSCoverage</h1>
+<div class="ProgressBar" id="progressBar"><span class="ProgressPercentage"></span><div class="ProgressGraph"><div class="ProgressCovered"></div></div></div>
+<span id="progressLabel"></span>
+</div>
+
+<div id="tabs" class="Tabs">
+ <div id="browserTab"><img src="jscoverage-throbber.gif" alt=""> Browser <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="summaryTab"><img id="summaryThrobber" src="jscoverage-throbber.gif" alt=""> Summary <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="sourceTab" class="disabled"><img src="jscoverage-throbber.gif" alt=""> Source <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="storeTab"><img id="storeThrobber" src="jscoverage-throbber.gif" alt=""> Store <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="aboutTab"><img src="jscoverage-throbber.gif" alt=""> About <img src="jscoverage-throbber.gif" alt=""></div>
+</div>
+<div id="tabPages" class="TabPages">
+ <div class="TabPage" id="browserTabPage">
+ <div id="locationDiv">
+ URL: <input id="location" type="text" size="70" onkeypress="jscoverage_input_keypress(event)">
+ <button onclick="jscoverage_button_click();">Go</button>
+ </div>
+ <div id="iframeDiv">
+ <iframe id="browserIframe" onload="jscoverage_browser_load();"></iframe>
+ </div>
+ </div>
+ <div class="TabPage">
+ <input type="checkbox" id="checkbox" onclick="return jscoverage_checkbox_click();"> <label for="checkbox">Show missing statements column</label>
+ <div id="summaryDiv">
+ <div id="summaryErrorDiv"></div>
+ <table id="summaryTable">
+ <thead>
+ <tr id="headerRow">
+ <th class="leftColumn">File</th>
+ <th><abbr title="The total number of executable statements">Statements</abbr></th>
+ <th><abbr title="The number of statements actually executed">Executed</abbr></th>
+ <th><abbr title="Number of executed statements as a percentage of total number of statements">Coverage</abbr></th>
+ </tr>
+ <tr id="summaryTotals">
+ <td class="leftColumn">
+ <span class="title">Total:</span>
+ <span>0</span>
+ </td>
+ <td class="numeric">0</td>
+ <td class="numeric">0</td>
+ <td class="coverage">
+ <div class="pctGraph">
+ <div class="covered"></div>
+ </div>
+ <span class="pct">0%</span>
+ </td>
+ </tr>
+
+ </thead>
+ <tbody id="summaryTbody">
+
+ <!--
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ <td>0</td>
+ <td>0%</td>
+ <td>0</td>
+ </tr>
+ -->
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="TabPage">
+ <div id="fileDiv"></div>
+ <div id="sourceDiv"></div>
+ </div>
+ <div class="TabPage" id="storeTabPage">
+ <button id="storeButton" onclick="jscoverage_storeButton_click();">Store Report</button>
+ <img id="storeImg" src="jscoverage-throbber.gif" alt="loading...">
+ <div id="storeDiv"></div>
+ </div>
+ <div class="TabPage">
+ <p>
+ This is version 0.4 of JSCoverage, a program that calculates code
+ coverage statistics for JavaScript.
+ </p>
+ <p>
+ See <a href="http://siliconforks.com/jscoverage/">http://siliconforks.com/jscoverage/</a> for more information.
+ </p>
+ <p>
+ Copyright &copy; 2007, 2008 siliconforks.com
+ </p>
+ </div>
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js
new file mode 100644
index 0000000..9e2ea5b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/jscoverage.js
@@ -0,0 +1,1024 @@
+/*
+ jscoverage.js - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/**
+Initializes the _$jscoverage object in a window. This should be the first
+function called in the page.
+@param w this should always be the global window object
+*/
+function jscoverage_init(w) {
+ try {
+ // in Safari, "import" is a syntax error
+ Components.utils['import']('resource://gre/modules/jscoverage.jsm');
+ jscoverage_isInvertedMode = true;
+ return;
+ }
+ catch (e) {}
+
+ if (w.opener && w.opener.top._$jscoverage) {
+ // we are in inverted mode
+ jscoverage_isInvertedMode = true;
+ if (! w._$jscoverage) {
+ w._$jscoverage = w.opener.top._$jscoverage;
+ }
+ }
+ else {
+ // we are not in inverted mode
+ jscoverage_isInvertedMode = false;
+ if (! w._$jscoverage) {
+ w._$jscoverage = {};
+ }
+ }
+}
+
+var jscoverage_currentFile = null;
+var jscoverage_currentLine = null;
+
+var jscoverage_inLengthyOperation = false;
+
+/*
+Possible states:
+ isInvertedMode isServer isReport tabs
+normal false false false Browser
+inverted true false false
+server, normal false true false Browser, Store
+server, inverted true true false Store
+report false false true
+*/
+var jscoverage_isInvertedMode = false;
+var jscoverage_isServer = false;
+var jscoverage_isReport = false;
+
+jscoverage_init(window);
+
+function jscoverage_createRequest() {
+ // Note that the IE7 XMLHttpRequest does not support file URL's.
+ // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html
+ // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ return new XMLHttpRequest();
+ }
+}
+
+// http://www.quirksmode.org/js/findpos.html
+function jscoverage_findPos(obj) {
+ var result = 0;
+ do {
+ result += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ while (obj);
+ return result;
+}
+
+// http://www.quirksmode.org/viewport/compatibility.html
+function jscoverage_getViewportHeight() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ if (self.innerHeight) {
+ // all except Explorer
+ return self.innerHeight;
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ // Explorer 6 Strict Mode
+ return document.documentElement.clientHeight;
+ }
+ else if (document.body) {
+ // other Explorers
+ return document.body.clientHeight;
+ }
+ else {
+ throw "Couldn't calculate viewport height";
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Indicates visually that a lengthy operation has begun. The progress bar is
+displayed, and the cursor is changed to busy (on browsers which support this).
+*/
+function jscoverage_beginLengthyOperation() {
+ jscoverage_inLengthyOperation = true;
+
+ var progressBar = document.getElementById('progressBar');
+ progressBar.style.visibility = 'visible';
+ ProgressBar.setPercentage(progressBar, 0);
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'visible';
+
+ /* blacklist buggy browsers */
+//#JSCOVERAGE_IF
+ if (! /Opera|WebKit/.test(navigator.userAgent)) {
+ /*
+ Change the cursor style of each element. Note that changing the class of the
+ element (to one with a busy cursor) is buggy in IE.
+ */
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = 'wait';
+ }
+ }
+}
+
+/**
+Removes the progress bar and busy cursor.
+*/
+function jscoverage_endLengthyOperation() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 100);
+ setTimeout(function() {
+ jscoverage_inLengthyOperation = false;
+ progressBar.style.visibility = 'hidden';
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'hidden';
+ progressLabel.innerHTML = '';
+
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = '';
+ }
+ }, 50);
+}
+
+function jscoverage_setSize() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ var viewportHeight = jscoverage_getViewportHeight();
+
+ /*
+ border-top-width: 1px
+ padding-top: 10px
+ padding-bottom: 10px
+ border-bottom-width: 1px
+ margin-bottom: 10px
+ ----
+ 32px
+ */
+ var tabPages = document.getElementById('tabPages');
+ var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px';
+ var nodeList = tabPages.childNodes;
+ var length = nodeList.length;
+ for (var i = 0; i < length; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ node.style.height = tabPageHeight;
+ }
+
+ var iframeDiv = document.getElementById('iframeDiv');
+ // may not exist if we have removed the first tab
+ if (iframeDiv) {
+ iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px';
+ }
+
+ var summaryDiv = document.getElementById('summaryDiv');
+ summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px';
+
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px';
+
+ var storeDiv = document.getElementById('storeDiv');
+ if (storeDiv) {
+ storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px';
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off',
+and '0' (upper or lower case) are false.
+@param s the string
+@return a boolean value
+*/
+function jscoverage_getBooleanValue(s) {
+ s = s.toLowerCase();
+ if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') {
+ return false;
+ }
+ return true;
+}
+
+function jscoverage_removeTab(id) {
+ var tab = document.getElementById(id + 'Tab');
+ tab.parentNode.removeChild(tab);
+ var tabPage = document.getElementById(id + 'TabPage');
+ tabPage.parentNode.removeChild(tabPage);
+}
+
+/**
+Initializes the contents of the tabs. This sets the initial values of the
+input field and iframe in the "Browser" tab and the checkbox in the "Summary"
+tab.
+@param queryString this should always be location.search
+*/
+function jscoverage_initTabContents(queryString) {
+ var showMissingColumn = false;
+ var parameters, parameter, i, index, url, name, value;
+ if (queryString.length > 0) {
+ // chop off the question mark
+ queryString = queryString.substring(1);
+ parameters = queryString.split(/&|;/);
+ for (i = 0; i < parameters.length; i++) {
+ parameter = parameters[i];
+ index = parameter.indexOf('=');
+ if (index === -1) {
+ // still works with old syntax
+ url = parameter;
+ }
+ else {
+ name = parameter.substr(0, index);
+ value = parameter.substr(index + 1);
+ if (name === 'missing' || name === 'm') {
+ showMissingColumn = jscoverage_getBooleanValue(value);
+ }
+ else if (name === 'url' || name === 'u') {
+ url = value;
+ }
+ }
+ }
+ }
+
+ var checkbox = document.getElementById('checkbox');
+ checkbox.checked = showMissingColumn;
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+
+ // this will automatically propagate to the input field
+ if (url) {
+ frames[0].location = url;
+ }
+
+ // if the browser tab is absent, we have to initialize the summary tab
+ if (! document.getElementById('browserTab')) {
+ jscoverage_recalculateSummaryTab();
+ }
+}
+
+function jscoverage_body_load() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.init(progressBar);
+
+ function reportError(e) {
+ jscoverage_endLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'hidden';
+ var div = document.getElementById('summaryErrorDiv');
+ div.innerHTML = 'Error: ' + e;
+ }
+
+ if (jscoverage_isReport) {
+ jscoverage_beginLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'visible';
+ var request = jscoverage_createRequest();
+ try {
+ request.open('GET', 'jscoverage.json', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ try {
+ if (request.status !== 0 && request.status !== 200) {
+ throw request.status;
+ }
+ var response = request.responseText;
+ if (response === '') {
+ throw 404;
+ }
+ var json = eval('(' + response + ')');
+ var file;
+ for (file in json) {
+ var fileCoverage = json[file];
+ _$jscoverage[file] = fileCoverage.coverage;
+ _$jscoverage[file].source = fileCoverage.source;
+ }
+ jscoverage_recalculateSummaryTab();
+ summaryThrobber.style.visibility = 'hidden';
+ }
+ catch (e) {
+ reportError(e);
+ }
+ }
+ };
+ request.send(null);
+ }
+ catch (e) {
+ reportError(e);
+ }
+
+ jscoverage_removeTab('browser');
+ jscoverage_removeTab('store');
+ }
+ else {
+ if (jscoverage_isInvertedMode) {
+ jscoverage_removeTab('browser');
+ }
+
+ if (! jscoverage_isServer) {
+ jscoverage_removeTab('store');
+ }
+ }
+
+ jscoverage_initTabControl();
+
+ jscoverage_initTabContents(location.search);
+}
+
+function jscoverage_body_resize() {
+ if (/MSIE/.test(navigator.userAgent)) {
+ jscoverage_setSize();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 1
+
+function jscoverage_updateBrowser() {
+ var input = document.getElementById("location");
+ frames[0].location = input.value;
+}
+
+function jscoverage_input_keypress(e) {
+ if (e.keyCode === 13) {
+ jscoverage_updateBrowser();
+ }
+}
+
+function jscoverage_button_click() {
+ jscoverage_updateBrowser();
+}
+
+function jscoverage_browser_load() {
+ /* update the input box */
+ var input = document.getElementById("location");
+
+ /* sometimes IE seems to fire this after the tab has been removed */
+ if (input) {
+ input.value = frames[0].location;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 2
+
+function jscoverage_createLink(file, line) {
+ var link = document.createElement("a");
+
+ var url;
+ var call;
+ var text;
+ if (line) {
+ url = file + ".jscoverage.html?" + line;
+ call = "jscoverage_get('" + file + "', " + line + ");";
+ text = line.toString();
+ }
+ else {
+ url = file + ".jscoverage.html";
+ call = "jscoverage_get('" + file + "');";
+ text = file;
+ }
+
+ link.setAttribute('href', 'javascript:' + call);
+ link.appendChild(document.createTextNode(text));
+
+ return link;
+}
+
+function jscoverage_recalculateSummaryTab(cc) {
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+
+ if (! cc) {
+ cc = window._$jscoverage;
+ }
+ if (! cc) {
+//#JSCOVERAGE_IF 0
+ throw "No coverage information found.";
+//#JSCOVERAGE_ENDIF
+ }
+
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+
+ var totals = { files:0, statements:0, executed:0, coverage:0, skipped:0 };
+
+ var file;
+ var files = [];
+ for (file in cc) {
+ files.push(file);
+ }
+ files.sort();
+
+ var rowCounter = 0;
+ for (var f = 0; f < files.length; f++) {
+ file = files[f];
+ var lineNumber;
+ var num_statements = 0;
+ var num_executed = 0;
+ var missing = [];
+ var fileCC = cc[file];
+ var length = fileCC.length;
+ var currentConditionalEnd = 0;
+ var conditionals = null;
+ if (fileCC.conditionals) {
+ conditionals = fileCC.conditionals;
+ }
+ for (lineNumber = 0; lineNumber < length; lineNumber++) {
+ var n = fileCC[lineNumber];
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) {
+ currentConditionalEnd = conditionals[lineNumber];
+ }
+
+ if (currentConditionalEnd !== 0) {
+ continue;
+ }
+
+ if (n === undefined || n === null) {
+ continue;
+ }
+
+ if (n === 0) {
+ missing.push(lineNumber);
+ }
+ else {
+ num_executed++;
+ }
+ num_statements++;
+ }
+
+ var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
+
+ var row = document.createElement("tr");
+ row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" );
+
+ var cell = document.createElement("td");
+ cell.className = 'leftColumn';
+ var link = jscoverage_createLink(file);
+ cell.appendChild(link);
+
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_statements));
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_executed));
+ row.appendChild(cell);
+
+ // new coverage td containing a bar graph
+ cell = document.createElement("td");
+ cell.className = 'coverage';
+ var pctGraph = document.createElement("div"),
+ covered = document.createElement("div"),
+ pct = document.createElement("span");
+ pctGraph.className = "pctGraph";
+ if( num_statements === 0 ) {
+ covered.className = "skipped";
+ pct.appendChild(document.createTextNode("N/A"));
+ } else {
+ covered.className = "covered";
+ covered.style.width = percentage + "px";
+ pct.appendChild(document.createTextNode(percentage + '%'));
+ }
+ pct.className = "pct";
+ pctGraph.appendChild(covered);
+ cell.appendChild(pctGraph);
+ cell.appendChild(pct);
+ row.appendChild(cell);
+
+ if (showMissingColumn) {
+ cell = document.createElement("td");
+ for (var i = 0; i < missing.length; i++) {
+ if (i !== 0) {
+ cell.appendChild(document.createTextNode(", "));
+ }
+ link = jscoverage_createLink(file, missing[i]);
+ cell.appendChild(link);
+ }
+ row.appendChild(cell);
+ }
+
+ tbody.appendChild(row);
+
+ totals['files'] ++;
+ totals['statements'] += num_statements;
+ totals['executed'] += num_executed;
+ totals['coverage'] += percentage;
+ if( num_statements === 0 ) {
+ totals['skipped']++;
+ }
+
+ // write totals data into summaryTotals row
+ var tr = document.getElementById("summaryTotals");
+ if (tr) {
+ var tds = tr.getElementsByTagName("td");
+ tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files'];
+ tds[1].firstChild.nodeValue = totals['statements'];
+ tds[2].firstChild.nodeValue = totals['executed'];
+
+ var coverage = parseInt(totals['coverage'] / ( totals['files'] - totals['skipped'] ) );
+ if( isNaN( coverage ) ) {
+ coverage = 0;
+ }
+ tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%';
+ tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px';
+ }
+
+ }
+ jscoverage_endLengthyOperation();
+}
+
+function jscoverage_appendMissingColumn() {
+ var headerRow = document.getElementById('headerRow');
+ var missingHeader = document.createElement('th');
+ missingHeader.id = 'missingHeader';
+ missingHeader.innerHTML = '<abbr title="List of statements missed during execution">Missing</abbr>';
+ headerRow.appendChild(missingHeader);
+ var summaryTotals = document.getElementById('summaryTotals');
+ var empty = document.createElement('td');
+ empty.id = 'missingCell';
+ summaryTotals.appendChild(empty);
+}
+
+function jscoverage_removeMissingColumn() {
+ var missingNode;
+ missingNode = document.getElementById('missingHeader');
+ missingNode.parentNode.removeChild(missingNode);
+ missingNode = document.getElementById('missingCell');
+ missingNode.parentNode.removeChild(missingNode);
+}
+
+function jscoverage_checkbox_click() {
+ if (jscoverage_inLengthyOperation) {
+ return false;
+ }
+ jscoverage_beginLengthyOperation();
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+ setTimeout(function() {
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+ else {
+ jscoverage_removeMissingColumn();
+ }
+ jscoverage_recalculateSummaryTab();
+ }, 50);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// tab 3
+
+function jscoverage_makeTable() {
+ var coverage = _$jscoverage[jscoverage_currentFile];
+ var lines = coverage.source;
+
+ // this can happen if there is an error in the original JavaScript file
+ if (! lines) {
+ lines = [];
+ }
+
+ var rows = ['<table id="sourceTable">'];
+ var i = 0;
+ var progressBar = document.getElementById('progressBar');
+ var tableHTML;
+ var currentConditionalEnd = 0;
+
+ function joinTableRows() {
+ tableHTML = rows.join('');
+ ProgressBar.setPercentage(progressBar, 60);
+ /*
+ This may be a long delay, so set a timeout of 100 ms to make sure the
+ display is updated.
+ */
+ setTimeout(appendTable, 100);
+ }
+
+ function appendTable() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = tableHTML;
+ ProgressBar.setPercentage(progressBar, 80);
+ setTimeout(jscoverage_scrollToLine, 0);
+ }
+
+ while (i < lines.length) {
+ var lineNumber = i + 1;
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) {
+ currentConditionalEnd = coverage.conditionals[lineNumber];
+ }
+
+ var row = '<tr>';
+ row += '<td class="numeric">' + lineNumber + '</td>';
+ var timesExecuted = coverage[lineNumber];
+ if (timesExecuted !== undefined && timesExecuted !== null) {
+ if (currentConditionalEnd !== 0) {
+ row += '<td class="y numeric">';
+ }
+ else if (timesExecuted === 0) {
+ row += '<td class="r numeric" id="line-' + lineNumber + '">';
+ }
+ else {
+ row += '<td class="g numeric">';
+ }
+ row += timesExecuted;
+ row += '</td>';
+ }
+ else {
+ row += '<td></td>';
+ }
+ row += '<td><pre>' + lines[i] + '</pre></td>';
+ row += '</tr>';
+ row += '\n';
+ rows[lineNumber] = row;
+ i++;
+ }
+ rows[i + 1] = '</table>';
+ ProgressBar.setPercentage(progressBar, 40);
+ setTimeout(joinTableRows, 0);
+}
+
+function jscoverage_scrollToLine() {
+ jscoverage_selectTab('sourceTab');
+ if (! window.jscoverage_currentLine) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var div = document.getElementById('sourceDiv');
+ if (jscoverage_currentLine === 1) {
+ div.scrollTop = 0;
+ }
+ else {
+ var cell = document.getElementById('line-' + jscoverage_currentLine);
+
+ // this might not be there if there is an error in the original JavaScript
+ if (cell) {
+ var divOffset = jscoverage_findPos(div);
+ var cellOffset = jscoverage_findPos(cell);
+ div.scrollTop = cellOffset - divOffset;
+ }
+ }
+ jscoverage_currentLine = 0;
+ jscoverage_endLengthyOperation();
+}
+
+/**
+Loads the given file (and optional line) in the source tab.
+*/
+function jscoverage_get(file, line) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ jscoverage_selectTab('sourceTab');
+ if (file === jscoverage_currentFile) {
+ jscoverage_currentLine = line;
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ if (jscoverage_currentFile === null) {
+ var tab = document.getElementById('sourceTab');
+ tab.className = '';
+ tab.onclick = jscoverage_tab_click;
+ }
+ jscoverage_currentFile = file;
+ jscoverage_currentLine = line || 1; // when changing the source, always scroll to top
+ var fileDiv = document.getElementById('fileDiv');
+ fileDiv.innerHTML = jscoverage_currentFile;
+ jscoverage_recalculateSourceTab();
+ return;
+ }
+ }, 50);
+}
+
+/**
+Calculates coverage statistics for the current source file.
+*/
+function jscoverage_recalculateSourceTab() {
+ if (! jscoverage_currentFile) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.innerHTML = 'Calculating coverage ...';
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 20);
+ setTimeout(jscoverage_makeTable, 0);
+}
+
+// -----------------------------------------------------------------------------
+// tabs
+
+/**
+Initializes the tab control. This function must be called when the document is
+loaded.
+*/
+function jscoverage_initTabControl() {
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child.className !== 'disabled') {
+ child.onclick = jscoverage_tab_click;
+ }
+ tabNum++;
+ }
+ }
+ jscoverage_selectTab(0);
+}
+
+/**
+Selects a tab.
+@param tab the integer index of the tab (0, 1, 2, or 3)
+ OR
+ the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_selectTab(tab) {
+ if (typeof tab !== 'number') {
+ tab = jscoverage_tabIndexOf(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var tabPages = document.getElementById('tabPages');
+ var nodeList;
+ var tabNum;
+ var i;
+ var node;
+
+ nodeList = tabs.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (node.className !== 'disabled') {
+ if (tabNum === tab) {
+ node.className = 'selected';
+ }
+ else {
+ node.className = '';
+ }
+ }
+ tabNum++;
+ }
+
+ nodeList = tabPages.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (tabNum === tab) {
+ node.className = 'selected TabPage';
+ }
+ else {
+ node.className = 'TabPage';
+ }
+ tabNum++;
+ }
+}
+
+/**
+Returns an integer (0, 1, 2, or 3) representing the index of a given tab.
+@param tab the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_tabIndexOf(tab) {
+ if (typeof tab === 'string') {
+ tab = document.getElementById(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child === tab) {
+ return tabNum;
+ }
+ tabNum++;
+ }
+ }
+//#JSCOVERAGE_IF 0
+ throw "Tab not found";
+//#JSCOVERAGE_ENDIF
+}
+
+function jscoverage_tab_click(e) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ var target;
+//#JSCOVERAGE_IF
+ if (e) {
+ target = e.target;
+ }
+ else if (window.event) {
+ // IE
+ target = window.event.srcElement;
+ }
+ if (target.className === 'selected') {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ if (target.id === 'summaryTab') {
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+ }
+ else if (target.id === 'sourceTab') {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ }
+ jscoverage_selectTab(target);
+ if (target.id === 'summaryTab') {
+ jscoverage_recalculateSummaryTab();
+ }
+ else if (target.id === 'sourceTab') {
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ jscoverage_endLengthyOperation();
+ }
+ }, 50);
+}
+
+// -----------------------------------------------------------------------------
+// progress bar
+
+var ProgressBar = {
+ init: function(element) {
+ element._percentage = 0;
+
+ /* doing this via JavaScript crashes Safari */
+/*
+ var pctGraph = document.createElement('div');
+ pctGraph.className = 'pctGraph';
+ element.appendChild(pctGraph);
+ var covered = document.createElement('div');
+ covered.className = 'covered';
+ pctGraph.appendChild(covered);
+ var pct = document.createElement('span');
+ pct.className = 'pct';
+ element.appendChild(pct);
+*/
+
+ ProgressBar._update(element);
+ },
+ setPercentage: function(element, percentage) {
+ element._percentage = percentage;
+ ProgressBar._update(element);
+ },
+ _update: function(element) {
+ var pctGraph = element.getElementsByTagName('div').item(0);
+ var covered = pctGraph.getElementsByTagName('div').item(0);
+ var pct = element.getElementsByTagName('span').item(0);
+ pct.innerHTML = element._percentage.toString() + '%';
+ covered.style.width = element._percentage + 'px';
+ }
+};
+
+// -----------------------------------------------------------------------------
+// reports
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_serializeCoverageToJSON() {
+ var json = [];
+ for (var file in _$jscoverage) {
+ var coverage = _$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(jscoverage_quote(file) + ':[' + array.join(',') + ']');
+ }
+ return '{' + json.join(',') + '}';
+}
+
+function jscoverage_storeButton_click() {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+
+ jscoverage_beginLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'visible';
+
+ var request = jscoverage_createRequest();
+ request.open('POST', '/jscoverage-store', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ var message;
+ try {
+ if (request.status !== 200 && request.status !== 201 && request.status !== 204) {
+ throw request.status;
+ }
+ message = request.responseText;
+ }
+ catch (e) {
+ if (e.toString().search(/^\d{3}$/) === 0) {
+ message = e + ': ' + request.responseText;
+ }
+ else {
+ message = 'Could not connect to server: ' + e;
+ }
+ }
+
+ jscoverage_endLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'hidden';
+
+ var div = document.getElementById('storeDiv');
+ div.appendChild(document.createTextNode(new Date() + ': ' + message));
+ div.appendChild(document.createElement('br'));
+ }
+ };
+ request.setRequestHeader('Content-Type', 'application/json');
+ var json = jscoverage_serializeCoverageToJSON();
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js
new file mode 100644
index 0000000..ac233a2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/instrumented/script.js
@@ -0,0 +1,65 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['script.js']) {
+ _$jscoverage['script.js'] = [];
+ _$jscoverage['script.js'][1] = 0;
+ _$jscoverage['script.js'][2] = 0;
+ _$jscoverage['script.js'][3] = 0;
+ _$jscoverage['script.js'][4] = 0;
+ _$jscoverage['script.js'][6] = 0;
+ _$jscoverage['script.js'][7] = 0;
+ _$jscoverage['script.js'][9] = 0;
+ _$jscoverage['script.js'][10] = 0;
+ _$jscoverage['script.js'][12] = 0;
+ _$jscoverage['script.js'][13] = 0;
+ _$jscoverage['script.js'][15] = 0;
+ _$jscoverage['script.js'][16] = 0;
+ _$jscoverage['script.js'][17] = 0;
+ _$jscoverage['script.js'][18] = 0;
+ _$jscoverage['script.js'][19] = 0;
+}
+_$jscoverage['script.js'][1]++;
+function go(element) {
+ _$jscoverage['script.js'][2]++;
+ var message;
+ _$jscoverage['script.js'][3]++;
+ if (element.id === "radio1") {
+ _$jscoverage['script.js'][4]++;
+ message = "You selected the number 1.";
+ }
+ else {
+ _$jscoverage['script.js'][6]++;
+ if (element.id === "radio2") {
+ _$jscoverage['script.js'][7]++;
+ message = "You selected the number 2.";
+ }
+ else {
+ _$jscoverage['script.js'][9]++;
+ if (element.id === "radio3") {
+ _$jscoverage['script.js'][10]++;
+ message = "You selected the number 3.";
+ }
+ else {
+ _$jscoverage['script.js'][12]++;
+ if (element.id === "radio4") {
+ _$jscoverage['script.js'][13]++;
+ message = "You selected the number 4.";
+ }
+ }
+ }
+ }
+ _$jscoverage['script.js'][15]++;
+ var div = document.getElementById("request");
+ _$jscoverage['script.js'][16]++;
+ div.className = "black";
+ _$jscoverage['script.js'][17]++;
+ div = document.getElementById("result");
+ _$jscoverage['script.js'][18]++;
+ div.innerHTML = "<p>" + message + "</p>";
+ _$jscoverage['script.js'][19]++;
+ div.innerHTML += "<p>If you are running the instrumented version of this program, you can click the \"Summary\" tab to view a coverage report.</p>";
+}
+_$jscoverage['script.js'].source = ["<span class=\"k\">function</span> go<span class=\"k\">(</span>element<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> message<span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio1'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 1.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio2'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 2.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio3'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 3.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>element<span class=\"k\">.</span>id <span class=\"k\">===</span> <span class=\"s\">'radio4'</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," message <span class=\"k\">=</span> <span class=\"s\">'You selected the number 4.'</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">var</span> div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'request'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>className <span class=\"k\">=</span> <span class=\"s\">'black'</span><span class=\"k\">;</span>"," div <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">'result'</span><span class=\"k\">);</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">=</span> <span class=\"s\">'&lt;p&gt;'</span> <span class=\"k\">+</span> message <span class=\"k\">+</span> <span class=\"s\">'&lt;/p&gt;'</span><span class=\"k\">;</span>"," div<span class=\"k\">.</span>innerHTML <span class=\"k\">+=</span> <span class=\"s\">'&lt;p&gt;If you are running the instrumented version of this program, you can click the \"Summary\" tab to view a coverage report.&lt;/p&gt;'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/license.html b/tools/node_modules/expresso/deps/jscoverage/doc/license.html
new file mode 100644
index 0000000..0acc7a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/license.html
@@ -0,0 +1,382 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - license</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+<h2>License</h2>
+<pre>
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ &lt;one line to give the program's name and a brief idea of what it does.&gt;
+ Copyright (C) &lt;year&gt; &lt;name of author&gt;
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ &lt;signature of Ty Coon&gt;, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+</pre>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li>License
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/links.html b/tools/node_modules/expresso/deps/jscoverage/doc/links.html
new file mode 100644
index 0000000..df6d793
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/links.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - links</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>Links</h2>
+ <p>
+ The design of JSCoverage has been influenced by other code coverage tools:
+ </p>
+ <dl>
+ <dt><a href="http://gcc.gnu.org/onlinedocs/gcc/Gcov.html">gcov</a>
+ <dd>Code coverage for C/C++.
+ <dt><a href="http://cobertura.sourceforge.net/">Cobertura</a>
+ <dd>Code coverage for Java.
+ <dt><a href="http://nedbatchelder.com/code/modules/coverage.html">coverage.py</a>
+ <dd>Code coverage for Python.
+ </dl>
+ <p>
+ The implementation of JSCoverage includes the following libraries:
+ </p>
+ <dl>
+ <dt><a href="https://developer.mozilla.org/en/SpiderMonkey">Mozilla SpiderMonkey</a>
+ <dd>JSCoverage uses Mozilla's JavaScript implementation to parse JavaScript.
+ </dl>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li>Links
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/manual.html b/tools/node_modules/expresso/deps/jscoverage/doc/manual.html
new file mode 100644
index 0000000..61d8e9e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/manual.html
@@ -0,0 +1,701 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage user manual</title>
+<link rel="stylesheet" type="text/css" href="sh_nedit.min.css">
+<link rel="stylesheet" type="text/css" href="doc.css">
+<script type="text/javascript" src="sh_main.min.js"></script>
+<script type="text/javascript" src="sh_html.min.js"></script>
+<script type="text/javascript" src="sh_javascript.min.js"></script>
+</head>
+<body onload="sh_highlightDocument();">
+
+<h1>JSCoverage user manual</h1>
+
+<p>
+JSCoverage is a tool that measures code coverage for JavaScript programs.
+</p>
+
+<p>
+JSCoverage works by adding instrumentation to JavaScript code before it is
+executed in a web browser. JSCoverage provides several alternative ways of doing
+this:
+</p>
+
+<ul>
+<li>The simplest method is to use the <code>jscoverage</code> program to generate
+instrumented JavaScript files.
+</li>
+<li>Alternatively, you can use the <code>jscoverage-server</code> program, a simple web server that instruments
+JavaScript code as it is served.
+</li>
+<li>Finally, <code>jscoverage-server</code> can be run with the <code>--proxy</code> option to
+act as a proxy server which instruments any JavaScript code proxied through it.
+</li>
+</ul>
+
+<p>
+The <code>jscoverage-server</code> program (with or without the <code>--proxy</code>
+option) has the advantage of being able to store coverage reports to the filesystem.
+</p>
+
+<h2>Compiling JSCoverage</h2>
+
+<p>
+You can compile JSCoverage on GNU/Linux or Microsoft Windows, using the GCC C++ compiler (<code>g++</code>). On
+Windows you will require <a href="http://cygwin.com/">Cygwin</a> or <a
+href="http://mingw.org/">MinGW/MSYS</a>.
+</p>
+
+<p>
+You can extract and compile the code with the following commands:
+</p>
+
+<pre>
+tar jxvf jscoverage-0.4.tar.bz2
+cd jscoverage-0.4/
+./configure
+make
+</pre>
+
+<p>
+This will create the <code>jscoverage</code> and <code>jscoverage-server</code>
+executables (<code>jscoverage.exe</code> and <code>jscoverage-server.exe</code>
+on Windows). You can install the executables in <code>/usr/local</code> with the
+command:
+</p>
+
+<pre>
+make install
+</pre>
+
+<p>
+Alternatively, you may simply copy the <code>jscoverage</code> executable and/or
+the <code>jscoverage-server</code> executable to a suitable location in your
+<code>PATH</code>.
+</p>
+
+<h2>Using the <code>jscoverage</code> program</h2>
+
+<p>
+To demonstrate how the <code>jscoverage</code> program works, we will use the
+trivial example JavaScript code located in the
+<code>doc/example/</code> directory of the JSCoverage distribution. You can run
+this example by viewing the file <code>doc/example/index.html</code> in your web browser.
+</p>
+
+<p>
+Generating code coverage statistics for this example using the
+<code>jscoverage</code> program involves the following steps:
+</p>
+
+<h3>1. Instrumenting code</h3>
+
+<p>
+The first step is to add instrumentation to your JavaScript code. You do this by
+executing <code>jscoverage</code> with two arguments:
+</p>
+
+<pre>
+jscoverage <var>SOURCE-DIRECTORY</var> <var>DESTINATION-DIRECTORY</var>
+</pre>
+
+<p>
+<var>SOURCE-DIRECTORY</var> is the directory containing the JavaScript code to be instrumented,
+and <var>DESTINATION-DIRECTORY</var> is the name of the
+directory to which <code>jscoverage</code> should output the instrumented code.
+The <code>jscoverage</code> program will create <var>DESTINATION-DIRECTORY</var> if necessary and (recursively) copy
+<var>SOURCE-DIRECTORY</var> to <var>DESTINATION-DIRECTORY</var>, instrumenting
+any files ending with a <code>.js</code> extension.
+</p>
+
+<p>
+The directory structure under <var>SOURCE-DIRECTORY</var> is preserved, so that if you have a file
+<code><var>SOURCE-DIRECTORY</var>/dir/index.html</code> referencing the script
+<code><var>SOURCE-DIRECTORY</var>/dir/script.js</code>, then
+<code>jscoverage</code> will create a copy of the HTML file at
+<code><var>DESTINATION-DIRECTORY</var>/dir/index.html</code> and an instrumented
+version of the script at
+<code><var>DESTINATION-DIRECTORY</var>/dir/script.js</code>.
+In addition, <code>jscoverage</code> creates a file called <code>jscoverage.html</code>
+which is used to execute the instrumented code.
+</p>
+
+<table>
+<tr>
+<td><pre>
+<var>SOURCE-DIRECTORY</var>/
+ dir/
+ index.html
+ script.js
+
+</pre></td>
+<td class="arrow">&rarr;</td>
+<td><pre>
+<var>DESTINATION-DIRECTORY</var>/
+ dir/
+ index.html
+ script.js [instrumented]
+ jscoverage.html
+</pre></td>
+</tr>
+</table>
+
+<p>
+For the example code in the <code>doc/example/</code> directory, you can execute the
+following command line from the top-level directory of the JSCoverage distribution:
+</p>
+
+<pre>
+jscoverage doc/example doc/instrumented
+</pre>
+
+<p>
+This will create the directory <code>doc/instrumented/</code> and place an
+instrumented copy of the code from <code>doc/example/</code> in
+<code>doc/instrumented/</code>.
+</p>
+
+<table>
+<tr>
+<td><pre>
+doc/example/
+ index.html
+ script.js
+
+</pre></td>
+<td class="arrow">&rarr;</td>
+<td><pre>
+doc/instrumented/
+ index.html
+ script.js [instrumented]
+ jscoverage.html
+</pre></td>
+</tr>
+</table>
+
+<h3>2. Executing the instrumented code in a web browser</h3>
+
+<p>
+Open the generated <code>jscoverage.html</code> file
+(<code>doc/instrumented/jscoverage.html</code>) in your web browser.
+The page contains a tabbed user interface:
+</p>
+
+<ul>
+<li>The "Browser" tab is used to display pages with instrumented scripts.
+<li>The "Summary" tab is used to display code coverage data.
+<li>The "Source" tab is used to display JavaScript code, showing the number of times
+each line of code was executed.
+<li>The "About" tab displays information about the current version of JSCoverage.
+</ul>
+
+<p><img src="screenshot.png" alt="Screenshot"></p>
+
+<p>
+The "Browser" tab contains an <code>&lt;iframe&gt;</code>, which is initially empty.
+You can load a page into this frame by
+entering its URL into the "URL" input field.
+You can load any page located in <code><var>DESTINATION-DIRECTORY</var>/</code>
+or a subdirectory underneath <code><var>DESTINATION-DIRECTORY</var>/</code>; loading a page
+from outside <code><var>DESTINATION-DIRECTORY</var>/</code>, or from a foreign web
+server, will give unexpected results.
+</p>
+
+<p>
+For example, you can load the file <code>doc/instrumented/index.html</code> by typing
+<code>index.html</code> in the "URL" input field (relative URLs are acceptable).
+</p>
+
+<p>
+Alternatively, you can load a page into the <code>&lt;iframe&gt;</code> by
+appending the page URL to the query string of the <code>jscoverage.html</code> URL.
+For example, appending <code>?index.html</code> to the <code>jscoverage.html</code> URL
+will cause the <code>index.html</code> file to be loaded automatically.
+</p>
+
+<p><img src="screenshot2.png" alt="Screenshot"></p>
+
+<p>
+For this example, the JavaScript does not execute automatically:
+you have to select one of the radio buttons to execute the code.
+</p>
+
+<p><img src="screenshot3.png" alt="Screenshot"></p>
+
+<h3>3. Generating a coverage report</h3>
+
+<p>
+Once the JavaScript code in the page in the "Browser" tab has been executed, click on
+the "Summary" tab. This will display the current code coverage statistics.
+</p>
+
+<p><img src="screenshot4.png" alt="Screenshot"></p>
+
+<p>
+You can click the checkbox to show a list of statements missed during execution.
+</p>
+
+<p><img src="screenshot5.png" alt="Screenshot"></p>
+
+<p>
+You can click one of the links to get a detailed view of a JavaScript source file.
+</p>
+
+<p><img src="screenshot6.png" alt="Screenshot"></p>
+
+<p>
+As long as you do not reload the
+<code>jscoverage.html</code> page, the coverage report statistics are
+cumulative. If you execute more JavaScript in the frame in the "Browser" tab (e.g., by clicking on a link to
+another scripted page, or by reloading the frame containing a scripted
+page) and switch to the "Summary" tab again,
+the coverage report will combine the statistics from the previous report with any newly generated statistics.
+Reloading <code>jscoverage.html</code> resets all code coverage statistics to zero.
+</p>
+
+<h2>Inverted mode</h2>
+
+<p>
+In some situations it may be difficult to execute your code within the
+JSCoverage "Browser" tab. For example, the code may assume that it is running in
+the top-level browser window, generating errors if it is executed from within a
+frame. JSCoverage has an alternative mode of operation, called <dfn>inverted
+mode</dfn>, which may be useful in this case.
+</p>
+
+<p>
+Normally you load <code>jscoverage.html</code> in your web browser, and in its
+"Browser" tab you launch your test code. In inverted mode, you do the
+opposite: you load your test page directly in your web browser, and from there
+you launch JSCoverage. To do this you need to add some code to your test page:
+</p>
+
+<pre class="sh_javascript">
+window.open('path/to/jscoverage.html');
+</pre>
+
+<p>
+The <code>"path/to/jscoverage.html"</code> should be a URL pointing to the
+location of the <code>jscoverage.html</code> file (remember, this will be in the
+top level of the <var>DESTINATION-DIRECTORY</var> you specified when running
+the <code>jscoverage</code> executable).
+</p>
+
+<p>
+You can place this code wherever you like in your page: for example, you could
+attach it to a button:
+</p>
+
+<pre class="sh_html">
+&lt;button onclick="window.open('path/to/jscoverage.html');"&gt;Coverage report&lt;/button&gt;
+</pre>
+
+<p>
+Note that you <em>must</em> use a <code>window.open</code> call; simply making a
+link to <code>jscoverage.html</code> is not sufficient.
+</p>
+
+<p>
+An example is located in the <code>doc/example-inverted</code> directory.
+You can instrument the code with the <code>jscoverage</code> program:
+</p>
+
+<pre>
+jscoverage doc/example-inverted doc/instrumented-inverted
+</pre>
+
+<p>
+You can load the page <code>doc/instrumented-inverted/index.html</code>
+directly in your web browser.
+From this page, you select one of the radio buttons and then click the "Coverage
+report" button to launch the JSCoverage report.
+</p>
+
+<p>
+Another example is located in the <code>doc/example-jsunit</code> directory.
+See the <a href="faq.html#jsunit">FAQ</a> for more information.
+</p>
+
+<h2><code>jscoverage</code> command line options</h2>
+
+<p>
+The <code>jscoverage</code> program accepts the following options:
+</p>
+
+<dl>
+<dt><code>-h</code>, <code>--help</code>
+<dd>Display a brief help message.
+<dt><code>-V</code>, <code>--version</code>
+<dd>Display the version of the program.
+<dt><code>-v</code>, <code>--verbose</code>
+<dd>Explain what is being done.
+<dt><code>--encoding=<var>ENCODING</var></code>
+<dd>Assume that all JavaScript files use the given character encoding. The
+default is ISO-8859-1.
+<dt><code>--exclude=<var>PATH</var></code>
+<dd>The command
+<pre>
+jscoverage --exclude=<var>PATH</var> <var>SOURCE-DIRECTORY</var> <var>DESTINATION-DIRECTORY</var>
+</pre>
+copies <var>SOURCE-DIRECTORY</var> to <var>DESTINATION-DIRECTORY</var>
+recursively, but does not copy <var>SOURCE-DIRECTORY</var>/<var>PATH</var>.
+<var>PATH</var> must be a complete path relative to <var>SOURCE-DIRECTORY</var>.
+<var>PATH</var> can be a file or a directory (in which case the directory and
+its entire contents are skipped). This option may be given multiple times.
+<dt><code>--js-version=<var>VERSION</var></code>
+<dd>Use the specified JavaScript version; valid values for <var>VERSION</var>
+are <code>1.0</code>, <code>1.1</code>, <code>1.2</code>, ..., <code>1.8</code>,
+or <code>ECMAv3</code> (the default).
+<dt><code>--no-highlight</code>
+<dd>Do not perform syntax highlighting of JavaScript code.
+<dt><code>--no-instrument=<var>PATH</var></code>
+<dd>The command
+<pre>
+jscoverage --no-instrument=<var>PATH</var> <var>SOURCE-DIRECTORY</var> <var>DESTINATION-DIRECTORY</var>
+</pre>
+copies <var>SOURCE-DIRECTORY</var> to <var>DESTINATION-DIRECTORY</var>
+recursively, but does not instrument any JavaScript code in
+<var>SOURCE-DIRECTORY</var>/<var>PATH</var>. <var>PATH</var> must be a complete
+path relative to <var>SOURCE-DIRECTORY</var>. <var>PATH</var> can be a
+(JavaScript) file or a directory (in which case any JavaScript files located
+anywhere underneath the directory are not instrumented). This option may be
+given multiple times.
+</dl>
+
+<h2>Query string options</h2>
+
+<p>
+When accessing <code>jscoverage.html</code> in a web browser, you may provide a
+query string consisting of options separated by ampersand (<code>&amp;</code>)
+or semicolon (<code>;</code>). Any option not containing an equals sign
+(<code>=</code>) is considered to be a URL which will be loaded in the "Browser"
+tab.
+</p>
+
+<dl>
+<dt><code>u=<var>URL</var></code>, <code>url=<var>URL</var></code>
+<dd>Load <var>URL</var> in the "Browser" tab. (This is the same as specifying
+an option without an equals sign.)
+<dt><code>m=<var>BOOLEAN</var></code>, <code>missing=<var>BOOLEAN</var></code>
+<dd>Determines whether to initially display the "Missing" column in the "Summary"
+tab. <var>BOOLEAN</var> can be
+<code>true</code>, <code>t</code>, <code>yes</code>, <code>y</code>, <code>on</code>, <code>1</code>
+(to display the "Missing" column), or
+<code>false</code>, <code>f</code>, <code>no</code>, <code>n</code>, <code>off</code>, <code>0</code>
+(to hide the "Missing" column). By default, the "Missing" column is not displayed.
+</dl>
+
+<h2>Using the <code>jscoverage-server</code> program</h2>
+
+<p>
+The <code>jscoverage-server</code> program is a simple web server. You can use
+<code>jscoverage-server</code> to serve files from the <code>doc/example/</code>
+directory:
+</p>
+
+<pre>
+ cd doc/example
+ jscoverage-server --verbose
+</pre>
+
+<p>
+Once the server is running, you can access the JSCoverage web interface by
+visiting the URL <code>http://127.0.0.1:8080/jscoverage.html</code>, and you can
+load the <code>doc/example/index.html</code> file by entering
+<code>index.html</code> in the "URL" input field. (Or you can do this all in
+one step by loading the URL
+<code>http://127.0.0.1:8080/jscoverage.html?index.html</code> in your web
+browser.) The
+<code>jscoverage-server</code> program automatically instruments any served
+JavaScript code, so that code coverage data will be gathered as the code is
+executed in your browser.
+</p>
+
+<p>
+The web interface is slightly different from that generated by the
+<code>jscoverage</code> program: it has a new tab named "Store".
+To store coverage data, click the "Store" tab.
+</p>
+
+<p><img src="screenshot7.png" alt="Screenshot"></p>
+
+<p>
+When you click the "Store Report" button, the coverage data will be saved to a directory named <code>jscoverage-report/</code>.
+You can view this stored report at any time by opening the file <code>jscoverage-report/jscoverage.html</code> in
+your web browser - you don't need the <code>jscoverage-server</code> running to access it.
+</p>
+
+<p>
+If you use the "Store" tab again to store coverage data, the new data will be merged with
+the previous data in the <code>jscoverage-report/</code> directory. This can be useful,
+for instance, if you wish to run a set of tests in different browsers and generate an
+aggregate report which combines the data for all of them.
+</p>
+
+<p>
+You can stop the server by running another instance of <code>jscoverage-server</code> with the
+<code>--shutdown</code> option:
+</p>
+
+<pre>
+ jscoverage-server --shutdown
+</pre>
+
+<h2>Using <code>jscoverage-server --proxy</code></h2>
+
+<p>
+To use <code>jscoverage-server</code> as a proxy server, use the <code>--proxy</code> option:
+</p>
+
+<pre>
+ jscoverage-server --verbose --proxy
+</pre>
+
+<p>
+Configure your browser to use an HTTP proxy with address 127.0.0.1 and port 8080.
+You can then generate code coverage data for a web page on the server <code>example.com</code>
+by accessing the JSCoverage web interface at the special URL <code>http://example.com/jscoverage.html</code>.
+Note that this URL is not provided by the <code>example.com</code> server; it is automatically generated
+by the proxy server whenever a URL with path <code>/jscoverage.html</code> is requested.
+</p>
+
+<h2><code>jscoverage-server</code> command line options</h2>
+
+<dl>
+<dt><code>-h</code>, <code>--help</code>
+<dd>Display a brief help message.
+<dt><code>-V</code>, <code>--version</code>
+<dd>Display the version of the program.
+<dt><code>-v</code>, <code>--verbose</code>
+<dd>Explain what is being done.
+<dt><code>--document-root=<var>PATH</var></code>
+<dd>Serve web content from the directory given by <var>PATH</var>. The default is
+the current directory. This option may not be given with the <code>--proxy</code> option.
+<dt><code>--encoding=<var>ENCODING</var></code>
+<dd>Assume that all JavaScript files use the given character encoding. The
+default is ISO-8859-1. Note that if you use the <code>--proxy</code> option, the
+character encoding will be determined from the <code>charset</code> parameter in
+the <code>Content-Type</code> HTTP header.
+<dt><code>--ip-address=<var>ADDRESS</var></code>
+<dd>Run the server on the IP address given by <var>ADDRESS</var>. The default is <code>127.0.0.1</code>. Specify
+<code>0.0.0.0</code> to use any address.
+<dt><code>--js-version=<var>VERSION</var></code>
+<dd>Use the specified JavaScript version; valid values for <var>VERSION</var>
+are <code>1.0</code>, <code>1.1</code>, <code>1.2</code>, ..., <code>1.8</code>,
+or <code>ECMAv3</code> (the default).
+<dt><code>--no-highlight</code>
+<dd>Do not perform syntax highlighting of JavaScript code.
+<dt><code>--no-instrument=<var>URL</var></code>
+<dd>Do not instrument JavaScript code from <var>URL</var>. If you are running <code>jscoverage-server</code>
+with the <code>--proxy</code> option, <var>URL</var> should be a full URL. For example:
+<pre>
+jscoverage-server --proxy --no-instrument=http://example.com/scripts/
+</pre>
+Without <code>--proxy</code>, <var>URL</var> should be only the path portion of a URL:
+<pre>
+jscoverage-server --no-instrument=/scripts/
+</pre>
+This option may be given multiple times.
+<dt><code>--port=<var>PORT</var></code>
+<dd>Run the server on the port given by <var>PORT</var>. The default is port 8080.
+<dt><code>--proxy</code>
+<dd>Run as a proxy server.
+<dt><code>--report-dir=<var>PATH</var></code>
+<dd>Use the directory given by <var>PATH</var> for storing coverage reports. The default is
+<code>jscoverage-report/</code> in the current directory.
+<dt><code>--shutdown</code>
+<dd>Stop a running instance of the server.
+</dl>
+
+<h2>Advanced topics</h2>
+
+<h3>Storing coverage reports programmatically</h3>
+
+<p>
+If you are executing a test suite using <code>jscoverage-server</code>, you can
+store a coverage report programmatically by having your test suite call the
+<code>jscoverage_report</code> function (automatically generated by
+<code>jscoverage-server</code>) after all your tests have finished running:
+</p>
+
+<pre class="sh_javascript">
+if (window.jscoverage_report) {
+ jscoverage_report();
+}
+</pre>
+
+<p>
+You can specify the name of the directory in which to store the report by
+passing the name as a parameter to the <code>jscoverage_report</code> function:
+</p>
+
+<pre class="sh_javascript">
+if (window.jscoverage_report) {
+ // determine the directory name based on the browser
+ var directory;
+ if (/MSIE/.test(navigator.userAgent)) {
+ directory = 'IE';
+ }
+ else {
+ directory = 'other';
+ }
+ jscoverage_report(directory);
+}
+</pre>
+
+<p>
+This directory will be a subdirectory under the <code>jscoverage-report/</code>
+directory (or whatever is specified with the <code>--report-dir</code> option).
+Using the above example, the report would be stored to either
+<code>jscoverage-report/IE/</code> or <code>jscoverage-report/other/</code>.
+</p>
+
+<p>
+It is not necessary that your test suite be executed within the
+<code>jscoverage.html</code> web interface to store a coverage report. The URL
+of the test suite can simply be loaded directly in a web browser.
+</p>
+
+<p>
+The example in <code>doc/example-jsunit/</code> demonstrates storing coverage
+reports programmatically.
+</p>
+
+<h3>Ignoring certain lines of code</h3>
+
+<p>
+Sometimes you may wish to exclude certain lines of code from coverage
+statistics. Some lines of code may be executed only in certain browsers; other
+lines should never be executed at all (they may be present only to detect
+programming errors). You can use specially formatted comments in your code to
+tell JSCoverage to ignore certain lines of code. These lines will not be
+included in the JSCoverage "Summary" tab; in the "Source" tab, these lines will
+be indicated with the color yellow.
+</p>
+
+<p>
+These comments take the following form:
+</p>
+
+<pre class="sh_javascript">
+//#JSCOVERAGE_IF <var>CONDITION</var>
+...
+//#JSCOVERAGE_ENDIF
+</pre>
+
+<p>
+The comment must be formatted exactly as shown: it must be a line comment
+starting with <code>//</code>, it must start in the first column, and it must be
+followed by <code>#JSCOVERAGE_IF</code> or <code>#JSCOVERAGE_ENDIF</code> in
+uppercase letters with no intervening white space.
+</p>
+
+<p>
+The <var>CONDITION</var> is an ordinary JavaScript expression; if this
+expression evaluates to <code>true</code>, then the lines of code between the
+<code>//#JSCOVERAGE_IF</code> and <code>//#JSCOVERAGE_ENDIF</code> comments are
+included in coverage statistics; otherwise, they are excluded from coverage
+statistics.
+</p>
+
+<p>
+For example:
+</p>
+
+<pre class="sh_javascript">
+function log(s) {
+ if (window.console) {
+//#JSCOVERAGE_IF window.console
+ console.log(s);
+//#JSCOVERAGE_ENDIF
+ }
+}
+</pre>
+
+<p>
+You can exclude code from coverage statistics unconditionally by using
+<code>#JSCOVERAGE_IF 0</code> or <code>#JSCOVERAGE_IF false</code>:
+</p>
+
+<pre class="sh_javascript">
+function f(x) {
+ if (x === null) {
+//#JSCOVERAGE_IF 0
+ throw 'error';
+//#JSCOVERAGE_ENDIF
+ }
+ ...
+</pre>
+
+<p>
+There is also a short form, which must appear on the line preceding an
+<code>if</code> statement:
+</p>
+
+<pre class="sh_javascript">
+//#JSCOVERAGE_IF
+if (...) {
+ ...
+}
+else if (...) {
+ ...
+}
+...
+else {
+ ...
+}
+</pre>
+
+<p>
+
+In this form, there is no condition on the <code>//#JSCOVERAGE_IF</code> line
+and no <code>//#JSCOVERAGE_ENDIF</code>. You use this form to tell JSCoverage
+that you expect only one branch of the <code>if</code> statement to be executed;
+coverage statistics will not be collected for the other branch(es). For
+example:
+</p>
+
+<pre class="sh_javascript">
+function log(s) {
+//#JSCOVERAGE_IF
+ if (window.console) {
+ console.log(s);
+ }
+ else if (window.opera) {
+ opera.postError(s);
+ }
+ else {
+ throw 'no logging function available';
+ }
+}
+</pre>
+
+<p>
+Currently, <code>//#JSCOVERAGE_IF</code> comments are not recorded in stored coverage reports.
+</p>
+
+<h2>Caveats</h2>
+
+<ul>
+<li>JSCoverage adds instrumentation to JavaScript code, which will slow down execution speed.
+Expect instrumented code to take at least twice as much time to run.
+<li>JSCoverage currently instruments only <code>.js</code> files; it does not instrument code in <code>&lt;script&gt;</code>
+elements in HTML files.
+<li>HTML files must use relative URLs to reference scripts. If you use an absolute URL, your page will reference
+the original uninstrumented script rather than the instrumented one, and no code coverage data will be collected.
+<li>JSCoverage instruments physical lines of code rather than logical JavaScript statements; it works bests with code
+that has exactly one statement per line. If you put multiple statements on a line, or split a line across two or more
+statements, you may get strange results.
+<li>JSCoverage uses frames. Some web pages that use frames may not function properly when run under JSCoverage, especially
+those which try to access the top-level frame (<code>window.top</code>, <code>target="_top"</code>, etc.).
+<li>JSCoverage is distributed without any warranty. See the <a href="license.html">license</a> for more details.
+</ul>
+
+<address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+</address>
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/news.html b/tools/node_modules/expresso/deps/jscoverage/doc/news.html
new file mode 100644
index 0000000..c51450f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/news.html
@@ -0,0 +1,214 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - news</title>
+<link rel="alternate" type="application/rss+xml" href="http://siliconforks.com/jscoverage/news.xml" title="RSS feed for JSCoverage">
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+ <h2>News <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a></h2>
+
+ <h3><a name="20081211">December 11, 2008 - JSCoverage 0.4</a></h3>
+ <p>
+ JSCoverage 0.4 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release includes many new features:
+ </p>
+ <ul class="list">
+ <li>
+ The new <code>jscoverage-server</code> program is provided as an
+ alternative to the <code>jscoverage</code> program. The
+ <code>jscoverage-server</code> program is a simple HTTP server which
+ instruments JavaScript code as it is served; this allows you to execute
+ JavaScript and gather code coverage statistics without a preliminary
+ step of creating instrumented code. The <code>jscoverage-server</code>
+ program can either serve files directly from the filesystem or run as a
+ proxy server (with the <code>--proxy</code> option), instrumenting
+ JavaScript provided by another web server.
+ <li>
+ Using <code>jscoverage-server</code>, coverage reports can now be stored
+ to the filesystem.
+ </li>
+ <li>
+ JSCoverage now recognizes special JavaScript comments which specify that
+ certain lines of code should be ignored in coverage reports.
+ </li>
+ <li>
+ The new <code>--encoding</code> option provides better support for
+ different character encodings.
+ </li>
+ <li>
+ The JSCoverage user interface is now faster and more responsive.
+ </li>
+ <li>
+ The new <code>--no-highlight</code> option can be used to disable syntax
+ highlighting (giving better performance for large JavaScript files).
+ </li>
+ <li>
+ The build system has been modified so that <code>make install</code>
+ only installs the <code>jscoverage</code> and
+ <code>jscoverage-server</code> executables and their manual pages.
+ (Previous versions installed SpiderMonkey library and executable files,
+ which could conflict with other versions of SpiderMonkey installed on
+ your system.)
+ </li>
+ <li>
+ JSCoverage now supports several features beyond those found in the
+ <cite>ECMAScript Language Specification</cite>, including the following:
+ <ul class="list">
+ <li>getters and setters
+ <li><code>for each</code> loops
+ <li>generators and iterators
+ <li>the <code>let</code> keyword
+ <li>destructuring assignment
+ <li>array comprehensions
+ <li>expression closures
+ <li>generator expressions
+ </ul>
+ Use the new <code>--js-version</code> option to enable these features.
+ </li>
+ </ul>
+ <p>
+ The GCC C++ compiler (<code>g++</code>) is now required to compile
+ JSCoverage. (Previously, only the C compiler was needed.)
+ </p>
+ <p>
+ Please report any bugs you find using the new <a href="http://siliconforks.com/jscoverage/bugs/">bug tracker</a>.
+ </p>
+
+ <h3><a name="20080331">March 31, 2008 - JSCoverage and Firefox 3</a></h3>
+ <p>
+ The <a href="faq.html">JSCoverage FAQ</a> has been updated to address problems using JSCoverage with Firefox 3.
+ </p>
+
+ <h3><a name="20080324">March 24, 2008 - JSCoverage in Debian GNU/Linux</a></h3>
+ <p>
+ JSCoverage is now <a href="http://packages.debian.org/sid/jscoverage">available</a> in the Debian unstable distribution.
+ </p>
+
+ <h3><a name="20071122">November 22, 2007 - JSCoverage 0.3.1</a></h3>
+ <p>
+ JSCoverage 0.3.1 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release has a number of bug fixes:
+ </p>
+ <ul class="list">
+ <li>
+ It should now be possible to run the native Windows version of <code>jscoverage</code>
+ with minimal privileges.
+ </li>
+ <li>
+ All files used by JSCoverage now use a <code>jscoverage</code>
+ prefix to avoid name collisions.
+ </li>
+ <li>
+ Compilation bugs which occurred under some versions of MSYS have been fixed.
+ </li>
+ <li>
+ Various documentation improvements.
+ </li>
+ </ul>
+
+ <h3><a name="20070826">August 26, 2007 - JSCoverage 0.3</a></h3>
+ <p>
+ JSCoverage 0.3 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ This release has the following new features:
+ </p>
+ <ul class="list">
+ <li>
+ The coverage summary now displays bar graphs (thanks to Ross Simpson).
+ </li>
+ <li>
+ A progress bar is displayed for lengthy computations.
+ </li>
+ <li>
+ JavaScript syntax highlighting has improved.
+ </li>
+ <li>
+ The display of missed statements can be turned on and off.
+ </li>
+ <li>
+ New "inverted mode" provides better support for working with <a href="http://www.jsunit.net/">JsUnit</a>.
+ </li>
+ </ul>
+
+ <h3><a name="20070823">August 23, 2007 - JSCoverage in Linux Format magazine</a></h3>
+ <p>
+ JSCoverage is in the October 2007 issue of Linux Format magazine
+ (<a href="http://www.linuxformat.co.uk/modules.php?op=modload&amp;name=NewArchives&amp;issue=97">table of contents</a>).
+ </p>
+
+ <h3><a name="20070731">July 31, 2007 - Subversion repository now available</a></h3>
+ <p>
+ See the <a href="http://siliconforks.com/jscoverage/download.html">download page</a> for instructions on accessing the Subversion repository.
+ </p>
+
+ <h3><a name="20070708">July 8, 2007 - JSCoverage 0.2</a></h3>
+ <p>
+ JSCoverage 0.2 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ JSCoverage 0.2 features a new tabbed user interface.
+ </p>
+
+ <h3><a name="20070701">July 1, 2007 - JSCoverage 0.1.1</a></h3>
+ <p>
+ JSCoverage 0.1.1 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ <p>
+ JSCoverage 0.1.1 fixes a bug that can cause large JavaScript files to be truncated when viewed with Opera.
+ </p>
+
+ <h3><a name="20070615">June 15, 2007 - documentation of JSCoverage internals</a></h3>
+ <p>
+ A new document,
+ <a href="http://siliconforks.com/doc/parsing-javascript-with-spidermonkey/">Parsing JavaScript with SpiderMonkey</a>,
+ describes the technique used by JSCoverage to parse JavaScript programs.
+ </p>
+
+ <h3><a name="20070530">May 30, 2007 - new examples</a></h3>
+ <p>
+ Added some <a href="demo.html">examples</a> of running JSCoverage on popular JavaScript libraries.
+ </p>
+
+ <h3><a name="20070526">May 26, 2007 - JSCoverage 0.1</a></h3>
+ <p>
+ JSCoverage 0.1 is available for <a href="http://siliconforks.com/jscoverage/download.html">download</a>.
+ </p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li>News <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li><a href="users.html">Users</a>
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css b/tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css
new file mode 100644
index 0000000..b3e042c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/reset-fonts-grids.css
@@ -0,0 +1,7 @@
+/*
+Copyright (c) 2008, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License:
+http://developer.yahoo.net/yui/license.txt
+version: 2.6.0
+*/
+html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;min-width:750px;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;} .yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot.png
new file mode 100644
index 0000000..e523c8a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.png
new file mode 100644
index 0000000..2c02f49
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot2.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.png
new file mode 100644
index 0000000..d63c862
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot3.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.png
new file mode 100644
index 0000000..0dc234b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot4.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.png
new file mode 100644
index 0000000..ffbfabe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot5.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.png
new file mode 100644
index 0000000..b2c09d4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot6.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.png b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.png
new file mode 100644
index 0000000..2d51202
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/screenshot7.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js b/tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js
new file mode 100644
index 0000000..64472a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_html.min.js
@@ -0,0 +1 @@
+if(!this.sh_languages){this.sh_languages={}}sh_languages.html=[[[/<\?xml/g,"sh_preproc",1,1],[/<!DOCTYPE/g,"sh_preproc",3,1],[/<!--/g,"sh_comment",5],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",6,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",8,1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",2]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",4]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",5]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",7]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",9]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]]]; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js b/tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js
new file mode 100644
index 0000000..a7d930e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_javascript.min.js
@@ -0,0 +1 @@
+if(!this.sh_languages){this.sh_languages={}}sh_languages.javascript=[[[/\/(?:\\.|[^*\\\/])(?:\\.|[^\\\/])*\/[gim]*(?![*\/])/g,"sh_regexp",-1],[/\b(?:import|package)\b/g,"sh_preproc",-1],[/\/\/\//g,"sh_comment",1],[/\/\//g,"sh_comment",11],[/\/\*\*/g,"sh_comment",12],[/\/\*/g,"sh_comment",22],[/\b[+-]?(?:(?:0x[A-Fa-f0-9]+)|(?:(?:[\d]*\.)?[\d]+(?:[eE][+-]?[\d]+)?))u?(?:(?:int(?:8|16|32|64))|L)?\b/g,"sh_number",-1],[/"/g,"sh_string",23],[/'/g,"sh_string",24],[/(\b(?:class|interface))([ \t]+)([$A-Za-z0-9_]+)/g,["sh_keyword","sh_normal","sh_classname"],-1],[/\b(?:abstract|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|final|finally|for|function|goto|if|implements|in|instanceof|interface|native|new|null|private|protected|prototype|public|return|static|super|switch|synchronized|throw|throws|this|transient|true|try|typeof|var|volatile|while|with)\b/g,"sh_keyword",-1],[/\b(?:int|byte|boolean|char|long|float|double|short|void)\b/g,"sh_type",-1],[/~|!|%|\^|\*|\(|\)|-|\+|=|\[|\]|\\|:|;|,|\.|\/|\?|&|<|>|\|/g,"sh_symbol",-1],[/\{|\}/g,"sh_cbracket",-1],[/(?:[A-Za-z]|_)[A-Za-z0-9_]*(?=[ \t]*\()/g,"sh_function",-1]],[[/$/g,null,-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",2,1],[/<!DOCTYPE/g,"sh_preproc",4,1],[/<!--/g,"sh_comment",6],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",7,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",9,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",3]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",5]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",6]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",8]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",10]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/$/g,null,-2]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/<\?xml/g,"sh_preproc",13,1],[/<!DOCTYPE/g,"sh_preproc",15,1],[/<!--/g,"sh_comment",17],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z](?:[A-Za-z0-9_:.-]*)/g,"sh_keyword",18,1],[/&(?:[A-Za-z0-9]+);/g,"sh_preproc",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*(?:\/)?>/g,"sh_keyword",-1],[/<(?:\/)?[A-Za-z][A-Za-z0-9]*/g,"sh_keyword",20,1],[/@[A-Za-z]+/g,"sh_type",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/\?>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",14]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/>/g,"sh_preproc",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",16]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/-->/g,"sh_comment",-2],[/<!--/g,"sh_comment",17]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",19]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/(?:\/)?>/g,"sh_keyword",-2],[/([^=" \t>]+)([ \t]*)(=?)/g,["sh_type","sh_normal","sh_symbol"],-1],[/"/g,"sh_string",21]],[[/\\(?:\\|")/g,null,-1],[/"/g,"sh_string",-2]],[[/\*\//g,"sh_comment",-2],[/(?:<?)[A-Za-z0-9_\.\/\-_~]+@[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:<?)[A-Za-z0-9_]+:\/\/[A-Za-z0-9_\.\/\-_~]+(?:>?)/g,"sh_url",-1],[/(?:TODO|FIXME|BUG)(?:[:]?)/g,"sh_todo",-1]],[[/"/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]],[[/'/g,"sh_string",-2],[/\\./g,"sh_specialchar",-1]]]; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js b/tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js
new file mode 100644
index 0000000..5f5f944
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_main.min.js
@@ -0,0 +1,4 @@
+/* Copyright (C) 2007, 2008 gnombat@users.sourceforge.net */
+/* License: http://shjs.sourceforge.net/doc/gplv3.html */
+
+if(!this.sh_languages){this.sh_languages={}}var sh_requests={};function sh_isEmailAddress(A){if(/^mailto:/.test(A)){return false}return A.indexOf("@")!==-1}function sh_setHref(B,C,D){var A=D.substring(B[C-2].pos,B[C-1].pos);if(A.length>=2&&A.charAt(0)==="<"&&A.charAt(A.length-1)===">"){A=A.substr(1,A.length-2)}if(sh_isEmailAddress(A)){A="mailto:"+A}B[C-2].node.href=A}function sh_konquerorExec(B){var A=[""];A.index=B.length;A.input=B;return A}function sh_highlightString(V,L){if(/Konqueror/.test(navigator.userAgent)){if(!L.konquered){for(var b=0;b<L.length;b++){for(var d=0;d<L[b].length;d++){var c=L[b][d][0];if(c.source==="$"){c.exec=sh_konquerorExec}}}L.konquered=true}}var k=document.createElement("a");var M=document.createElement("span");var U=[];var H=0;var K=[];var W=0;var I=null;var R=function(i,a){var m=i.length;if(m===0){return }if(!a){var p=K.length;if(p!==0){var n=K[p-1];if(!n[3]){a=n[1]}}}if(I!==a){if(I){U[H++]={pos:W};if(I==="sh_url"){sh_setHref(U,H,V)}}if(a){var o;if(a==="sh_url"){o=k.cloneNode(false)}else{o=M.cloneNode(false)}o.className=a;U[H++]={node:o,pos:W}}}W+=m;I=a};var N=/\r\n|\r|\n/g;N.lastIndex=0;var C=V.length;var j=[];while(W<C){var P=W;var J;var Q;var G=N.exec(V);if(G===null){J=C;Q=C}else{J=G.index;Q=N.lastIndex}var F=V.substring(P,J);var X=-1;for(;;){var e=W-P;var Y;var S=K.length;if(S===0){Y=0}else{Y=K[S-1][2]}var l=L[Y];var T=l.length;if(Y!==X){j.length=0}var Z=null;var O=-1;for(var g=0;g<T;g++){var E;if(Y===X&&g<j.length&&(j[g]===null||e<=j[g].index)){E=j[g]}else{var B=l[g][0];B.lastIndex=e;E=B.exec(F);j[g]=E}if(E!==null&&(Z===null||E.index<Z.index)){Z=E;O=g;if(E.index===e){break}}}X=Y;if(Z===null){R(F.substring(e),null);break}else{if(Z.index>e){R(F.substring(e,Z.index),null)}var D=l[O];var f=D[1];var A;if(f instanceof Array){for(var h=0;h<f.length;h++){A=Z[h+1];R(A,f[h])}}else{A=Z[0];R(A,f)}switch(D[2]){case -1:break;case -2:K.pop();break;case -3:K.length=0;break;default:K.push(D);break}}}if(I){U[H++]={pos:W};if(I==="sh_url"){sh_setHref(U,H,V)}I=null}W=Q}return U}function sh_getClasses(D){var A=[];var B=D.className;if(B&&B.length>0){var E=B.split(" ");for(var C=0;C<E.length;C++){if(E[C].length>0){A.push(E[C])}}}return A}function sh_addClass(C,A){var D=sh_getClasses(C);for(var B=0;B<D.length;B++){if(A.toLowerCase()===D[B].toLowerCase()){return }}D.push(A);C.className=D.join(" ")}function sh_extractTagsFromNodeList(C,A){var F=C.length;for(var D=0;D<F;D++){var E=C.item(D);switch(E.nodeType){case 1:if(E.nodeName.toLowerCase()==="br"){var B;if(/MSIE/.test(navigator.userAgent)){B="\r"}else{B="\n"}A.text.push(B);A.pos++}else{A.tags.push({node:E.cloneNode(false),pos:A.pos});sh_extractTagsFromNodeList(E.childNodes,A);A.tags.push({pos:A.pos})}break;case 3:case 4:A.text.push(E.data);A.pos+=E.length;break}}}function sh_extractTags(C,B){var A={};A.text=[];A.tags=B;A.pos=0;sh_extractTagsFromNodeList(C.childNodes,A);return A.text.join("")}function sh_mergeTags(D,F){var A=D.length;if(A===0){return F}var C=F.length;if(C===0){return D}var I=[];var E=0;var B=0;while(E<A&&B<C){var H=D[E];var G=F[B];if(H.pos<=G.pos){I.push(H);E++}else{I.push(G);if(F[B+1].pos<=H.pos){B++;I.push(F[B]);B++}else{I.push({pos:H.pos});F[B]={node:G.node.cloneNode(false),pos:H.pos}}}}while(E<A){I.push(D[E]);E++}while(B<C){I.push(F[B]);B++}return I}function sh_insertTags(K,H){var G=document;var L=document.createDocumentFragment();var E=0;var D=K.length;var B=0;var J=H.length;var C=L;while(B<J||E<D){var I;var A;if(E<D){I=K[E];A=I.pos}else{A=J}if(A<=B){if(I.node){var F=I.node;C.appendChild(F);C=F}else{C=C.parentNode}E++}else{C.appendChild(G.createTextNode(H.substring(B,A)));B=A}}return L}function sh_highlightElement(D,G){sh_addClass(D,"sh_sourceCode");var C=[];var E=sh_extractTags(D,C);var F=sh_highlightString(E,G);var B=sh_mergeTags(C,F);var A=sh_insertTags(B,E);while(D.hasChildNodes()){D.removeChild(D.firstChild)}D.appendChild(A)}function sh_getXMLHttpRequest(){if(window.ActiveXObject){return new ActiveXObject("Msxml2.XMLHTTP")}else{if(window.XMLHttpRequest){return new XMLHttpRequest()}}throw"No XMLHttpRequest implementation available"}function sh_load(language,element,prefix,suffix){if(language in sh_requests){sh_requests[language].push(element);return }sh_requests[language]=[element];var request=sh_getXMLHttpRequest();var url=prefix+"sh_"+language+suffix;request.open("GET",url,true);request.onreadystatechange=function(){if(request.readyState===4){try{if(!request.status||request.status===200){eval(request.responseText);var elements=sh_requests[language];for(var i=0;i<elements.length;i++){sh_highlightElement(elements[i],sh_languages[language])}}else{throw"HTTP error: status "+request.status}}finally{request=null}}};request.send(null)}function sh_highlightDocument(G,I){var B=document.getElementsByTagName("pre");for(var E=0;E<B.length;E++){var F=B.item(E);var A=sh_getClasses(F);for(var C=0;C<A.length;C++){var H=A[C].toLowerCase();if(H==="sh_sourcecode"){continue}if(H.substr(0,3)==="sh_"){var D=H.substring(3);if(D in sh_languages){sh_highlightElement(F,sh_languages[D])}else{if(typeof (G)==="string"&&typeof (I)==="string"){sh_load(D,F,G,I)}else{throw'Found <pre> element with class="'+H+'", but no such language exists'}}break}}}}; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css b/tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css
new file mode 100644
index 0000000..cf09093
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/sh_nedit.min.css
@@ -0,0 +1 @@
+pre.sh_sourceCode{background-color:#fff;color:#000;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_keyword{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_type{color:#a52a2a;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_string{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_regexp{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_specialchar{color:#2e8b57;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_comment{color:#000;font-weight:normal;font-style:italic;}pre.sh_sourceCode .sh_number{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_preproc{color:#27408b;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_symbol{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_function{color:#000;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_cbracket{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_url{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_date{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_time{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_file{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_ip{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_name{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_variable{color:#dda0dd;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_oldfile{color:#2e8b57;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_newfile{color:#006400;font-weight:normal;font-style:normal;}pre.sh_sourceCode .sh_difflines{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_selector{color:#dda0dd;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_property{color:#000;font-weight:bold;font-style:normal;}pre.sh_sourceCode .sh_value{color:#006400;font-weight:normal;font-style:normal;} \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.png b/tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.png
new file mode 100644
index 0000000..c3684aa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/siliconforks-16x16.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/style.css b/tools/node_modules/expresso/deps/jscoverage/doc/style.css
new file mode 100644
index 0000000..4681e69
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/style.css
@@ -0,0 +1,138 @@
+html {
+ background: #bfffbf;
+}
+h1 a {
+ color: black;
+ text-decoration: none;
+ font-size: 182%;
+ font-weight: bold;
+}
+span.h1 {
+ font-size: 182%;
+ font-weight: bold;
+}
+span.tag {
+ font-size: 85%;
+ font-style: italic;
+}
+h2 {
+ font-size: 136%;
+ font-weight: bold;
+ margin-bottom: 1em;
+}
+h3 {
+ font-size: 122%;
+ font-weight: bold;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+h4 {
+ font-size: 107%;
+ font-weight: bold;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+p {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+p:first-child {
+ margin-top: 0;
+}
+div {
+ background: white;
+}
+div#doc3 {
+ font-size: 107%;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ border: 1px solid #aaa;
+}
+div#hd {
+ margin: 1em;
+}
+div#bd {
+ margin: 1em;
+ border-top: 1px solid #aaa;
+ border-bottom: 1px solid #aaa;
+ padding-top: 1em;
+ padding-bottom: 1em;
+}
+div#ft {
+ margin: 1em;
+}
+div#yui-main {
+
+}
+div#jscoverage-main {
+
+}
+div#jscoverage-sidebar {
+ border-left: 1px solid #aaa;
+ padding-left: 10px;
+}
+dd {
+ padding-left: 1em;
+}
+ul.list {
+ padding-left: 1em;
+}
+ul.list li {
+ display: list-item;
+ list-style-position: outside;
+ list-style-type: disc;
+}
+address {
+ font-style: italic;
+}
+em {
+ font-style: italic;
+}
+strong {
+ font-weight: bold;
+}
+var {
+ font-style: italic;
+}
+dfn {
+ font-style: italic;
+}
+cite {
+ font-style: italic;
+}
+abbr {
+ cursor: help;
+ border-bottom-width: 1px;
+ border-bottom-style: dotted;
+}
+img.icon {
+ vertical-align: middle;
+}
+
+/* tables */
+table {
+ border-collapse: collapse;
+}
+col {
+ border-left: 1px solid #d9d9d9;
+}
+col.first-col {
+ border-left-width: 0px;
+}
+thead {
+ border-bottom: 1px solid #666666;
+}
+th {
+ font-weight: normal;
+ text-align: left;
+}
+th, td {
+ padding-left: 5px;
+ padding-right: 5px;
+}
+.numeric {
+ text-align: right;
+}
+tr.odd td {
+ background-color: #e6ffe6;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/doc/users.html b/tools/node_modules/expresso/deps/jscoverage/doc/users.html
new file mode 100644
index 0000000..57fa070
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/doc/users.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+<head>
+<title>JSCoverage - users</title>
+<link rel="stylesheet" type="text/css" href="reset-fonts-grids.css">
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+<div id="doc3" class="yui-t5">
+ <div id="hd"><h1><a href="./">JSCoverage</a><br><span class="tag">code coverage for JavaScript</span></h1></div>
+ <div id="bd">
+ <div id="yui-main">
+ <div id="jscoverage-main" class="yui-b">
+<h2>Who's using JSCoverage?</h2>
+<ul class="list">
+<li>The <a href="http://pokersource.info/">pokersource</a> online poker project has used JSCoverage in testing the
+<a href="http://jspoker.pokersource.info/">JavaScript client</a>
+<li><a href="http://github.com/nickstenning/micromvc/tree/master">MicroMVC</a>, a JavaScript Model-View-Controller framework
+<li>The <a href="http://kssproject.org/">KSS</a> Ajax framework
+<li><a href="http://knowledgeforge.net/project/microfacts/">Micro Facts</a>
+<li>The <a href="http://bassistance.de/jquery-plugins/jquery-plugin-validation/">jQuery Validation plugin</a>
+<li>The <a href="http://code.google.com/p/jqmock/">jqMock</a> JavaScript mock object framework
+<li>The <a href="http://www.mozilla.org/">Mozilla</a> project has used JSCoverage for instrumenting JavaScript code in <a href="http://www.mozilla.com/en-US/firefox/">Firefox</a>
+</ul>
+<p>
+If you, your project, or your company uses JSCoverage in testing your JavaScript
+code, please send email to <a
+href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a> so
+you can be added to this list. (It is not necessary that it be a Free
+Software/Open Source project.)
+</p>
+ </div>
+ </div>
+ <div id="jscoverage-sidebar" class="yui-b">
+ <ul>
+ <li><a href="./">Home</a>
+ <li><a href="news.html">News</a> <a href="http://siliconforks.com/jscoverage/news.xml" type="application/rss+xml" title="RSS feed for JSCoverage"><img src="feed-icon-14x14.png" alt="RSS feed"></a>
+ <li><a href="manual.html">Documentation</a>
+ <li><a href="demo.html">Demo</a>
+ <li><a href="http://siliconforks.com/jscoverage/download.html">Download</a>
+ <li><a href="faq.html">FAQ</a>
+ <li><a href="help.html">Help</a>
+ <li><a href="license.html">License</a>
+ <li><a href="links.html">Links</a>
+ <li>Users
+ <li><a href="http://siliconforks.com/jscoverage/bugs/">Bug tracker</a>
+ </ul>
+ </div>
+ </div>
+ <div id="ft">
+ <address>
+ Copyright &copy; 2007, 2008 <a href="http://siliconforks.com/"><img src="siliconforks-16x16.png" width="16" height="16" class="icon" alt="Silicon Forks"></a> <a href="http://siliconforks.com/">siliconforks.com</a><br>
+ <a href="mailto:jscoverage@siliconforks.com">jscoverage@siliconforks.com</a>
+ </address>
+ </div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/encoding.c b/tools/node_modules/expresso/deps/jscoverage/encoding.c
new file mode 100644
index 0000000..76b2f26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/encoding.c
@@ -0,0 +1,315 @@
+/*
+ encoding.c - character encoding
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "encoding.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#elif defined HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#include "util.h"
+
+static void skip_bom(jschar ** characters, size_t * num_characters) {
+ jschar * c = *characters;
+ size_t nc = *num_characters;
+
+ size_t i;
+ for (i = 0; i < nc; i++) {
+ if (c[i] != 0xfeff) {
+ break;
+ }
+ }
+
+ if (i == 0) {
+ return;
+ }
+
+ nc -= i;
+ jschar * old = c;
+ c = xnew(jschar, nc);
+ memcpy(c, old + i, nc * sizeof(jschar));
+ free(old);
+
+ *characters = c;
+ *num_characters = nc;
+}
+
+#ifdef HAVE_ICONV
+
+#ifdef WORDS_BIGENDIAN
+#define UTF_16_INTERNAL "UTF-16BE"
+#else
+#define UTF_16_INTERNAL "UTF-16LE"
+#endif
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters) {
+ assert(encoding != NULL);
+
+ iconv_t state = iconv_open(UTF_16_INTERNAL, encoding);
+ if (state == (iconv_t) -1) {
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+
+ ICONV_CONST char * input = (char *) bytes;
+ size_t input_bytes_left = num_bytes;
+
+ jschar * c = xnew(jschar, num_bytes);
+ char * output = (char *) c;
+ size_t output_bytes_left = sizeof(jschar) * num_bytes;
+
+ size_t result = iconv(state, &input, &input_bytes_left, &output, &output_bytes_left);
+ iconv_close(state);
+ if (result == (size_t) -1) {
+ free(c);
+ return JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE;
+ }
+
+ assert(input_bytes_left == 0);
+
+ size_t nc = ((jschar *) output) - c;
+
+ skip_bom(&c, &nc);
+
+ *characters = c;
+ *num_characters = nc;
+ return 0;
+}
+
+#elif HAVE_MULTIBYTETOWIDECHAR
+
+/* http://msdn.microsoft.com/en-us/library/ms776446(VS.85).aspx */
+static struct CodePage {
+ UINT value;
+ LPCSTR string;
+} code_pages[] = {
+ {37, "IBM037"}, /* IBM EBCDIC US-Canada */
+ {437, "IBM437"}, /* OEM United States */
+ {500, "IBM500"}, /* IBM EBCDIC International */
+ {708, "ASMO-708"}, /* Arabic (ASMO 708) */
+ {720, "DOS-720"}, /* Arabic (Transparent ASMO); Arabic (DOS) */
+ {737, "ibm737"}, /* OEM Greek (formerly 437G); Greek (DOS) */
+ {775, "ibm775"}, /* OEM Baltic; Baltic (DOS) */
+ {850, "ibm850"}, /* OEM Multilingual Latin 1; Western European (DOS) */
+ {852, "ibm852"}, /* OEM Latin 2; Central European (DOS) */
+ {855, "IBM855"}, /* OEM Cyrillic (primarily Russian) */
+ {857, "ibm857"}, /* OEM Turkish; Turkish (DOS) */
+ {858, "IBM00858"}, /* OEM Multilingual Latin 1 + Euro symbol */
+ {860, "IBM860"}, /* OEM Portuguese; Portuguese (DOS) */
+ {861, "ibm861"}, /* OEM Icelandic; Icelandic (DOS) */
+ {862, "DOS-862"}, /* OEM Hebrew; Hebrew (DOS) */
+ {863, "IBM863"}, /* OEM French Canadian; French Canadian (DOS) */
+ {864, "IBM864"}, /* OEM Arabic; Arabic (864) */
+ {865, "IBM865"}, /* OEM Nordic; Nordic (DOS) */
+ {866, "cp866"}, /* OEM Russian; Cyrillic (DOS) */
+ {869, "ibm869"}, /* OEM Modern Greek; Greek, Modern (DOS) */
+ {870, "IBM870"}, /* IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 */
+ {874, "windows-874"}, /* ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) */
+ {875, "cp875"}, /* IBM EBCDIC Greek Modern */
+ {932, "shift_jis"}, /* ANSI/OEM Japanese; Japanese (Shift-JIS) */
+ {936, "gb2312"}, /* ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) */
+ {949, "ks_c_5601-1987"}, /* ANSI/OEM Korean (Unified Hangul Code) */
+ {950, "big5"}, /* ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) */
+ {1026, "IBM1026"}, /* IBM EBCDIC Turkish (Latin 5) */
+ {1047, "IBM01047"}, /* IBM EBCDIC Latin 1/Open System */
+ {1140, "IBM01140"}, /* IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) */
+ {1141, "IBM01141"}, /* IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) */
+ {1142, "IBM01142"}, /* IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) */
+ {1143, "IBM01143"}, /* IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) */
+ {1144, "IBM01144"}, /* IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) */
+ {1145, "IBM01145"}, /* IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) */
+ {1146, "IBM01146"}, /* IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) */
+ {1147, "IBM01147"}, /* IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) */
+ {1148, "IBM01148"}, /* IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) */
+ {1149, "IBM01149"}, /* IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) */
+ {1200, "utf-16"}, /* Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications */
+ {1201, "unicodeFFFE"}, /* Unicode UTF-16, big endian byte order; available only to managed applications */
+ {1250, "windows-1250"}, /* ANSI Central European; Central European (Windows) */
+ {1251, "windows-1251"}, /* ANSI Cyrillic; Cyrillic (Windows) */
+ {1252, "windows-1252"}, /* ANSI Latin 1; Western European (Windows) */
+ {1253, "windows-1253"}, /* ANSI Greek; Greek (Windows) */
+ {1254, "windows-1254"}, /* ANSI Turkish; Turkish (Windows) */
+ {1255, "windows-1255"}, /* ANSI Hebrew; Hebrew (Windows) */
+ {1256, "windows-1256"}, /* ANSI Arabic; Arabic (Windows) */
+ {1257, "windows-1257"}, /* ANSI Baltic; Baltic (Windows) */
+ {1258, "windows-1258"}, /* ANSI/OEM Vietnamese; Vietnamese (Windows) */
+ {1361, "Johab"}, /* Korean (Johab) */
+ {10000, "macintosh"}, /* MAC Roman; Western European (Mac) */
+ {10001, "x-mac-japanese"}, /* Japanese (Mac) */
+ {10002, "x-mac-chinesetrad"}, /* MAC Traditional Chinese (Big5); Chinese Traditional (Mac) */
+ {10003, "x-mac-korean"}, /* Korean (Mac) */
+ {10004, "x-mac-arabic"}, /* Arabic (Mac) */
+ {10005, "x-mac-hebrew"}, /* Hebrew (Mac) */
+ {10006, "x-mac-greek"}, /* Greek (Mac) */
+ {10007, "x-mac-cyrillic"}, /* Cyrillic (Mac) */
+ {10008, "x-mac-chinesesimp"}, /* MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) */
+ {10010, "x-mac-romanian"}, /* Romanian (Mac) */
+ {10017, "x-mac-ukrainian"}, /* Ukrainian (Mac) */
+ {10021, "x-mac-thai"}, /* Thai (Mac) */
+ {10029, "x-mac-ce"}, /* MAC Latin 2; Central European (Mac) */
+ {10079, "x-mac-icelandic"}, /* Icelandic (Mac) */
+ {10081, "x-mac-turkish"}, /* Turkish (Mac) */
+ {10082, "x-mac-croatian"}, /* Croatian (Mac) */
+ {12000, "utf-32"}, /* Unicode UTF-32, little endian byte order; available only to managed applications */
+ {12001, "utf-32BE"}, /* Unicode UTF-32, big endian byte order; available only to managed applications */
+ {20000, "x-Chinese_CNS"}, /* CNS Taiwan; Chinese Traditional (CNS) */
+ {20001, "x-cp20001"}, /* TCA Taiwan */
+ {20002, "x_Chinese-Eten"}, /* Eten Taiwan; Chinese Traditional (Eten) */
+ {20003, "x-cp20003"}, /* IBM5550 Taiwan */
+ {20004, "x-cp20004"}, /* TeleText Taiwan */
+ {20005, "x-cp20005"}, /* Wang Taiwan */
+ {20105, "x-IA5"}, /* IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) */
+ {20106, "x-IA5-German"}, /* IA5 German (7-bit) */
+ {20107, "x-IA5-Swedish"}, /* IA5 Swedish (7-bit) */
+ {20108, "x-IA5-Norwegian"}, /* IA5 Norwegian (7-bit) */
+ {20127, "us-ascii"}, /* US-ASCII (7-bit) */
+ {20261, "x-cp20261"}, /* T.61 */
+ {20269, "x-cp20269"}, /* ISO 6937 Non-Spacing Accent */
+ {20273, "IBM273"}, /* IBM EBCDIC Germany */
+ {20277, "IBM277"}, /* IBM EBCDIC Denmark-Norway */
+ {20278, "IBM278"}, /* IBM EBCDIC Finland-Sweden */
+ {20280, "IBM280"}, /* IBM EBCDIC Italy */
+ {20284, "IBM284"}, /* IBM EBCDIC Latin America-Spain */
+ {20285, "IBM285"}, /* IBM EBCDIC United Kingdom */
+ {20290, "IBM290"}, /* IBM EBCDIC Japanese Katakana Extended */
+ {20297, "IBM297"}, /* IBM EBCDIC France */
+ {20420, "IBM420"}, /* IBM EBCDIC Arabic */
+ {20423, "IBM423"}, /* IBM EBCDIC Greek */
+ {20424, "IBM424"}, /* IBM EBCDIC Hebrew */
+ {20833, "x-EBCDIC-KoreanExtended"}, /* IBM EBCDIC Korean Extended */
+ {20838, "IBM-Thai"}, /* IBM EBCDIC Thai */
+ {20866, "koi8-r"}, /* Russian (KOI8-R); Cyrillic (KOI8-R) */
+ {20871, "IBM871"}, /* IBM EBCDIC Icelandic */
+ {20880, "IBM880"}, /* IBM EBCDIC Cyrillic Russian */
+ {20905, "IBM905"}, /* IBM EBCDIC Turkish */
+ {20924, "IBM00924"}, /* IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) */
+ {20932, "EUC-JP"}, /* Japanese (JIS 0208-1990 and 0121-1990) */
+ {20936, "x-cp20936"}, /* Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) */
+ {20949, "x-cp20949"}, /* Korean Wansung */
+ {21025, "cp1025"}, /* IBM EBCDIC Cyrillic Serbian-Bulgarian */
+ {21866, "koi8-u"}, /* Ukrainian (KOI8-U); Cyrillic (KOI8-U) */
+ {28591, "iso-8859-1"}, /* ISO 8859-1 Latin 1; Western European (ISO) */
+ {28592, "iso-8859-2"}, /* ISO 8859-2 Central European; Central European (ISO) */
+ {28593, "iso-8859-3"}, /* ISO 8859-3 Latin 3 */
+ {28594, "iso-8859-4"}, /* ISO 8859-4 Baltic */
+ {28595, "iso-8859-5"}, /* ISO 8859-5 Cyrillic */
+ {28596, "iso-8859-6"}, /* ISO 8859-6 Arabic */
+ {28597, "iso-8859-7"}, /* ISO 8859-7 Greek */
+ {28598, "iso-8859-8"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Visual) */
+ {28599, "iso-8859-9"}, /* ISO 8859-9 Turkish */
+ {28603, "iso-8859-13"}, /* ISO 8859-13 Estonian */
+ {28605, "iso-8859-15"}, /* ISO 8859-15 Latin 9 */
+ {29001, "x-Europa"}, /* Europa 3 */
+ {38598, "iso-8859-8-i"}, /* ISO 8859-8 Hebrew; Hebrew (ISO-Logical) */
+ {50220, "iso-2022-jp"}, /* ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) */
+ {50221, "csISO2022JP"}, /* ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) */
+ {50222, "iso-2022-jp"}, /* ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) */
+ {50225, "iso-2022-kr"}, /* ISO 2022 Korean */
+ {50227, "x-cp50227"}, /* ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) */
+ {51932, "euc-jp"}, /* EUC Japanese */
+ {51936, "EUC-CN"}, /* EUC Simplified Chinese; Chinese Simplified (EUC) */
+ {51949, "euc-kr"}, /* EUC Korean */
+ {52936, "hz-gb-2312"}, /* HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) */
+ {54936, "GB18030"}, /* Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) */
+ {57002, "x-iscii-de"}, /* ISCII Devanagari */
+ {57003, "x-iscii-be"}, /* ISCII Bengali */
+ {57004, "x-iscii-ta"}, /* ISCII Tamil */
+ {57005, "x-iscii-te"}, /* ISCII Telugu */
+ {57006, "x-iscii-as"}, /* ISCII Assamese */
+ {57007, "x-iscii-or"}, /* ISCII Oriya */
+ {57008, "x-iscii-ka"}, /* ISCII Kannada */
+ {57009, "x-iscii-ma"}, /* ISCII Malayalam */
+ {57010, "x-iscii-gu"}, /* ISCII Gujarati */
+ {57011, "x-iscii-pa"}, /* ISCII Punjabi */
+ {65000, "utf-7"}, /* Unicode (UTF-7) */
+ {65001, "utf-8"}, /* Unicode (UTF-8) */
+};
+
+int find_code_page(const char * encoding, UINT * code_page) {
+ for (size_t i = 0; i < sizeof(code_pages) / sizeof(code_pages[0]); i++) {
+ if (strcasecmp(encoding, code_pages[i].string) == 0) {
+ *code_page = code_pages[i].value;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters) {
+ assert(encoding != NULL);
+
+ if (num_bytes == 0) {
+ *characters = xnew(jschar, 0);
+ *num_characters = 0;
+ return 0;
+ }
+
+ UINT code_page;
+ if (find_code_page(encoding, &code_page) != 0) {
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+
+ if (num_bytes > INT_MAX) {
+ fatal("overflow");
+ }
+
+ *characters = xnew(jschar, num_bytes);
+
+ int result = MultiByteToWideChar(code_page, MB_ERR_INVALID_CHARS, bytes, num_bytes, *characters, num_bytes);
+ if (result == 0) {
+ free(*characters);
+ return JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE;
+ }
+
+ *num_characters = result;
+ skip_bom(characters, num_characters);
+ return 0;
+}
+
+#else
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters) {
+ assert(encoding != NULL);
+
+ if (strcasecmp(encoding, "us-ascii") != 0 && strcasecmp(encoding, "iso-8859-1") != 0 && strcasecmp(encoding, "utf-8") != 0) {
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+
+ jschar * c = xnew(jschar, num_bytes);
+ for (size_t i = 0; i < num_bytes; i++) {
+ if (bytes[i] > 127) {
+ free(c);
+ return JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED;
+ }
+ c[i] = bytes[i];
+ }
+
+ *characters = c;
+ *num_characters = num_bytes;
+ return 0;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/encoding.h b/tools/node_modules/expresso/deps/jscoverage/encoding.h
new file mode 100644
index 0000000..0e4edbb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/encoding.h
@@ -0,0 +1,33 @@
+/*
+ encoding.h - character encoding
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef ENCODING_H_
+#define ENCODING_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <jsapi.h>
+
+#define JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED (-1)
+#define JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE (-2)
+
+int jscoverage_bytes_to_characters(const char * encoding, const uint8_t * bytes, size_t num_bytes, jschar ** characters, size_t * num_characters);
+
+#endif /* ENCODING_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/generate-resources b/tools/node_modules/expresso/deps/jscoverage/generate-resources
new file mode 100755
index 0000000..aa650cf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/generate-resources
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/generate-resources.c b/tools/node_modules/expresso/deps/jscoverage/generate-resources.c
new file mode 100644
index 0000000..adabf60
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/generate-resources.c
@@ -0,0 +1,58 @@
+/*
+ generate-resources.c - code generator for embedded resources
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/stat.h>
+
+int main(int argc, char ** argv) {
+ for (int i = 1; i < argc; i++) {
+ printf("const unsigned char RESOURCE%d_[] = {\n", i);
+ FILE * f = fopen(argv[i], "rb");
+ if (f == NULL) {
+ fprintf(stderr, "cannot open file %s\n", argv[i]);
+ exit(EXIT_FAILURE);
+ }
+ int c;
+ int j = 0;
+ while ((c = fgetc(f)) != EOF) {
+ if (j % 16 == 0) {
+ printf("\n ");
+ }
+ printf("0x%02x,", c);
+ j++;
+ }
+ fclose(f);
+ printf("\n};\n");
+ }
+
+ printf("const struct Resource RESOURCES[] = {\n");
+ for (int i = 1; i < argc; i++) {
+ printf(" {\n");
+ printf(" \"%s\",\n", argv[i]);
+ printf(" RESOURCE%d_,\n", i);
+ printf(" sizeof(RESOURCE%d_)\n", i);
+ printf(" },\n");
+ }
+ printf("};\n");
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/global.h b/tools/node_modules/expresso/deps/jscoverage/global.h
new file mode 100644
index 0000000..1384d12
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/global.h
@@ -0,0 +1,29 @@
+/*
+ global.h - global variables
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef GLOBAL_H_
+#define GLOBAL_H_
+
+#include <stdbool.h>
+
+extern const char * jscoverage_encoding;
+
+extern bool jscoverage_highlight;
+
+#endif /* GLOBAL_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/highlight.c b/tools/node_modules/expresso/deps/jscoverage/highlight.c
new file mode 100644
index 0000000..7dddf3b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/highlight.c
@@ -0,0 +1,478 @@
+/*
+ highlight.c - JavaScript syntax highlighting
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "highlight.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jslock.h>
+#include <jsscan.h>
+
+#include "util.h"
+
+enum Class {
+ CLASS_NONE,
+ CLASS_COMMENT,
+ CLASS_REGEXP,
+ CLASS_NUMBER,
+ CLASS_STRING,
+ CLASS_SPECIALCHAR,
+ CLASS_KEYWORD,
+ CLASS_TYPE,
+ CLASS_SYMBOL,
+ CLASS_CBRACKET
+};
+
+static const char * get_class_name(enum Class class) {
+ switch (class) {
+ case CLASS_NONE:
+ abort();
+ break;
+ case CLASS_COMMENT:
+ return "c";
+ break;
+ case CLASS_REGEXP:
+ return "s";
+ break;
+ case CLASS_NUMBER:
+ return "s";
+ break;
+ case CLASS_STRING:
+ return "s";
+ break;
+ case CLASS_SPECIALCHAR:
+ return "t";
+ break;
+ case CLASS_KEYWORD:
+ return "k";
+ break;
+ case CLASS_TYPE:
+ return "k";
+ break;
+ case CLASS_SYMBOL:
+ return "k";
+ break;
+ case CLASS_CBRACKET:
+ return "k";
+ break;
+ default:
+ abort();
+ break;
+ }
+}
+
+static const char * g_id;
+static const jschar * g_characters;
+static size_t g_num_characters;
+static Stream * g_output;
+static size_t character_offset;
+static uint16_t line_num;
+static uint16_t column_num;
+static enum Class current_class;
+
+static void output_character(jschar c, enum Class class) {
+ if (c == '\r' || c == '\n' || c == 0x2028 || c == 0x2029) {
+ class = CLASS_NONE;
+ }
+
+ if (class != current_class) {
+ /* output the end tag */
+ if (current_class != CLASS_NONE) {
+ Stream_write_string(g_output, "</span>");
+ }
+
+ current_class = class;
+
+ /* output the start tag */
+ if (current_class != CLASS_NONE) {
+ Stream_printf(g_output, "<span class=\"%s\">", get_class_name(class));
+ }
+ }
+
+ if (column_num == UINT16_MAX) {
+ fatal("%s: script contains a line with more than 65,535 columns", g_id);
+ }
+ column_num++;
+ switch (c) {
+ case '&':
+ Stream_write_string(g_output, "&amp;");
+ break;
+ case '<':
+ Stream_write_string(g_output, "&lt;");
+ break;
+ case '>':
+ Stream_write_string(g_output, "&gt;");
+ break;
+ case '\t':
+ Stream_write_char(g_output, c);
+ break;
+ case '\r':
+ case '\n':
+ case 0x2028:
+ case 0x2029:
+ if (c == '\r' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '\n') {
+ break;
+ }
+ Stream_write_char(g_output, '\n');
+ column_num = 0;
+ if (line_num == UINT16_MAX) {
+ fatal("%s: script contains more than 65,535 lines", g_id);
+ }
+ line_num++;
+ break;
+ default:
+ if (32 <= c && c <= 126) {
+ Stream_write_char(g_output, c);
+ }
+ else {
+ Stream_printf(g_output, "&#%d;", c);
+ }
+ break;
+ }
+ character_offset++;
+}
+
+static void mark_nontoken_chars(uint16_t end_line, uint16_t end_column) {
+ enum State {
+ STATE_NORMAL,
+ STATE_LINE_COMMENT,
+ STATE_MULTILINE_COMMENT
+ };
+
+ enum State state = STATE_NORMAL;
+ while (character_offset < g_num_characters) {
+ if (end_line != 0 && line_num > end_line) {
+ break;
+ }
+ else if (line_num == end_line && column_num >= end_column) {
+ break;
+ }
+
+ jschar c = g_characters[character_offset];
+ if (c == '\0') {
+ fatal("%s: script contains NULL character", g_id);
+ }
+
+ switch (state) {
+ case STATE_NORMAL:
+ if (c == '/' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '/') {
+ state = STATE_LINE_COMMENT;
+ }
+ else if (c == '/' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '*') {
+ state = STATE_MULTILINE_COMMENT;
+ output_character('/', CLASS_COMMENT);
+ output_character('*', CLASS_COMMENT);
+ continue;
+ }
+ break;
+ case STATE_LINE_COMMENT:
+ if (c == '\r' || c == '\n' || c == 0x2028 || c == 0x2029) {
+ state = STATE_NORMAL;
+ }
+ break;
+ case STATE_MULTILINE_COMMENT:
+ if (c == '*' && character_offset + 1 < g_num_characters && g_characters[character_offset + 1] == '/') {
+ output_character('*', CLASS_COMMENT);
+ output_character('/', CLASS_COMMENT);
+ state = STATE_NORMAL;
+ continue;
+ }
+ break;
+ }
+
+ if (state == STATE_NORMAL) {
+ output_character(c, CLASS_NONE);
+ }
+ else {
+ output_character(c, CLASS_COMMENT);
+ }
+ }
+}
+
+void jscoverage_highlight_js(JSContext * context, const char * id, const jschar * characters, size_t num_characters, Stream * output) {
+ g_id = id;
+ g_characters = characters;
+ g_num_characters = num_characters;
+ g_output = output;
+
+ character_offset = 0;
+ line_num = 1;
+ column_num = 0;
+ current_class = CLASS_NONE;
+
+ /* tokenize the JavaScript */
+ JSTokenStream token_stream;
+ if (! js_InitTokenStream(context, &token_stream, characters, num_characters, NULL, NULL, 1)) {
+ fatal("cannot create token stream from JavaScript file %s", id);
+ }
+
+ for (;;) {
+ JSTokenType tt = js_GetToken(context, &token_stream);
+
+ if (tt == TOK_ERROR) {
+ fatal("JavaScript parse error: %s: line = %d, col = %d\n", id, line_num, column_num);
+ }
+
+ if (tt == TOK_EOF) {
+ mark_nontoken_chars(0, 0);
+ break;
+ }
+
+ /* mark the chars before the token */
+ JSToken t = CURRENT_TOKEN(&token_stream);
+ mark_nontoken_chars(t.pos.begin.lineno, t.pos.begin.index);
+
+ /* mark the token */
+ enum Class class;
+ switch (tt) {
+ case TOK_ERROR:
+ case TOK_EOF:
+ abort();
+ case TOK_EOL:
+ class = CLASS_NONE;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_SEMI:
+ case TOK_COMMA:
+ case TOK_ASSIGN:
+ case TOK_HOOK:
+ case TOK_COLON:
+ case TOK_OR:
+ case TOK_AND:
+ case TOK_BITOR:
+ case TOK_BITXOR:
+ case TOK_BITAND:
+ case TOK_EQOP:
+ case TOK_RELOP:
+ case TOK_SHOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ case TOK_STAR:
+ case TOK_DIVOP:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_UNARYOP:
+ switch (t.t_op) {
+ case JSOP_NEG:
+ case JSOP_POS:
+ case JSOP_NOT:
+ case JSOP_BITNOT:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case JSOP_TYPEOF:
+ class = CLASS_KEYWORD;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case JSOP_VOID:
+ class = CLASS_TYPE;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case TOK_INC:
+ case TOK_DEC:
+ class = CLASS_SYMBOL;
+ /* token_stream.flags does not change w.r.t. TSF_OPERAND */
+ break;
+ case TOK_DOT:
+ case TOK_LB:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_RB:
+ class = CLASS_SYMBOL;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_LC:
+ class = CLASS_CBRACKET;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_RC:
+ class = CLASS_CBRACKET;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_LP:
+ class = CLASS_SYMBOL;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_RP:
+ class = CLASS_SYMBOL;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_NAME:
+ class = CLASS_NONE;
+ token_stream.flags &= ~TSF_OPERAND;
+ if (js_PeekToken(context, &token_stream) == TOK_LP) {
+ /* function */
+ class = CLASS_NONE;
+ }
+ break;
+ case TOK_NUMBER:
+ class = CLASS_NUMBER;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_STRING:
+ class = CLASS_STRING;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_REGEXP:
+ class = CLASS_REGEXP;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ case TOK_PRIMARY:
+ switch (t.t_op) {
+ case JSOP_TRUE:
+ case JSOP_FALSE:
+ case JSOP_NULL:
+ case JSOP_THIS:
+ class = CLASS_KEYWORD;
+ token_stream.flags &= ~TSF_OPERAND;
+ break;
+ default:
+ abort();
+ }
+ break;
+ case TOK_FUNCTION:
+ class = CLASS_KEYWORD;
+ token_stream.flags |= TSF_OPERAND;
+ break;
+ case TOK_IF:
+ case TOK_ELSE:
+ case TOK_SWITCH:
+ case TOK_CASE:
+ case TOK_DEFAULT:
+ case TOK_WHILE:
+ case TOK_DO:
+ case TOK_FOR:
+ case TOK_BREAK:
+ case TOK_CONTINUE:
+ case TOK_IN:
+ case TOK_VAR:
+ case TOK_WITH:
+ case TOK_RETURN:
+ case TOK_NEW:
+ case TOK_DELETE:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_DEFSHARP:
+ case TOK_USESHARP:
+ abort();
+ break;
+ case TOK_TRY:
+ case TOK_CATCH:
+ case TOK_FINALLY:
+ case TOK_THROW:
+ case TOK_INSTANCEOF:
+ case TOK_DEBUGGER:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_XMLSTAGO:
+ case TOK_XMLETAGO:
+ case TOK_XMLPTAGC:
+ case TOK_XMLTAGC:
+ case TOK_XMLNAME:
+ case TOK_XMLATTR:
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_XMLCOMMENT:
+ case TOK_XMLCDATA:
+ case TOK_XMLPI:
+ case TOK_AT:
+ case TOK_DBLCOLON:
+ case TOK_ANYNAME:
+ case TOK_DBLDOT:
+ case TOK_FILTER:
+ case TOK_XMLELEM:
+ case TOK_XMLLIST:
+ abort();
+ break;
+ case TOK_YIELD:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_ARRAYCOMP:
+ case TOK_ARRAYPUSH:
+ case TOK_LEXICALSCOPE:
+ abort();
+ break;
+ case TOK_LET:
+ token_stream.flags |= TSF_OPERAND;
+ class = CLASS_KEYWORD;
+ break;
+ case TOK_SEQ:
+ case TOK_FORHEAD:
+ case TOK_RESERVED:
+ case TOK_LIMIT:
+ abort();
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ uint16_t start_line = t.pos.begin.lineno;
+ uint16_t end_line = t.pos.end.lineno;
+ uint16_t start_column = t.pos.begin.index;
+ uint16_t end_column = t.pos.end.index;
+ assert(line_num == start_line);
+ assert(column_num == start_column);
+ if (start_line == end_line && start_column >= end_column) {
+ fatal("%s: script contains line with more than 65,535 characters", id);
+ }
+ for (;;) {
+ assert(character_offset < num_characters);
+ jschar c = characters[character_offset];
+ if (tt == TOK_STRING && c == '\\') {
+ output_character(c, CLASS_SPECIALCHAR);
+ assert(character_offset < num_characters);
+ c = characters[character_offset];
+ output_character(c, CLASS_SPECIALCHAR);
+ }
+ else {
+ output_character(c, class);
+ }
+
+ if (line_num > end_line) {
+ break;
+ }
+ else if (line_num == end_line && column_num >= end_column) {
+ break;
+ }
+ }
+
+ assert(line_num == end_line);
+ assert(column_num = end_column);
+ }
+
+ if (current_class != CLASS_NONE) {
+ output_character('\n', CLASS_NONE);
+ }
+
+ js_CloseTokenStream(context, &token_stream);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/highlight.h b/tools/node_modules/expresso/deps/jscoverage/highlight.h
new file mode 100644
index 0000000..5bc8c88
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/highlight.h
@@ -0,0 +1,37 @@
+/*
+ highlight.h - JavaScript syntax highlighting
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef HIGHLIGHT_H_
+#define HIGHLIGHT_H_
+
+#include <jscntxt.h>
+
+#include "stream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void jscoverage_highlight_js(JSContext * context, const char * id, const jschar * characters, size_t num_characters, Stream * output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HIGHLIGHT_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-connection.c b/tools/node_modules/expresso/deps/jscoverage/http-connection.c
new file mode 100644
index 0000000..4280d0a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-connection.c
@@ -0,0 +1,192 @@
+/*
+ http-connection.c - TCP connection between HTTP client and server
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "util.h"
+
+#define CONNECTION_BUFFER_CAPACITY 8192
+
+#ifdef _WIN32
+#define ERRNO (WSAGetLastError())
+#else
+#include <errno.h>
+#define ERRNO errno
+#endif
+
+struct HTTPConnection {
+ SOCKET s;
+ uint8_t input_buffer[CONNECTION_BUFFER_CAPACITY];
+ size_t input_buffer_offset;
+ size_t input_buffer_length;
+ uint8_t output_buffer[CONNECTION_BUFFER_CAPACITY];
+ size_t output_buffer_offset;
+ size_t output_buffer_length;
+};
+
+static HTTPConnection * HTTPConnection_new(SOCKET s) {
+ HTTPConnection * connection = xmalloc(sizeof(HTTPConnection));
+ connection->s = s;
+ connection->input_buffer_offset = 0;
+ connection->input_buffer_length = 0;
+ connection->output_buffer_offset = 0;
+ connection->output_buffer_length = 0;
+ return connection;
+}
+
+HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) {
+ struct in_addr ip_address;
+ if (! inet_aton(host, &ip_address)) {
+ /* it's a host name */
+ if (xgethostbyname(host, &ip_address) != 0) {
+ return NULL;
+ }
+ }
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ return NULL;
+ }
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(port);
+ a.sin_addr = ip_address;
+
+ if (connect(s, (struct sockaddr *) &a, sizeof(a)) < 0) {
+ closesocket(s);
+ return NULL;
+ }
+
+ return HTTPConnection_new(s);
+}
+
+HTTPConnection * HTTPConnection_new_server(SOCKET s) {
+ return HTTPConnection_new(s);
+}
+
+int HTTPConnection_delete(HTTPConnection * connection) {
+ int result = 0;
+ if (closesocket(connection->s) == -1) {
+ result = ERRNO;
+ assert(result != 0);
+ }
+ free(connection);
+ return result;
+}
+
+int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) {
+ int result = 0;
+ socklen_t length = sizeof(struct sockaddr_in);
+ if (getpeername(connection->s, (struct sockaddr *) peer, &length) == -1) {
+ result = ERRNO;
+ assert(result != 0);
+ }
+ return result;
+}
+
+int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) {
+ if (connection->input_buffer_offset >= connection->input_buffer_length) {
+ ssize_t bytes_received = recv(connection->s, connection->input_buffer, CONNECTION_BUFFER_CAPACITY, 0);
+ if (bytes_received == -1) {
+ int result = ERRNO;
+ assert(result != 0);
+ return result;
+ }
+ else if (bytes_received == 0) {
+ /* orderly shutdown */
+ *octet = -1;
+ return 0;
+ }
+ else {
+ connection->input_buffer_offset = 0;
+ connection->input_buffer_length = bytes_received;
+ }
+ }
+ *octet = connection->input_buffer[connection->input_buffer_offset];
+ connection->input_buffer_offset++;
+ return 0;
+}
+
+int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) {
+ int result = HTTPConnection_read_octet(connection, octet);
+
+ /* check for error */
+ if (result != 0) {
+ return result;
+ }
+
+ /* check for end */
+ if (*octet == -1) {
+ return 0;
+ }
+
+ /* reset input buffer */
+ connection->input_buffer_offset--;
+ return 0;
+}
+
+int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) {
+ while (size > 0) {
+ if (connection->output_buffer_length == CONNECTION_BUFFER_CAPACITY) {
+ /* buffer full */
+ ssize_t bytes_sent = send(connection->s, connection->output_buffer, CONNECTION_BUFFER_CAPACITY, 0);
+ if (bytes_sent == -1) {
+ int result = ERRNO;
+ assert(result != 0);
+ return result;
+ }
+ connection->output_buffer_length = 0;
+ }
+
+ size_t buffer_remaining = CONNECTION_BUFFER_CAPACITY - connection->output_buffer_length;
+ size_t bytes_to_copy;
+ if (size <= buffer_remaining) {
+ bytes_to_copy = size;
+ }
+ else {
+ bytes_to_copy = buffer_remaining;
+ }
+
+ memcpy(connection->output_buffer + connection->output_buffer_length, p, bytes_to_copy);
+ connection->output_buffer_length += bytes_to_copy;
+ p += bytes_to_copy;
+ size -= bytes_to_copy;
+ }
+
+ return 0;
+}
+
+int HTTPConnection_flush(HTTPConnection * connection) {
+ if (connection->output_buffer_length > 0) {
+ ssize_t bytes_sent = send(connection->s, connection->output_buffer, connection->output_buffer_length, 0);
+ if (bytes_sent == -1) {
+ int result = ERRNO;
+ assert(result != 0);
+ return result;
+ }
+ connection->output_buffer_length = 0;
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-exchange.c b/tools/node_modules/expresso/deps/jscoverage/http-exchange.c
new file mode 100644
index 0000000..9356455
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-exchange.c
@@ -0,0 +1,494 @@
+/*
+ http-exchange.c - HTTP request/response exchange
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "util.h"
+
+struct HTTPExchange {
+ HTTPConnection * connection;
+
+ HTTPMessage * request_message;
+
+ char * method;
+ char * request_uri;
+ char * request_http_version;
+
+ char * host;
+ uint16_t port;
+ char * abs_path;
+ char * query;
+
+ HTTPMessage * response_message;
+
+ uint16_t status_code;
+ char * response_http_version;
+};
+
+static const struct {
+ const int status_code;
+ const char * const reason_phrase;
+} reason_phrases[] = {
+ {100, "Continue"},
+ {101, "Switching Protocols"},
+ {200, "OK"},
+ {201, "Created"},
+ {202, "Accepted"},
+ {203, "Non-Authoritative Information"},
+ {204, "No Content"},
+ {205, "Reset Content"},
+ {206, "Partial Content"},
+ {301, "Moved Permanently"},
+ {302, "Found"},
+ {303, "See Other"},
+ {304, "Not Modified"},
+ {305, "Use Proxy"},
+ {307, "Temporary Redirect"},
+ {400, "Bad Request"},
+ {401, "Unauthorized"},
+ {402, "Payment Required"},
+ {403, "Forbidden"},
+ {404, "Not Found"},
+ {405, "Method Not Allowed"},
+ {406, "Not Acceptable"},
+ {407, "Proxy Authentication Required"},
+ {408, "Request Time-out"},
+ {409, "Conflict"},
+ {410, "Gone"},
+ {411, "Length Required"},
+ {412, "Precondition Failed"},
+ {413, "Request Entity Too Large"},
+ {414, "Request-URI Too Large"},
+ {415, "Unsupported Media Type"},
+ {416, "Requested range not satisfiable"},
+ {417, "Expectation Failed"},
+ {500, "Internal Server Error"},
+ {501, "Not Implemented"},
+ {502, "Bad Gateway"},
+ {503, "Service Unavailable"},
+ {504, "Gateway Time-out"},
+ {505, "HTTP Version not supported"},
+};
+
+HTTPExchange * HTTPExchange_new(HTTPConnection * connection) {
+ HTTPExchange * exchange = xmalloc(sizeof(HTTPExchange));
+
+ exchange->connection = connection;
+
+ exchange->request_message = HTTPMessage_new(connection);
+ exchange->method = NULL;
+ exchange->request_uri = NULL;
+ exchange->request_http_version = NULL;
+ exchange->host = NULL;
+ exchange->port = 0;
+ exchange->abs_path = NULL;
+ exchange->query = NULL;
+
+ exchange->response_message = HTTPMessage_new(connection);
+ exchange->response_http_version = NULL;
+ exchange->status_code = 0;
+
+ return exchange;
+}
+
+void HTTPExchange_delete(HTTPExchange * exchange) {
+ HTTPMessage_delete(exchange->response_message);
+ free(exchange->response_http_version);
+
+ HTTPMessage_delete(exchange->request_message);
+ free(exchange->method);
+ free(exchange->request_uri);
+ free(exchange->request_http_version);
+ free(exchange->host);
+ free(exchange->abs_path);
+ free(exchange->query);
+
+ free(exchange);
+}
+
+int HTTPExchange_get_peer(const HTTPExchange * exchange, struct sockaddr_in * peer) {
+ return HTTPConnection_get_peer(exchange->connection, peer);
+}
+
+HTTPMessage * HTTPExchange_get_request_message(const HTTPExchange * exchange) {
+ return exchange->request_message;
+}
+
+const char * HTTPExchange_get_request_line(const HTTPExchange * exchange) {
+ return HTTPMessage_get_start_line(exchange->request_message);
+}
+
+const char * HTTPExchange_get_method(const HTTPExchange * exchange) {
+ return exchange->method;
+}
+
+const char * HTTPExchange_get_request_uri(const HTTPExchange * exchange) {
+ return exchange->request_uri;
+}
+
+const char * HTTPExchange_get_request_http_version(const HTTPExchange * exchange) {
+ return exchange->request_http_version;
+}
+
+const char * HTTPExchange_get_host(const HTTPExchange * exchange) {
+ return exchange->host;
+}
+
+uint16_t HTTPExchange_get_port(const HTTPExchange * exchange) {
+ return exchange->port;
+}
+
+const char * HTTPExchange_get_abs_path(const HTTPExchange * exchange) {
+ return exchange->abs_path;
+}
+
+void HTTPExchange_set_method(HTTPExchange * exchange, const char * method) {
+ free(exchange->method);
+ exchange->method = xstrdup(method);
+}
+
+void HTTPExchange_set_request_uri(HTTPExchange * exchange, const char * request_uri) {
+ free(exchange->request_uri);
+ exchange->request_uri = xstrdup(request_uri);
+}
+
+const HTTPHeader * HTTPExchange_get_request_headers(const HTTPExchange * exchange) {
+ return HTTPMessage_get_headers(exchange->request_message);
+}
+
+const char * HTTPExchange_find_request_header(const HTTPExchange * exchange, const char * name) {
+ return HTTPMessage_find_header(exchange->request_message, name);
+}
+
+void HTTPExchange_add_request_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_add_header(exchange->request_message, name, value);
+}
+
+void HTTPExchange_set_request_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_set_header(exchange->request_message, name, value);
+}
+
+void HTTPExchange_set_request_content_length(HTTPExchange * exchange, size_t value) {
+ HTTPMessage_set_content_length(exchange->request_message, value);
+}
+
+int HTTPExchange_read_request_headers(HTTPExchange * exchange) {
+ int result = 0;
+
+ result = HTTPMessage_read_start_line_and_headers(exchange->request_message);
+ if (result != 0) {
+ return result;
+ }
+
+ /* parse the Request-Line */
+ const char * request_line = HTTPMessage_get_start_line(exchange->request_message);
+ const char * p = request_line;
+
+ /* parse the Method */
+ while (*p != ' ') {
+ if (*p == '\0') {
+ return -1;
+ }
+ p++;
+ }
+ if (p == request_line) {
+ return -1;
+ }
+ exchange->method = xstrndup(request_line, p - request_line);
+
+ /* skip over space */
+ p++;
+
+ /* parse the Request-URI */
+ const char * start = p;
+ while (*p != ' ') {
+ if (*p == '\0') {
+ return -1;
+ }
+ p++;
+ }
+ if (p == start) {
+ return -1;
+ }
+ exchange->request_uri = xstrndup(start, p - start);
+
+ /* skip over space */
+ p++;
+
+ /* parse the HTTP-Version */
+ start = p;
+ while (*p != '\r' && *p != '\n') {
+ if (*p == '\0') {
+ return -1;
+ }
+ p++;
+ }
+ if (p == start) {
+ return -1;
+ }
+ exchange->request_http_version = xstrndup(start, p - start);
+
+ /* uri elements */
+ /* RFC 2616 5.1.2: the Request-URI can be an `absoluteURI' or an `abs_path' */
+ result = URL_parse(exchange->request_uri, &(exchange->host), &(exchange->port),
+ &(exchange->abs_path), &(exchange->query));
+ if (result != 0) {
+ return result;
+ }
+
+ if (exchange->host == NULL) {
+ /* abs_path */
+ const char * h = HTTPMessage_find_header(exchange->request_message, HTTP_HOST);
+ if (h == NULL) {
+ /* this must be an HTTP/1.0 client */
+ }
+ else {
+ result = URL_parse_host_and_port(h, &(exchange->host), &(exchange->port));
+ if (result != 0) {
+ return result;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int HTTPExchange_write_request_headers(HTTPExchange * exchange) {
+ if (HTTPMessage_has_sent_headers(exchange->request_message)) {
+ return 0;
+ }
+
+ /* set the Request-Line */
+ if (HTTPMessage_get_start_line(exchange->request_message) == NULL) {
+ if (exchange->method == NULL) {
+ exchange->method = xstrdup("GET");
+ }
+ assert(exchange->request_uri != NULL);
+ char * request_line;
+ xasprintf(&request_line, "%s %s HTTP/1.1\r\n", exchange->method, exchange->request_uri);
+ HTTPMessage_set_start_line(exchange->request_message, request_line);
+ free(request_line);
+ }
+
+ /* set the Host, if necessary */
+ if (! str_starts_with(exchange->request_uri, "http://")) {
+ const char * host = HTTPMessage_find_header(exchange->request_message, HTTP_HOST);
+ if (host == NULL) {
+ struct sockaddr_in peer;
+ int result = HTTPConnection_get_peer(exchange->connection, &peer);
+ if (result != 0) {
+ return result;
+ }
+ const char * a = inet_ntoa(peer.sin_addr);
+ char * value;
+ xasprintf(&value, "%s:%u", a, ntohs(peer.sin_port));
+ HTTPMessage_add_header(exchange->request_message, HTTP_HOST, value);
+ free(value);
+ }
+ }
+
+ return HTTPMessage_write_start_line_and_headers(exchange->request_message);
+}
+
+bool HTTPExchange_request_has_body(const HTTPExchange * exchange) {
+ /*
+ RFC 2616 4.3: a request has a body iff the request has a Content-Length or Transfer-Encoding header
+ */
+ return HTTPMessage_find_header(exchange->request_message, HTTP_CONTENT_LENGTH) != NULL ||
+ HTTPMessage_find_header(exchange->request_message, HTTP_TRANSFER_ENCODING) != NULL;
+}
+
+int HTTPExchange_read_entire_request_entity_body(HTTPExchange * exchange, Stream * stream) {
+ return HTTPMessage_read_entire_entity_body(exchange->request_message, stream);
+}
+
+int HTTPExchange_flush_request(HTTPExchange * exchange) {
+ return HTTPMessage_flush(exchange->request_message);
+}
+
+/* response methods */
+
+HTTPMessage * HTTPExchange_get_response_message(const HTTPExchange * exchange) {
+ return exchange->response_message;
+}
+
+const char * HTTPExchange_get_response_http_version(const HTTPExchange * exchange) {
+ return exchange->response_http_version;
+}
+
+uint16_t HTTPExchange_get_status_code(const HTTPExchange * exchange) {
+ return exchange->status_code;
+}
+
+void HTTPExchange_set_status_code(HTTPExchange * exchange, uint16_t status_code) {
+ exchange->status_code = status_code;
+}
+
+const HTTPHeader * HTTPExchange_get_response_headers(const HTTPExchange * exchange) {
+ return HTTPMessage_get_headers(exchange->response_message);
+}
+
+const char * HTTPExchange_find_response_header(const HTTPExchange * exchange, const char * name) {
+ return HTTPMessage_find_header(exchange->response_message, name);
+}
+
+void HTTPExchange_add_response_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_add_header(exchange->response_message, name, value);
+}
+
+void HTTPExchange_set_response_header(HTTPExchange * exchange, const char * name, const char * value) {
+ HTTPMessage_set_header(exchange->response_message, name, value);
+}
+
+void HTTPExchange_set_response_content_length(HTTPExchange * exchange, size_t value) {
+ HTTPMessage_set_content_length(exchange->response_message, value);
+}
+
+static void skip_digits(const char ** p) {
+ while (**p != '\0' && isdigit(**p)) {
+ (*p)++;
+ }
+}
+
+int HTTPExchange_read_response_headers(HTTPExchange * exchange) {
+ /* make sure the request went through before we try to read stuff */
+ int result = HTTPExchange_flush_request(exchange);
+ if (result != 0) {
+ return result;
+ }
+
+ result = HTTPMessage_read_start_line_and_headers(exchange->response_message);
+ if (result != 0) {
+ return result;
+ }
+
+ /* parse the Status-Line (RFC 2616 6.1) */
+ const char * status_line = HTTPMessage_get_start_line(exchange->response_message);
+ const char * p = status_line;
+
+ /* read the HTTP-Version */
+ if (! str_starts_with(p, "HTTP/")) {
+ return -1;
+ }
+ p += 5;
+ const char * start = p;
+ skip_digits(&p);
+ if (start == p) {
+ return -1;
+ }
+ if (*p != '.') {
+ return -1;
+ }
+ p++;
+ start = p;
+ skip_digits(&p);
+ if (start == p) {
+ return -1;
+ }
+ if (*p != ' ') {
+ return -1;
+ }
+ exchange->response_http_version = xstrndup(status_line, p - status_line);
+
+ /* skip over the space */
+ p++;
+
+ /* read the Status-Code */
+ start = p;
+ skip_digits(&p);
+ if (p - start != 3) {
+ return -1;
+ }
+ if (*p != ' ') {
+ return -1;
+ }
+ exchange->status_code = strtoul(start, NULL, 10);
+
+ return 0;
+}
+
+int HTTPExchange_write_response_headers(HTTPExchange * exchange) {
+ if (HTTPMessage_has_sent_headers(exchange->response_message)) {
+ return 0;
+ }
+
+ /* set the Status-Line (RFC 2616 6.1) */
+ if (exchange->status_code == 0) {
+ exchange->status_code = 200;
+ }
+ const char * reason_phrase = NULL;
+ size_t num_reason_phrases = sizeof(reason_phrases) / sizeof(reason_phrases[0]);
+ for (size_t i = 0; i < num_reason_phrases; i++) {
+ if (reason_phrases[i].status_code == exchange->status_code) {
+ reason_phrase = reason_phrases[i].reason_phrase;
+ break;
+ }
+ }
+ assert(reason_phrase != NULL);
+ char * status_line;
+ xasprintf(&status_line, "HTTP/1.1 %u %s\r\n", exchange->status_code, reason_phrase);
+ HTTPMessage_set_start_line(exchange->response_message, status_line);
+ free(status_line);
+
+ /* set the Content-Type, if necessary */
+ const char * content_type = HTTPMessage_find_header(exchange->response_message, HTTP_CONTENT_TYPE);
+ if (content_type == NULL) {
+ HTTPMessage_set_header(exchange->response_message, HTTP_CONTENT_TYPE, "text/html");
+ }
+
+ return HTTPMessage_write_start_line_and_headers(exchange->response_message);
+}
+
+bool HTTPExchange_response_has_body(const HTTPExchange * exchange) {
+ /*
+ RFC 2616 4.3: a response has a body iff the request is not HEAD and the response is not 1xx, 204, 304
+ */
+ const char * request_method = HTTPExchange_get_method(exchange);
+ assert(request_method != NULL);
+ return strcmp(request_method, "HEAD") != 0 &&
+ exchange->status_code != 304 &&
+ exchange->status_code != 204 &&
+ exchange->status_code / 100 != 1;
+}
+
+int HTTPExchange_read_entire_response_entity_body(HTTPExchange * exchange, Stream * stream) {
+ return HTTPMessage_read_entire_entity_body(exchange->response_message, stream);
+}
+
+int HTTPExchange_write_response(HTTPExchange * exchange, const void * p, size_t size) {
+ int result = HTTPExchange_write_response_headers(exchange);
+ if (result != 0) {
+ return result;
+ }
+ return HTTPMessage_write(exchange->response_message, p, size);
+}
+
+int HTTPExchange_flush_response(HTTPExchange * exchange) {
+ int result = HTTPExchange_write_response_headers(exchange);
+ if (result != 0) {
+ return result;
+ }
+ return HTTPMessage_flush(exchange->response_message);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-host.c b/tools/node_modules/expresso/deps/jscoverage/http-host.c
new file mode 100644
index 0000000..4458eee
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-host.c
@@ -0,0 +1,95 @@
+/*
+ http-host.c - thread-safe host lookup
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include "util.h"
+
+int xgethostbyname(const char * host, struct in_addr * a) {
+#if defined(__CYGWIN__) || defined(__MINGW32__)
+ /* gethostbyname is thread-safe */
+ struct hostent * p = gethostbyname(host);
+ if (p == NULL || p->h_addrtype != AF_INET) {
+ return -1;
+ }
+ *a = *((struct in_addr *) p->h_addr);
+ return 0;
+#elif HAVE_GETADDRINFO
+ struct addrinfo hints;
+ hints.ai_flags = 0;
+ hints.ai_family = PF_INET;
+ hints.ai_socktype = 0;
+ hints.ai_protocol = 0;
+ hints.ai_addrlen = 0;
+ hints.ai_addr = NULL;
+ hints.ai_canonname = NULL;
+ hints.ai_next = NULL;
+ struct addrinfo * p;
+ int result = getaddrinfo(host, NULL, &hints, &p);
+ if (result != 0 || p == NULL) {
+ return -1;
+ }
+ if (p->ai_family != PF_INET) {
+ freeaddrinfo(p);
+ return -1;
+ }
+ struct sockaddr_in * address_and_port = (struct sockaddr_in *) p->ai_addr;
+ *a = address_and_port->sin_addr;
+ freeaddrinfo(p);
+ return 0;
+#elif HAVE_GETHOSTBYNAME_R
+ struct hostent h;
+ struct hostent * p;
+ char * buffer;
+ size_t buffer_size;
+ int error;
+ int result;
+
+ buffer_size = 1024;
+ buffer = xmalloc(buffer_size);
+ while ((result = gethostbyname_r(host, &h, buffer, buffer_size, &p, &error)) == ERANGE) {
+ buffer_size = mulst(buffer_size, 2);
+ buffer = xrealloc(buffer, buffer_size);
+ }
+ if (result != 0 || p == NULL || p->h_addrtype != AF_INET) {
+ free(buffer);
+ return -1;
+ }
+ *a = *((struct in_addr *) p->h_addr);
+ free(buffer);
+ return 0;
+#else
+#error "No thread-safe host lookup available"
+#endif
+}
+
+#ifndef HAVE_INET_ATON
+int inet_aton(const char * name, struct in_addr * a) {
+ unsigned long result = inet_addr(name);
+ if (result == INADDR_NONE) {
+ return 0;
+ }
+ else {
+ a->s_addr = result;
+ return 1;
+ }
+}
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-message.c b/tools/node_modules/expresso/deps/jscoverage/http-message.c
new file mode 100644
index 0000000..6a92956
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-message.c
@@ -0,0 +1,900 @@
+/*
+ http-message.c - HTTP message object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "stream.h"
+#include "util.h"
+
+enum ChunkedBodyState {
+ CHUNKED_BODY_CHUNK_SIZE, CHUNKED_BODY_CHUNK_DATA, CHUNKED_BODY_TRAILER, CHUNKED_BODY_DONE
+};
+
+struct HTTPMessage {
+ char * start_line;
+ HTTPHeader * headers;
+
+ /* used for sending and receiving */
+ struct HTTPConnection * connection;
+
+ /* used only for receiving */
+ bool has_content_length;
+ bool is_chunked;
+ size_t bytes_remaining;
+ enum ChunkedBodyState chunked_body_state;
+ Stream * chunk_buffer;
+
+ /* used only for sending */
+ bool is_started;
+};
+
+static bool is_lws(uint8_t c) {
+ return c == '\r' || c == '\n' || c == ' ' || c == '\t';
+}
+
+static bool is_separator(uint8_t c) {
+ /* RFC 2616 2.2 */
+ return strchr("()<>@,;:\\\"/[]?={} \t", c) != NULL;
+}
+
+static bool is_token_char(uint8_t c) {
+ /* RFC 2616 2.2 */
+ return 32 <= c && c <= 126 && ! is_separator(c);
+}
+
+static bool is_text(uint8_t c) {
+ return ! (c <= 31 || c == 127);
+}
+
+static void skip_lws(const uint8_t ** p) {
+ while (**p != '\0' && is_lws(**p)) {
+ (*p)++;
+ }
+}
+
+static uint8_t * parse_token(const uint8_t ** p) {
+ const uint8_t * start = *p;
+ while (**p != '\0' && is_token_char(**p)) {
+ (*p)++;
+ }
+
+ if (*p == start) {
+ return NULL;
+ }
+
+ return (uint8_t *) xstrndup((char *) start, *p - start);
+}
+
+static uint8_t * parse_quoted_string(const uint8_t ** p) {
+ const uint8_t * start = *p;
+
+ if (**p != '"') {
+ return NULL;
+ }
+ (*p)++;
+
+ while (**p != '\0' && **p != '"') {
+ if (**p == '\\') {
+ (*p)++;
+ if (**p < 1 || **p > 127) {
+ return NULL;
+ }
+ (*p)++;
+ }
+ else if (is_text(**p)) {
+ (*p)++;
+ }
+ else {
+ return NULL;
+ }
+ }
+
+ if (**p != '"') {
+ return NULL;
+ }
+ (*p)++;
+
+ return (uint8_t *) xstrndup((char *) start, *p - start);
+}
+
+HTTPMessage * HTTPMessage_new(HTTPConnection * connection) {
+ HTTPMessage * message = xmalloc(sizeof(HTTPMessage));
+ message->start_line = NULL;
+ message->headers = NULL;
+ message->connection = connection;
+
+ message->has_content_length = false;
+ message->is_chunked = false;
+ message->bytes_remaining = 0;
+ message->chunked_body_state = CHUNKED_BODY_CHUNK_SIZE;
+ message->chunk_buffer = NULL;
+
+ message->is_started = false;
+ return message;
+}
+
+void HTTPMessage_delete(HTTPMessage * message) {
+ free(message->start_line);
+
+ HTTPHeader * h = message->headers;
+ while (h != NULL) {
+ HTTPHeader * doomed = h;
+ h = h->next;
+ free(doomed->name);
+ free(doomed->value);
+ free(doomed);
+ }
+
+ if (message->chunk_buffer != NULL) {
+ Stream_delete(message->chunk_buffer);
+ }
+
+ free(message);
+}
+
+HTTPConnection * HTTPMessage_get_connection(const HTTPMessage * message) {
+ return message->connection;
+}
+
+void HTTPMessage_add_header(HTTPMessage * message, const char * name, const char * value) {
+ HTTPHeader * last = NULL;
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ if (strcmp(h->name, name) == 0) {
+ char * new_value;
+ xasprintf(&new_value, "%s, %s", h->value, value);
+ free(h->value);
+ h->value = new_value;
+ return;
+ }
+ last = h;
+ }
+
+ HTTPHeader * header = xmalloc(sizeof(HTTPHeader));
+ header->name = xstrdup(name);
+ header->value = xstrdup(value);
+ header->next = NULL;
+ if (last == NULL) {
+ message->headers = header;
+ }
+ else {
+ last->next = header;
+ }
+}
+
+void HTTPMessage_set_header(HTTPMessage * message, const char * name, const char * value) {
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ if (strcmp(name, h->name) == 0) {
+ free(h->value);
+ h->value = xstrdup(value);
+ return;
+ }
+ }
+ HTTPMessage_add_header(message, name, value);
+}
+
+char * HTTPMessage_get_charset(const HTTPMessage * message) {
+ const char * content_type = HTTPMessage_find_header(message, HTTP_CONTENT_TYPE);
+ if (content_type == NULL) {
+ return NULL;
+ }
+
+ const uint8_t * p = (const uint8_t *) content_type;
+
+ /* e.g., text/html */
+ uint8_t * token;
+ skip_lws(&p);
+ if (! is_token_char(*p)) {
+ return NULL;
+ }
+ token = parse_token(&p);
+ free(token);
+ skip_lws(&p);
+ if (*p != '/') {
+ return NULL;
+ }
+ p++;
+ skip_lws(&p);
+ if (! is_token_char(*p)) {
+ return NULL;
+ }
+ token = parse_token(&p);
+ free(token);
+
+ skip_lws(&p);
+
+ while (*p != '\0') {
+ bool is_charset = false;
+ if (*p != ';') {
+ return NULL;
+ }
+ p++;
+
+ skip_lws(&p);
+
+ if (! is_token_char(*p)) {
+ return NULL;
+ }
+ uint8_t * attribute = parse_token(&p);
+ if (strcasecmp((char *) attribute, "charset") == 0) {
+ is_charset = true;
+ }
+ free(attribute);
+ skip_lws(&p);
+ if (*p != '=') {
+ return NULL;
+ }
+ p++;
+
+ skip_lws(&p);
+
+ if (*p == '"') {
+ uint8_t * value = parse_quoted_string(&p);
+ if (value == NULL) {
+ return NULL;
+ }
+ if (is_charset) {
+ return (char *) value;
+ }
+ free(value);
+ }
+ else if (is_token_char(*p)) {
+ uint8_t * value = parse_token(&p);
+ if (is_charset) {
+ return (char *) value;
+ }
+ free(value);
+ }
+ else {
+ return NULL;
+ }
+
+ skip_lws(&p);
+ }
+
+ return NULL;
+}
+
+void HTTPMessage_set_content_length(HTTPMessage * message, size_t value) {
+ char * s;
+ xasprintf(&s, "%u", value);
+ HTTPMessage_set_header(message, HTTP_CONTENT_LENGTH, s);
+ free(s);
+}
+
+const char * HTTPMessage_find_header(const HTTPMessage * message, const char * name) {
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ if (strcasecmp(h->name, name) == 0) {
+ return h->value;
+ }
+ }
+ return NULL;
+}
+
+const HTTPHeader * HTTPMessage_get_headers(const HTTPMessage * message) {
+ return message->headers;
+}
+
+const char * HTTPMessage_get_start_line(const HTTPMessage * message) {
+ return message->start_line;
+}
+
+void HTTPMessage_set_start_line(HTTPMessage * message, const char * start_line) {
+ free(message->start_line);
+ message->start_line = xstrdup(start_line);
+}
+
+static int read_line(Stream * stream, HTTPConnection * connection) __attribute__((warn_unused_result));
+
+static int read_line(Stream * stream, HTTPConnection * connection) {
+ for (;;) {
+ int octet;
+ int result = HTTPConnection_read_octet(connection, &octet);
+ if (result != 0) {
+ return result;
+ }
+
+ /* check for end of input */
+ if (octet == -1) {
+ return 0;
+ }
+
+ char c = (char) octet;
+ Stream_write_char(stream, c);
+ if (c == '\n') {
+ return 0;
+ }
+ }
+}
+
+static int read_header(Stream * stream, HTTPConnection * connection) __attribute__((warn_unused_result));
+
+static int read_header(Stream * stream, HTTPConnection * connection) {
+ int c;
+
+ do {
+ int result = read_line(stream, connection);
+ if (result != 0) {
+ return result;
+ }
+
+ /* check for blank line ending the headers */
+ if (stream->length == 0 ||
+ (stream->length == 1 && stream->data[0] == '\n') ||
+ (stream->length == 2 && stream->data[0] == '\r' && stream->data[1] == '\n')) {
+ break;
+ }
+
+ result = HTTPConnection_peek_octet(connection, &c);
+ if (result != 0) {
+ return result;
+ }
+ }
+ while (c == ' ' || c == '\t');
+
+ return 0;
+}
+
+static bool stream_contains_nul(const Stream * stream) {
+ for (size_t i = 0; i < stream->length; i++) {
+ if (stream->data[i] == '\0') {
+ return true;
+ }
+ }
+ return false;
+}
+
+int HTTPMessage_read_start_line_and_headers(HTTPMessage * message) {
+ Stream * stream = Stream_new(0);
+
+ /* read the start line */
+ int result = read_line(stream, message->connection);
+ if (result != 0) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* check for NUL byte */
+ if (stream_contains_nul(stream)) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ message->start_line = xstrndup((char *) stream->data, stream->length);
+
+ /* read the headers - RFC 2616 4.2 */
+ message->headers = NULL;
+ for (;;) {
+ Stream_reset(stream);
+ result = read_header(stream, message->connection);
+ if (result != 0) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* check for CRLF (or similar) to terminate headers */
+ if (stream->length == 0 ||
+ (stream->length == 1 && stream->data[0] == '\n') ||
+ (stream->length == 2 && stream->data[0] == '\r' && stream->data[1] == '\n')) {
+ break;
+ }
+
+ /* check for NUL byte */
+ if (stream_contains_nul(stream)) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* NUL-terminate the header */
+ Stream_write_char(stream, '\0');
+
+ const uint8_t * p = stream->data;
+
+ char * name = (char *) parse_token(&p);
+ if (name == NULL) {
+ Stream_delete(stream);
+ return -1;
+ }
+
+ skip_lws(&p);
+
+ /* expect colon */
+ if (*p != ':') {
+ free(name);
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* skip over colon */
+ p++;
+
+ skip_lws(&p);
+
+ if (*p == '\0') {
+ free(name);
+ Stream_delete(stream);
+ return -1;
+ }
+
+ /* skip backward over LWS, starting from the last char in the buffer */
+ uint8_t * end = stream->data + stream->length - 2;
+ while (end > p && is_lws(*end)) {
+ end--;
+ }
+
+ char * value = xstrndup((char *) p, end - p + 1);
+
+ HTTPMessage_add_header(message, name, value);
+ free(name);
+ free(value);
+ }
+
+ Stream_delete(stream);
+
+ /*
+ RFC 2616 4.3:
+ - a request has a body iff the request headers include Content-Length or Transfer-Encoding
+ - a response has a body iff the request is not HEAD and the response is not 1xx, 204, 304
+ */
+
+ const char * content_length = HTTPMessage_find_header(message, HTTP_CONTENT_LENGTH);
+ if (content_length != NULL) {
+ size_t value = 0;
+ for (const char * p = content_length; *p != '\0'; p++) {
+ /* check for overflow */
+ if (SIZE_MAX / 10 < value) {
+ return -1;
+ }
+ value *= 10;
+
+ uint8_t digit = *p;
+
+ /* check that it contains only decimal digits */
+ if (digit < '0' || digit > '9') {
+ return -1;
+ }
+
+ size_t digit_value = digit - '0';
+
+ /* check for overflow */
+ if (SIZE_MAX - digit_value < value) {
+ return -1;
+ }
+ value += digit_value;
+ }
+
+ message->bytes_remaining = value;
+ message->has_content_length = true;
+ }
+
+ const char * transfer_encoding = HTTPMessage_find_header(message, HTTP_TRANSFER_ENCODING);
+ if (transfer_encoding != NULL) {
+ uint8_t * token = NULL;
+
+ const uint8_t * p = (const uint8_t *) transfer_encoding;
+ result = 0;
+ for (;;) {
+ skip_lws(&p);
+
+ if (! is_token_char(*p)) {
+ result = -1;
+ break;
+ }
+
+ free(token);
+ token = parse_token(&p);
+
+ skip_lws(&p);
+
+ while (*p == ';') {
+ p++;
+
+ skip_lws(&p);
+
+ if (! is_token_char(*p)) {
+ result = -1;
+ break;
+ }
+ uint8_t * attribute = parse_token(&p);
+ free(attribute);
+
+ skip_lws(&p);
+
+ if (*p != '=') {
+ result = -1;
+ break;
+ }
+ p++;
+
+ skip_lws(&p);
+
+ if (*p == '"') {
+ uint8_t * value = parse_quoted_string(&p);
+ if (value == NULL) {
+ result = -1;
+ break;
+ }
+ free(value);
+ }
+ else if (is_token_char(*p)) {
+ uint8_t * value = parse_token(&p);
+ free(value);
+ }
+ else {
+ result = -1;
+ break;
+ }
+
+ skip_lws(&p);
+ }
+
+ if (result == -1) {
+ break;
+ }
+
+ if (*p != ',') {
+ break;
+ }
+
+ p++;
+ }
+
+ if (result == 0 && *p == '\0' && token != NULL && strcasecmp((char *) token, "chunked") == 0) {
+ message->is_chunked = true;
+ message->chunk_buffer = Stream_new(0);
+ }
+
+ free(token);
+ }
+
+ return result;
+}
+
+int HTTPMessage_write_start_line_and_headers(HTTPMessage * message) {
+ int result = 0;
+
+ if (message->is_started) {
+ return result;
+ }
+
+ message->is_started = true;
+
+ /* send the start line */
+ assert(message->start_line != NULL);
+ size_t length = strlen(message->start_line);
+ assert(length >= 2 && message->start_line[length - 2] == '\r' && message->start_line[length - 1] == '\n');
+ result = HTTPConnection_write(message->connection, message->start_line, length);
+ if (result != 0) {
+ return result;
+ }
+
+ /* send the headers */
+ HTTPMessage_set_header(message, HTTP_CONNECTION, "close");
+ for (HTTPHeader * h = message->headers; h != NULL; h = h->next) {
+ result = HTTPConnection_write(message->connection, h->name, strlen(h->name));
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, ": ", 2);
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, h->value, strlen(h->value));
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, "\r\n", 2);
+ if (result != 0) {
+ return result;
+ }
+ }
+
+ result = HTTPConnection_write(message->connection, "\r\n", 2);
+ return result;
+}
+
+bool HTTPMessage_has_sent_headers(const HTTPMessage * message) {
+ return message->is_started;
+}
+
+int HTTPMessage_write(HTTPMessage * message, const void * p, size_t size) {
+ int result = 0;
+ result = HTTPMessage_write_start_line_and_headers(message);
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_write(message->connection, p, size);
+ return result;
+}
+
+int HTTPMessage_flush(HTTPMessage * message) {
+ int result = 0;
+ result = HTTPMessage_write_start_line_and_headers(message);
+ if (result != 0) {
+ return result;
+ }
+ result = HTTPConnection_flush(message->connection);
+ return result;
+}
+
+static int read_chunk_size_line(HTTPMessage * message) __attribute__((warn_unused_result));
+
+static int read_chunk_size_line(HTTPMessage * message) {
+ Stream_reset(message->chunk_buffer);
+ int result = read_line(message->chunk_buffer, message->connection);
+ if (result != 0) {
+ return result;
+ }
+ if (message->chunk_buffer->length < 2) {
+ return -1;
+ }
+ return 0;
+}
+
+static int read_chunk_size(Stream * stream, size_t * chunk_size) __attribute__((warn_unused_result));
+
+static int read_chunk_size(Stream * stream, size_t * chunk_size) {
+ size_t value = 0;
+ for (size_t i = 0; i < stream->length; i++) {
+ uint8_t digit = stream->data[i];
+
+ /* check that it contains only hexadecimal digits */
+ size_t digit_value;
+ if ('0' <= digit && digit <= '9') {
+ digit_value = digit - '0';
+ }
+ else if ('a' <= digit && digit <= 'f') {
+ digit_value = digit - 'a' + 10;
+ }
+ else if ('A' <= digit && digit <= 'F') {
+ digit_value = digit - 'A' + 10;
+ }
+ else if (is_lws(digit) || digit == ';') {
+ break;
+ }
+ else {
+ return -1;
+ }
+
+ /* check for overflow */
+ if (SIZE_MAX / 16 < value) {
+ return -1;
+ }
+ value *= 16;
+
+ /* check for overflow */
+ if (SIZE_MAX - digit_value < value) {
+ return -1;
+ }
+ value += digit_value;
+ }
+
+ *chunk_size = value;
+ return 0;
+}
+
+static int read_chunked_message_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ int result = 0;
+ *bytes_read = 0;
+
+ if (message->chunked_body_state == CHUNKED_BODY_DONE) {
+ return 0;
+ }
+
+ uint8_t * s = p;
+ int c;
+ for (*bytes_read = 0; *bytes_read < capacity; (*bytes_read)++) {
+ switch (message->chunked_body_state) {
+ case CHUNKED_BODY_CHUNK_SIZE:
+ if (message->chunk_buffer->length == 0) {
+ /* read a `chunk-size' line */
+ result = read_chunk_size_line(message);
+ if (result != 0) {
+ return result;
+ }
+
+ message->bytes_remaining = message->chunk_buffer->length;
+ }
+
+ if (message->bytes_remaining == 0) {
+ return -1;
+ }
+
+ /* serve from the chunk buffer */
+ s[*bytes_read] = message->chunk_buffer->data[message->chunk_buffer->length - message->bytes_remaining];
+ message->bytes_remaining--;
+
+ if (message->bytes_remaining == 0) {
+ size_t chunk_size;
+ result = read_chunk_size(message->chunk_buffer, &chunk_size);
+ if (result != 0) {
+ return result;
+ }
+ Stream_reset(message->chunk_buffer);
+ if (chunk_size == 0) {
+ message->chunked_body_state = CHUNKED_BODY_TRAILER;
+ }
+ else if (SIZE_MAX - 2 < chunk_size) {
+ /* overflow */
+ return -1;
+ }
+ else {
+ message->chunked_body_state = CHUNKED_BODY_CHUNK_DATA;
+ message->bytes_remaining = chunk_size + 2;
+ }
+ }
+
+ break;
+ case CHUNKED_BODY_CHUNK_DATA:
+ /* serve from the chunk */
+ result = HTTPConnection_read_octet(message->connection, &c);
+ if (result != 0) {
+ return result;
+ }
+ if (c == -1) {
+ result = -1;
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ return result;
+ }
+ s[*bytes_read] = (uint8_t) c;
+ message->bytes_remaining--;
+
+ if (message->bytes_remaining == 0) {
+ message->chunked_body_state = CHUNKED_BODY_CHUNK_SIZE;
+ }
+
+ break;
+ case CHUNKED_BODY_TRAILER:
+ if (message->chunk_buffer->length == 0) {
+ /* read a header */
+ result = read_header(message->chunk_buffer, message->connection);
+ if (result != 0) {
+ return result;
+ }
+ message->bytes_remaining = message->chunk_buffer->length;
+ }
+
+ if (message->bytes_remaining == 0) {
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ return result;
+ }
+
+ /* serve from the chunk buffer */
+ s[*bytes_read] = message->chunk_buffer->data[message->chunk_buffer->length - message->bytes_remaining];
+ message->bytes_remaining--;
+
+ if (message->bytes_remaining == 0) {
+ size_t length = message->chunk_buffer->length;
+ uint8_t * chunk_buffer = message->chunk_buffer->data;
+ if (length == 0 ||
+ (length == 1 && chunk_buffer[0] == '\n') ||
+ (length == 2 && chunk_buffer[0] == '\r' && chunk_buffer[1] == '\n')) {
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ return result;
+ }
+ Stream_reset(message->chunk_buffer);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ return result;
+}
+
+static int read_chunked_entity_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ int result = 0;
+ *bytes_read = 0;
+
+ if (message->chunked_body_state == CHUNKED_BODY_DONE) {
+ return result;
+ }
+
+ uint8_t * s = p;
+ for (*bytes_read = 0; *bytes_read < capacity; (*bytes_read)++) {
+ if (message->bytes_remaining == 0) {
+ result = read_chunk_size_line(message);
+ if (result != 0) {
+ break;
+ }
+ size_t chunk_size;
+ result = read_chunk_size(message->chunk_buffer, &chunk_size);
+ if (result != 0) {
+ break;
+ }
+ message->bytes_remaining = chunk_size;
+ if (chunk_size == 0) {
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ break;
+ }
+ }
+
+ int c;
+ result = HTTPConnection_read_octet(message->connection, &c);
+ if (result != 0) {
+ break;
+ }
+ if (c == -1) {
+ result = -1;
+ message->chunked_body_state = CHUNKED_BODY_DONE;
+ break;
+ }
+ s[*bytes_read] = (uint8_t) c;
+ message->bytes_remaining--;
+ }
+
+ return result;
+}
+
+int HTTPMessage_read_message_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ if (message->is_chunked) {
+ return read_chunked_message_body(message, p, capacity, bytes_read);
+ }
+
+ int result = 0;
+ uint8_t * s = p;
+ for (*bytes_read = 0; *bytes_read < capacity; (*bytes_read)++) {
+ if (message->has_content_length && message->bytes_remaining == 0) {
+ break;
+ }
+
+ int c;
+ result = HTTPConnection_read_octet(message->connection, &c);
+ if (result != 0) {
+ break;
+ }
+ if (c == -1) {
+ break;
+ }
+ s[*bytes_read] = (uint8_t) c;
+ message->bytes_remaining--;
+ }
+ return result;
+}
+
+int HTTPMessage_read_entity_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) {
+ if (message->is_chunked) {
+ return read_chunked_entity_body(message, p, capacity, bytes_read);
+ }
+
+ return HTTPMessage_read_message_body(message, p, capacity, bytes_read);
+}
+
+int HTTPMessage_read_entire_entity_body(HTTPMessage * message, Stream * input_stream) {
+ int result = 0;
+ uint8_t * buffer[8192];
+ for (;;) {
+ size_t bytes_read;
+ result = HTTPMessage_read_entity_body(message, buffer, 8192, &bytes_read);
+ if (result != 0) {
+ break;
+ }
+ if (bytes_read == 0) {
+ break;
+ }
+ Stream_write(input_stream, buffer, bytes_read);
+ }
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-server.c b/tools/node_modules/expresso/deps/jscoverage/http-server.c
new file mode 100644
index 0000000..853d285
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-server.c
@@ -0,0 +1,236 @@
+/*
+ http-server.c - generic HTTP server
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#ifdef __MINGW32__
+#include <process.h>
+#endif
+
+#include "util.h"
+
+#ifdef __MINGW32__
+typedef void ThreadRoutineReturnType;
+#define THREAD_ROUTINE_RETURN return
+#else
+typedef void * ThreadRoutineReturnType;
+#define THREAD_ROUTINE_RETURN return NULL
+#endif
+
+struct HTTPServer {
+ char * ip_address;
+ uint16_t port;
+ HTTPServerHandler handler;
+ SOCKET s;
+};
+
+struct HTTPServerConnection {
+ HTTPConnection * connection;
+ struct HTTPServer * server;
+};
+
+static bool is_shutdown = false;
+#ifdef __MINGW32__
+CRITICAL_SECTION shutdown_mutex;
+#define LOCK EnterCriticalSection
+#define UNLOCK LeaveCriticalSection
+#else
+pthread_mutex_t shutdown_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define LOCK pthread_mutex_lock
+#define UNLOCK pthread_mutex_unlock
+#endif
+
+static ThreadRoutineReturnType handle_connection(void * p) {
+ struct HTTPServerConnection * connection = p;
+ uint16_t port = connection->server->port;
+
+ HTTPExchange * exchange = HTTPExchange_new(connection->connection);
+ if (HTTPExchange_read_request_headers(exchange) == 0) {
+ connection->server->handler(exchange);
+ }
+ else {
+ HTTPExchange_set_status_code(exchange, 400);
+ const char * message = "Could not parse request headers\n";
+ if (HTTPExchange_write_response(exchange, message, strlen(message)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ }
+ if (HTTPExchange_flush_response(exchange) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ HTTPExchange_delete(exchange);
+ if (HTTPConnection_delete(connection->connection) != 0) {
+ HTTPServer_log_err("Warning: error closing connection to client\n");
+ }
+ free(connection);
+
+ /* HACK: make connection to server to force accept() to return */
+ LOCK(&shutdown_mutex);
+ if (is_shutdown) {
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ HTTPServer_log_err("Warning: error creating socket\n");
+ }
+ else {
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(port);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ if (connect(s, (struct sockaddr *) &a, sizeof(a)) == -1) {
+ HTTPServer_log_err("Warning: error connecting to server\n");
+ }
+ closesocket(s);
+ }
+ }
+ UNLOCK(&shutdown_mutex);
+
+ THREAD_ROUTINE_RETURN;
+}
+
+static struct HTTPServer * HTTPServer_new(const char * ip_address, uint16_t port, HTTPServerHandler handler) {
+ struct HTTPServer * result = xmalloc(sizeof(struct HTTPServer));
+ if (ip_address == NULL) {
+ result->ip_address = NULL;
+ }
+ else {
+ result->ip_address = xstrdup(ip_address);
+ }
+ result->port = port;
+ result->handler = handler;
+ result->s = -1;
+ return result;
+}
+
+static void HTTPServer_delete(struct HTTPServer * server) {
+ free(server->ip_address);
+ closesocket(server->s);
+ free(server);
+}
+
+void HTTPServer_run(const char * ip_address, uint16_t port, HTTPServerHandler handler) {
+ struct HTTPServer * server = HTTPServer_new(ip_address, port, handler);
+
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ fatal("could not start Winsock");
+ }
+ InitializeCriticalSection(&shutdown_mutex);
+#endif
+
+ server->s = socket(PF_INET, SOCK_STREAM, 0);
+ if (server->s == INVALID_SOCKET) {
+ fatal("could not create socket");
+ }
+
+ /* http://hea-www.harvard.edu/~fine/Tech/addrinuse.html */
+ int optval = 1;
+ setsockopt(server->s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(server->port);
+ if (server->ip_address == NULL) {
+ /*
+ a.sin_addr.s_addr = htonl(INADDR_ANY);
+ */
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ }
+ else {
+ if (inet_aton(server->ip_address, &(a.sin_addr)) == 0) {
+ closesocket(server->s);
+ fatal("invalid address: %s", server->ip_address);
+ }
+ }
+
+ if (bind(server->s, (struct sockaddr *) &a, sizeof(a)) == -1) {
+ closesocket(server->s);
+ fatal("could not bind to address");
+ }
+
+ if (listen(server->s, 5) == -1) {
+ closesocket(server->s);
+ fatal("could not listen for connections");
+ }
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t client_address_size = sizeof(client_address);
+ SOCKET s = accept(server->s, (struct sockaddr *) &client_address, &client_address_size);
+ if (s == INVALID_SOCKET) {
+ HTTPServer_log_err("Warning: could not accept client connection\n");
+ continue;
+ }
+
+ LOCK(&shutdown_mutex);
+ if (is_shutdown) {
+ closesocket(s);
+ break;
+ }
+ UNLOCK(&shutdown_mutex);
+
+ struct HTTPServerConnection * connection = xmalloc(sizeof(struct HTTPServerConnection));
+ connection->server = server;
+ connection->connection = HTTPConnection_new_server(s);
+
+#ifdef __MINGW32__
+ unsigned long thread = _beginthread(handle_connection, 0, connection);
+#else
+ pthread_t thread;
+ pthread_attr_t a;
+ pthread_attr_init(&a);
+ pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
+ pthread_create(&thread, &a, handle_connection, connection);
+ pthread_attr_destroy(&a);
+#endif
+ }
+
+ HTTPServer_delete(server);
+}
+
+void HTTPServer_shutdown(void) {
+ LOCK(&shutdown_mutex);
+ is_shutdown = true;
+ UNLOCK(&shutdown_mutex);
+}
+
+void HTTPServer_log_out(const char * format, ...) {
+ va_list a;
+ va_start(a, format);
+ vfprintf(stdout, format, a);
+ va_end(a);
+ fflush(stdout);
+}
+
+void HTTPServer_log_err(const char * format, ...) {
+ va_list a;
+ va_start(a, format);
+ vfprintf(stderr, format, a);
+ va_end(a);
+ fflush(stderr);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-server.h b/tools/node_modules/expresso/deps/jscoverage/http-server.h
new file mode 100644
index 0000000..b7024f2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-server.h
@@ -0,0 +1,208 @@
+/*
+ http-server.h - generic HTTP server
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef HTTP_SERVER_H_
+#define HTTP_SERVER_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __MINGW32__
+#include <winsock2.h>
+typedef int socklen_t;
+#else
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+typedef int SOCKET;
+#define INVALID_SOCKET (-1)
+#define closesocket close
+#endif
+
+#include "stream.h"
+
+#define HTTP_ACCEPT "Accept"
+#define HTTP_ACCEPT_CHARSET "Accept-Charset"
+#define HTTP_ACCEPT_ENCODING "Accept-Encoding"
+#define HTTP_ACCEPT_LANGUAGE "Accept-Language"
+#define HTTP_ACCEPT_RANGES "Accept-Ranges"
+#define HTTP_AGE "Age"
+#define HTTP_ALLOW "Allow"
+#define HTTP_AUTHORIZATION "Authorization"
+#define HTTP_CACHE_CONTROL "Cache-Control"
+#define HTTP_CONNECTION "Connection"
+#define HTTP_CONTENT_ENCODING "Content-Encoding"
+#define HTTP_CONTENT_LANGUAGE "Content-Language"
+#define HTTP_CONTENT_LENGTH "Content-Length"
+#define HTTP_CONTENT_LOCATION "Content-Location"
+#define HTTP_CONTENT_MD5 "Content-MD5"
+#define HTTP_CONTENT_RANGE "Content-Range"
+#define HTTP_CONTENT_TYPE "Content-Type"
+#define HTTP_DATE "Date"
+#define HTTP_ETAG "ETag"
+#define HTTP_EXPECT "Expect"
+#define HTTP_EXPIRES "Expires"
+#define HTTP_FROM "From"
+#define HTTP_HOST "Host"
+#define HTTP_IF_MATCH "If-Match"
+#define HTTP_IF_MODIFIED_SINCE "If-Modified-Since"
+#define HTTP_IF_NONE_MATCH "If-None-Match"
+#define HTTP_IF_RANGE "If-Range"
+#define HTTP_IF_UNMODIFIED_SINCE "If-Unmodified-Since"
+#define HTTP_LAST_MODIFIED "Last-Modified"
+#define HTTP_LOCATION "Location"
+#define HTTP_MAX_FORWARDS "Max-Forwards"
+#define HTTP_PRAGMA "Pragma"
+#define HTTP_PROXY_AUTHENTICATE "Proxy-Authenticate"
+#define HTTP_PROXY_AUTHORIZATION "Proxy-Authorization"
+#define HTTP_RANGE "Range"
+#define HTTP_REFERER "Referer"
+#define HTTP_RETRY_AFTER "Retry-After"
+#define HTTP_SERVER "Server"
+#define HTTP_TE "TE"
+#define HTTP_TRAILER "Trailer"
+#define HTTP_TRANSFER_ENCODING "Transfer-Encoding"
+#define HTTP_UPGRADE "Upgrade"
+#define HTTP_USER_AGENT "User-Agent"
+#define HTTP_VARY "Vary"
+#define HTTP_VIA "Via"
+#define HTTP_WARNING "Warning"
+#define HTTP_WWW_AUTHENTICATE "WWW-Authenticate"
+
+typedef struct HTTPHeader {
+ char * name;
+ char * value;
+ struct HTTPHeader * next;
+} HTTPHeader;
+
+typedef struct HTTPMessage HTTPMessage;
+
+typedef struct HTTPExchange HTTPExchange;
+
+typedef struct HTTPConnection HTTPConnection;
+
+typedef void (*HTTPServerHandler)(HTTPExchange * exchange);
+
+/* HTTPConnection */
+HTTPConnection * HTTPConnection_new_server(SOCKET s);
+HTTPConnection * HTTPConnection_new_client(const char * host, uint16_t port) __attribute__((warn_unused_result));
+int HTTPConnection_delete(HTTPConnection * connection) __attribute__((warn_unused_result));
+int HTTPConnection_get_peer(HTTPConnection * connection, struct sockaddr_in * peer) __attribute__((warn_unused_result));
+int HTTPConnection_read_octet(HTTPConnection * connection, int * octet) __attribute__((warn_unused_result));
+int HTTPConnection_peek_octet(HTTPConnection * connection, int * octet) __attribute__((warn_unused_result));
+int HTTPConnection_write(HTTPConnection * connection, const void * p, size_t size) __attribute__((warn_unused_result));
+int HTTPConnection_flush(HTTPConnection * connection) __attribute__((warn_unused_result));
+
+/* HTTPMessage */
+HTTPMessage * HTTPMessage_new(HTTPConnection * connection);
+void HTTPMessage_delete(HTTPMessage * message);
+HTTPConnection * HTTPMessage_get_connection(const HTTPMessage * message);
+const char * HTTPMessage_get_start_line(const HTTPMessage * message);
+void HTTPMessage_set_start_line(HTTPMessage * message, const char * start_line);
+const HTTPHeader * HTTPMessage_get_headers(const HTTPMessage * message);
+const char * HTTPMessage_find_header(const HTTPMessage * message, const char * name);
+void HTTPMessage_add_header(HTTPMessage * message, const char * name, const char * value);
+void HTTPMessage_set_header(HTTPMessage * message, const char * name, const char * value);
+char * HTTPMessage_get_charset(const HTTPMessage * message);
+void HTTPMessage_set_content_length(HTTPMessage * message, size_t value);
+int HTTPMessage_read_start_line_and_headers(HTTPMessage * message) __attribute__((warn_unused_result));
+int HTTPMessage_write_start_line_and_headers(HTTPMessage * message) __attribute__((warn_unused_result));
+bool HTTPMessage_has_sent_headers(const HTTPMessage * message);
+int HTTPMessage_write(HTTPMessage * message, const void * p, size_t size) __attribute__((warn_unused_result));
+int HTTPMessage_flush(HTTPMessage * message) __attribute__((warn_unused_result));
+
+/*
+This function reads the entire entity body from a message. If the message uses
+the "chunked" Transfer-Encoding, this function will decode it, so that the
+result will be the original entity.
+*/
+int HTTPMessage_read_entire_entity_body(HTTPMessage * message, Stream * input_stream) __attribute__((warn_unused_result));
+
+/*
+This function makes no attempt to decode the Transfer-Encoding.
+*/
+int HTTPMessage_read_message_body(HTTPMessage * message, void * p, size_t capacity, size_t * bytes_read) __attribute__((warn_unused_result));
+
+/* HTTPExchange */
+HTTPExchange * HTTPExchange_new(HTTPConnection * connection);
+void HTTPExchange_delete(HTTPExchange * exchange);
+int HTTPExchange_get_peer(const HTTPExchange * exchange, struct sockaddr_in * peer) __attribute__((warn_unused_result));
+
+HTTPMessage * HTTPExchange_get_request_message(const HTTPExchange * exchange);
+
+const char * HTTPExchange_get_request_line(const HTTPExchange * exchange);
+const char * HTTPExchange_get_method(const HTTPExchange * exchange);
+const char * HTTPExchange_get_request_uri(const HTTPExchange * exchange);
+const char * HTTPExchange_get_request_http_version(const HTTPExchange * exchange);
+const char * HTTPExchange_get_host(const HTTPExchange * exchange);
+uint16_t HTTPExchange_get_port(const HTTPExchange * exchange);
+const char * HTTPExchange_get_abs_path(const HTTPExchange * exchange);
+void HTTPExchange_set_method(HTTPExchange * exchange, const char * method);
+void HTTPExchange_set_request_uri(HTTPExchange * exchange, const char * request_uri);
+
+const HTTPHeader * HTTPExchange_get_request_headers(const HTTPExchange * exchange);
+const char * HTTPExchange_find_request_header(const HTTPExchange * exchange, const char * name);
+void HTTPExchange_add_request_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_request_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_request_content_length(HTTPExchange * exchange, size_t value);
+
+int HTTPExchange_read_request_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+int HTTPExchange_write_request_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+bool HTTPExchange_request_has_body(const HTTPExchange * exchange);
+int HTTPExchange_read_entire_request_entity_body(HTTPExchange * exchange, Stream * stream) __attribute__((warn_unused_result));
+int HTTPExchange_flush_request(HTTPExchange * exchange) __attribute__((warn_unused_result));
+
+HTTPMessage * HTTPExchange_get_response_message(const HTTPExchange * exchange);
+
+uint16_t HTTPExchange_get_status_code(const HTTPExchange * exchange);
+const char * HTTPExchange_get_response_http_version(const HTTPExchange * exchange);
+void HTTPExchange_set_status_code(HTTPExchange * exchange, uint16_t status_code);
+
+const HTTPHeader * HTTPExchange_get_response_headers(const HTTPExchange * exchange);
+const char * HTTPExchange_find_response_header(const HTTPExchange * exchange, const char * name);
+void HTTPExchange_add_response_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_response_header(HTTPExchange * exchange, const char * name, const char * value);
+void HTTPExchange_set_response_content_length(HTTPExchange * exchange, size_t value);
+
+int HTTPExchange_read_response_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+int HTTPExchange_write_response_headers(HTTPExchange * exchange) __attribute__((warn_unused_result));
+bool HTTPExchange_response_has_body(const HTTPExchange * exchange);
+int HTTPExchange_read_entire_response_entity_body(HTTPExchange * exchange, Stream * stream) __attribute__((warn_unused_result));
+int HTTPExchange_write_response(HTTPExchange * exchange, const void * p, size_t size) __attribute__((warn_unused_result));
+int HTTPExchange_flush_response(HTTPExchange * exchange) __attribute__((warn_unused_result));
+
+void HTTPServer_run(const char * ip_address, uint16_t port, HTTPServerHandler handler);
+void HTTPServer_shutdown(void);
+void HTTPServer_log_out(const char * format, ...) __attribute__((__format__(printf, 1, 2)));
+void HTTPServer_log_err(const char * format, ...) __attribute__((__format__(printf, 1, 2)));
+
+int URL_parse(const char * url, char ** host, uint16_t * port, char ** abs_path, char ** query) __attribute__((warn_unused_result));
+int URL_parse_host_and_port(const char * s, char ** host, uint16_t * port) __attribute__((warn_unused_result));
+int URL_parse_abs_path_and_query(const char * s, char ** abs_path, char ** query) __attribute__((warn_unused_result));
+
+int xgethostbyname(const char * host, struct in_addr * result) __attribute__((warn_unused_result));
+
+#ifndef HAVE_INET_ATON
+int inet_aton(const char * name, struct in_addr * a);
+#endif
+
+#endif /* HTTP_SERVER_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/http-url.c b/tools/node_modules/expresso/deps/jscoverage/http-url.c
new file mode 100644
index 0000000..ee2fa78
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/http-url.c
@@ -0,0 +1,156 @@
+/*
+ http-url.c - URL parsing routines
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "http-server.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include "util.h"
+
+int URL_parse_host_and_port(const char * s, char ** host, uint16_t * port) {
+ char * colon = strchr(s, ':');
+ if (colon == NULL) {
+ *host = xstrdup(s);
+ *port = 80;
+ }
+ else {
+ if (*(colon + 1) == '\0') {
+ *port = 80;
+ }
+ else {
+ char * end;
+ unsigned long p = strtoul(colon + 1, &end, 10);
+ if (*end == '\0') {
+ if (p > UINT16_MAX) {
+ return -1;
+ }
+ else {
+ *port = p;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ *host = xstrndup(s, colon - s);
+ }
+ return 0;
+}
+
+int URL_parse_abs_path_and_query(const char * s, char ** abs_path, char ** query) {
+ if (*s == '\0') {
+ *abs_path = xstrdup("/");
+ *query = NULL;
+ }
+ else if (*s == '?') {
+ *abs_path = xstrdup("/");
+ *query = xstrdup(s + 1);
+ }
+ else if (*s == '/') {
+ char * question = strchr(s, '?');
+ if (question == NULL) {
+ *abs_path = xstrdup(s);
+ *query = NULL;
+ }
+ else {
+ *abs_path = xstrndup(s, question - s);
+ *query = xstrdup(question + 1);
+ }
+ }
+ else {
+ return -1;
+ }
+ return 0;
+}
+
+int URL_parse(const char * url, char ** host, uint16_t * port, char ** abs_path, char ** query) {
+ /* check for invalid characters */
+ for (const char * p = url; *p != '\0'; p++) {
+ switch (*p) {
+ case ';':
+ case '/':
+ case '?':
+ case ':':
+ case '@':
+ case '&':
+ case '=':
+ case '+':
+ case '$':
+ case ',':
+ case '-':
+ case '_':
+ case '.':
+ case '!':
+ case '~':
+ case '*':
+ case '\'':
+ case '(':
+ case ')':
+ case '%':
+ break;
+ default:
+ if (! isalnum(*p)) {
+ return -1;
+ }
+ break;
+ }
+ }
+
+ int result;
+ if (strncasecmp(url, "http://", 7) == 0) {
+ /* absoluteURI */
+
+ /* advance past the http:// */
+ const char * authority_start = url + 7;
+
+ /* look for a slash or question mark */
+ const char * p;
+ for (p = authority_start; *p != '/' && *p != '?' && *p != '\0'; p++) {
+ ;
+ }
+
+ char * host_and_port = xstrndup(authority_start, p - authority_start);
+ result = URL_parse_host_and_port(host_and_port, host, port);
+ free(host_and_port);
+ if (result != 0) {
+ return result;
+ }
+
+ result = URL_parse_abs_path_and_query(p, abs_path, query);
+ if (result != 0) {
+ free(*host);
+ *host = NULL;
+ return result;
+ }
+ }
+ else {
+ /* abs_path */
+ *host = NULL;
+ *port = 80;
+ result = URL_parse_abs_path_and_query(url, abs_path, query);
+ if (result != 0) {
+ return result;
+ }
+ }
+ result = 0;
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/install-sh b/tools/node_modules/expresso/deps/jscoverage/install-sh
new file mode 100755
index 0000000..a5897de
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/install-sh
@@ -0,0 +1,519 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2006-12-25.00
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# 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
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp b/tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp
new file mode 100644
index 0000000..7a1868a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument-js.cpp
@@ -0,0 +1,1873 @@
+/*
+ instrument-js.cpp - JavaScript instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "instrument-js.h"
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <jsapi.h>
+#include <jsarena.h>
+#include <jsatom.h>
+#include <jsemit.h>
+#include <jsexn.h>
+#include <jsfun.h>
+#include <jsinterp.h>
+#include <jsiter.h>
+#include <jsparse.h>
+#include <jsregexp.h>
+#include <jsscope.h>
+#include <jsstr.h>
+
+#include "encoding.h"
+#include "global.h"
+#include "highlight.h"
+#include "resource-manager.h"
+#include "util.h"
+
+struct IfDirective {
+ const jschar * condition_start;
+ const jschar * condition_end;
+ uint16_t start_line;
+ uint16_t end_line;
+ struct IfDirective * next;
+};
+
+bool jscoverage_mozilla = false;
+
+static bool * exclusive_directives = NULL;
+
+static JSRuntime * runtime = NULL;
+static JSContext * context = NULL;
+static JSObject * global = NULL;
+static JSVersion js_version = JSVERSION_ECMA_3;
+
+/*
+JSParseNode objects store line numbers starting from 1.
+The lines array stores line numbers starting from 0.
+*/
+static const char * file_id = NULL;
+static char * lines = NULL;
+static uint16_t num_lines = 0;
+
+void jscoverage_set_js_version(const char * version) {
+ js_version = JS_StringToVersion(version);
+ if (js_version != JSVERSION_UNKNOWN) {
+ return;
+ }
+
+ char * end;
+ js_version = (JSVersion) strtol(version, &end, 10);
+ if ((size_t) (end - version) != strlen(version)) {
+ fatal("invalid version: %s", version);
+ }
+}
+
+void jscoverage_init(void) {
+ runtime = JS_NewRuntime(8L * 1024L * 1024L);
+ if (runtime == NULL) {
+ fatal("cannot create runtime");
+ }
+
+ context = JS_NewContext(runtime, 8192);
+ if (context == NULL) {
+ fatal("cannot create context");
+ }
+
+ JS_SetVersion(context, js_version);
+
+ global = JS_NewObject(context, NULL, NULL, NULL);
+ if (global == NULL) {
+ fatal("cannot create global object");
+ }
+
+ if (! JS_InitStandardClasses(context, global)) {
+ fatal("cannot initialize standard classes");
+ }
+}
+
+void jscoverage_cleanup(void) {
+ JS_DestroyContext(context);
+ JS_DestroyRuntime(runtime);
+}
+
+static void print_javascript(const jschar * characters, size_t num_characters, Stream * f) {
+ for (size_t i = 0; i < num_characters; i++) {
+ jschar c = characters[i];
+ /*
+ XXX does not handle no-break space, other unicode "space separator"
+ */
+ switch (c) {
+ case 0x9:
+ case 0xB:
+ case 0xC:
+ Stream_write_char(f, c);
+ break;
+ default:
+ if (32 <= c && c <= 126) {
+ Stream_write_char(f, c);
+ }
+ else {
+ Stream_printf(f, "\\u%04x", c);
+ }
+ break;
+ }
+ }
+}
+
+static void print_string(JSString * s, Stream * f) {
+ size_t length = JSSTRING_LENGTH(s);
+ jschar * characters = JSSTRING_CHARS(s);
+ for (size_t i = 0; i < length; i++) {
+ jschar c = characters[i];
+ if (32 <= c && c <= 126) {
+ switch (c) {
+ case '"':
+ Stream_write_string(f, "\\\"");
+ break;
+/*
+ case '\'':
+ Stream_write_string(f, "\\'");
+ break;
+*/
+ case '\\':
+ Stream_write_string(f, "\\\\");
+ break;
+ default:
+ Stream_write_char(f, c);
+ break;
+ }
+ }
+ else {
+ switch (c) {
+ case 0x8:
+ Stream_write_string(f, "\\b");
+ break;
+ case 0x9:
+ Stream_write_string(f, "\\t");
+ break;
+ case 0xa:
+ Stream_write_string(f, "\\n");
+ break;
+ /* IE doesn't support this */
+ /*
+ case 0xb:
+ Stream_write_string(f, "\\v");
+ break;
+ */
+ case 0xc:
+ Stream_write_string(f, "\\f");
+ break;
+ case 0xd:
+ Stream_write_string(f, "\\r");
+ break;
+ default:
+ Stream_printf(f, "\\u%04x", c);
+ break;
+ }
+ }
+ }
+}
+
+static void print_string_atom(JSAtom * atom, Stream * f) {
+ assert(ATOM_IS_STRING(atom));
+ JSString * s = ATOM_TO_STRING(atom);
+ print_string(s, f);
+}
+
+static void print_regex(jsval value, Stream * f) {
+ assert(JSVAL_IS_STRING(value));
+ JSString * s = JSVAL_TO_STRING(value);
+ size_t length = JSSTRING_LENGTH(s);
+ jschar * characters = JSSTRING_CHARS(s);
+ for (size_t i = 0; i < length; i++) {
+ jschar c = characters[i];
+ if (32 <= c && c <= 126) {
+ Stream_write_char(f, c);
+ }
+ else {
+ Stream_printf(f, "\\u%04x", c);
+ }
+ }
+}
+
+static void print_quoted_string_atom(JSAtom * atom, Stream * f) {
+ assert(ATOM_IS_STRING(atom));
+ JSString * s = ATOM_TO_STRING(atom);
+ Stream_write_char(f, '"');
+ print_string(s, f);
+ Stream_write_char(f, '"');
+}
+
+static const char * get_op(uint8 op) {
+ switch(op) {
+ case JSOP_OR:
+ return "||";
+ case JSOP_AND:
+ return "&&";
+ case JSOP_BITOR:
+ return "|";
+ case JSOP_BITXOR:
+ return "^";
+ case JSOP_BITAND:
+ return "&";
+ case JSOP_EQ:
+ return "==";
+ case JSOP_NE:
+ return "!=";
+ case JSOP_STRICTEQ:
+ return "===";
+ case JSOP_STRICTNE:
+ return "!==";
+ case JSOP_LT:
+ return "<";
+ case JSOP_LE:
+ return "<=";
+ case JSOP_GT:
+ return ">";
+ case JSOP_GE:
+ return ">=";
+ case JSOP_LSH:
+ return "<<";
+ case JSOP_RSH:
+ return ">>";
+ case JSOP_URSH:
+ return ">>>";
+ case JSOP_ADD:
+ return "+";
+ case JSOP_SUB:
+ return "-";
+ case JSOP_MUL:
+ return "*";
+ case JSOP_DIV:
+ return "/";
+ case JSOP_MOD:
+ return "%";
+ default:
+ abort();
+ }
+}
+
+static void output_expression(JSParseNode * node, Stream * f, bool parenthesize_object_literals);
+static void instrument_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if);
+static void output_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if);
+
+enum FunctionType {
+ FUNCTION_NORMAL,
+ FUNCTION_GETTER_OR_SETTER
+};
+
+static void output_for_in(JSParseNode * node, Stream * f) {
+ assert(node->pn_type == TOK_FOR);
+ assert(node->pn_arity == PN_BINARY);
+ Stream_write_string(f, "for ");
+ if (node->pn_iflags & JSITER_FOREACH) {
+ Stream_write_string(f, "each ");
+ }
+ Stream_write_char(f, '(');
+ output_expression(node->pn_left, f, false);
+ Stream_write_char(f, ')');
+}
+
+static void output_array_comprehension_or_generator_expression(JSParseNode * node, Stream * f) {
+ assert(node->pn_type == TOK_LEXICALSCOPE);
+ assert(node->pn_arity == PN_NAME);
+ JSParseNode * for_node = node->pn_expr;
+ assert(for_node->pn_type == TOK_FOR);
+ assert(for_node->pn_arity == PN_BINARY);
+ JSParseNode * p = for_node;
+ while (p->pn_type == TOK_FOR) {
+ p = p->pn_right;
+ }
+ JSParseNode * if_node = NULL;
+ if (p->pn_type == TOK_IF) {
+ if_node = p;
+ assert(if_node->pn_arity == PN_TERNARY);
+ p = if_node->pn_kid2;
+ }
+ switch (p->pn_arity) {
+ case PN_UNARY:
+ p = p->pn_kid;
+ if (p->pn_type == TOK_YIELD) {
+ /* for generator expressions */
+ p = p->pn_kid;
+ }
+ output_expression(p, f, false);
+ break;
+ case PN_LIST:
+ /*
+ When the array comprehension contains "if (0)", it will be optimized away and
+ the result will be an empty TOK_LC list.
+ */
+ assert(p->pn_type == TOK_LC);
+ assert(p->pn_head == NULL);
+ /* the "1" is arbitrary (since the list is empty) */
+ Stream_write_char(f, '1');
+ break;
+ default:
+ abort();
+ break;
+ }
+
+ p = for_node;
+ while (p->pn_type == TOK_FOR) {
+ Stream_write_char(f, ' ');
+ output_for_in(p, f);
+ p = p->pn_right;
+ }
+ if (p->pn_type == TOK_LC) {
+ /* this is the optimized-away "if (0)" */
+ Stream_write_string(f, " if (0)");
+ }
+ else if (if_node) {
+ Stream_write_string(f, " if (");
+ output_expression(if_node->pn_kid1, f, false);
+ Stream_write_char(f, ')');
+ }
+}
+
+static void instrument_function(JSParseNode * node, Stream * f, int indent, enum FunctionType type) {
+ assert(node->pn_type == TOK_FUNCTION);
+ assert(node->pn_arity == PN_FUNC);
+ JSObject * object = node->pn_funpob->object;
+ assert(JS_ObjectIsFunction(context, object));
+ JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
+ assert(function);
+ assert(object == &function->object);
+ Stream_printf(f, "%*s", indent, "");
+ if (type == FUNCTION_NORMAL) {
+ Stream_write_string(f, "function ");
+ }
+
+ /* function name */
+ if (function->atom) {
+ print_string_atom(function->atom, f);
+ }
+
+ /*
+ function parameters - see JS_DecompileFunction in jsapi.cpp, which calls
+ js_DecompileFunction in jsopcode.cpp
+ */
+ Stream_write_char(f, '(');
+ JSArenaPool pool;
+ JS_INIT_ARENA_POOL(&pool, "instrument_function", 256, 1, &context->scriptStackQuota);
+ jsuword * local_names = NULL;
+ if (JS_GET_LOCAL_NAME_COUNT(function)) {
+ local_names = js_GetLocalNameArray(context, function, &pool);
+ if (local_names == NULL) {
+ fatal("out of memory");
+ }
+ }
+ bool destructuring = false;
+ for (int i = 0; i < function->nargs; i++) {
+ if (i > 0) {
+ Stream_write_string(f, ", ");
+ }
+ JSAtom * param = JS_LOCAL_NAME_TO_ATOM(local_names[i]);
+ if (param == NULL) {
+ destructuring = true;
+ JSParseNode * expression = NULL;
+ assert(node->pn_body->pn_type == TOK_LC || node->pn_body->pn_type == TOK_SEQ);
+ JSParseNode * semi = node->pn_body->pn_head;
+ assert(semi->pn_type == TOK_SEMI);
+ JSParseNode * comma = semi->pn_kid;
+ assert(comma->pn_type == TOK_COMMA);
+ for (JSParseNode * p = comma->pn_head; p != NULL; p = p->pn_next) {
+ assert(p->pn_type == TOK_ASSIGN);
+ JSParseNode * rhs = p->pn_right;
+ assert(JSSTRING_LENGTH(ATOM_TO_STRING(rhs->pn_atom)) == 0);
+ if (rhs->pn_slot == i) {
+ expression = p->pn_left;
+ break;
+ }
+ }
+ assert(expression != NULL);
+ output_expression(expression, f, false);
+ }
+ else {
+ print_string_atom(param, f);
+ }
+ }
+ JS_FinishArenaPool(&pool);
+ Stream_write_string(f, ") {\n");
+
+ /* function body */
+ if (function->flags & JSFUN_EXPR_CLOSURE) {
+ /* expression closure - use output_statement instead of instrument_statement */
+ if (node->pn_body->pn_type == TOK_SEQ) {
+ assert(node->pn_body->pn_arity == PN_LIST);
+ assert(node->pn_body->pn_count == 2);
+ output_statement(node->pn_body->pn_head->pn_next, f, indent + 2, false);
+ }
+ else {
+ output_statement(node->pn_body, f, indent + 2, false);
+ }
+ }
+ else {
+ assert(node->pn_body->pn_type == TOK_LC);
+ assert(node->pn_body->pn_arity == PN_LIST);
+ JSParseNode * p = node->pn_body->pn_head;
+ if (destructuring) {
+ p = p->pn_next;
+ }
+ for (; p != NULL; p = p->pn_next) {
+ instrument_statement(p, f, indent + 2, false);
+ }
+ }
+
+ Stream_write_char(f, '}');
+}
+
+static void instrument_function_call(JSParseNode * node, Stream * f) {
+ JSParseNode * function_node = node->pn_head;
+ if (function_node->pn_type == TOK_FUNCTION) {
+ JSObject * object = function_node->pn_funpob->object;
+ assert(JS_ObjectIsFunction(context, object));
+ JSFunction * function = (JSFunction *) JS_GetPrivate(context, object);
+ assert(function);
+ assert(object == &function->object);
+
+ if (function_node->pn_flags & TCF_GENEXP_LAMBDA) {
+ /* it's a generator expression */
+ Stream_write_char(f, '(');
+ output_array_comprehension_or_generator_expression(function_node->pn_body, f);
+ Stream_write_char(f, ')');
+ return;
+ }
+ }
+ output_expression(function_node, f, false);
+ Stream_write_char(f, '(');
+ for (struct JSParseNode * p = function_node->pn_next; p != NULL; p = p->pn_next) {
+ if (p != node->pn_head->pn_next) {
+ Stream_write_string(f, ", ");
+ }
+ output_expression(p, f, false);
+ }
+ Stream_write_char(f, ')');
+}
+
+static void instrument_declarations(JSParseNode * list, Stream * f) {
+ assert(list->pn_arity == PN_LIST);
+ for (JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) {
+ if (p != list->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+ output_expression(p, f, false);
+ }
+}
+
+/*
+See <Expressions> in jsparse.h.
+TOK_FUNCTION is handled as a statement and as an expression.
+TOK_DBLDOT is not handled (XML op).
+TOK_DEFSHARP and TOK_USESHARP are not handled.
+TOK_ANYNAME is not handled (XML op).
+TOK_AT is not handled (XML op).
+TOK_DBLCOLON is not handled.
+TOK_XML* are not handled.
+There seem to be some undocumented expressions:
+TOK_INSTANCEOF binary
+TOK_IN binary
+*/
+static void output_expression(JSParseNode * node, Stream * f, bool parenthesize_object_literals) {
+ switch (node->pn_type) {
+ case TOK_FUNCTION:
+ Stream_write_char(f, '(');
+ instrument_function(node, f, 0, FUNCTION_NORMAL);
+ Stream_write_char(f, ')');
+ break;
+ case TOK_COMMA:
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p != node->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+ output_expression(p, f, parenthesize_object_literals);
+ }
+ break;
+ case TOK_ASSIGN:
+ output_expression(node->pn_left, f, parenthesize_object_literals);
+ Stream_write_char(f, ' ');
+ switch (node->pn_op) {
+ case JSOP_ADD:
+ case JSOP_SUB:
+ case JSOP_MUL:
+ case JSOP_MOD:
+ case JSOP_LSH:
+ case JSOP_RSH:
+ case JSOP_URSH:
+ case JSOP_BITAND:
+ case JSOP_BITOR:
+ case JSOP_BITXOR:
+ case JSOP_DIV:
+ Stream_printf(f, "%s", get_op(node->pn_op));
+ break;
+ default:
+ /* do nothing - it must be a simple assignment */
+ break;
+ }
+ Stream_write_string(f, "= ");
+ output_expression(node->pn_right, f, false);
+ break;
+ case TOK_HOOK:
+ output_expression(node->pn_kid1, f, parenthesize_object_literals);
+ Stream_write_string(f, "? ");
+ output_expression(node->pn_kid2, f, false);
+ Stream_write_string(f, ": ");
+ output_expression(node->pn_kid3, f, false);
+ break;
+ case TOK_OR:
+ case TOK_AND:
+ case TOK_BITOR:
+ case TOK_BITXOR:
+ case TOK_BITAND:
+ case TOK_EQOP:
+ case TOK_RELOP:
+ case TOK_SHOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ case TOK_STAR:
+ case TOK_DIVOP:
+ switch (node->pn_arity) {
+ case PN_BINARY:
+ output_expression(node->pn_left, f, parenthesize_object_literals);
+ Stream_printf(f, " %s ", get_op(node->pn_op));
+ output_expression(node->pn_right, f, false);
+ break;
+ case PN_LIST:
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p == node->pn_head) {
+ output_expression(p, f, parenthesize_object_literals);
+ }
+ else {
+ Stream_printf(f, " %s ", get_op(node->pn_op));
+ output_expression(p, f, false);
+ }
+ }
+ break;
+ default:
+ abort();
+ }
+ break;
+ case TOK_UNARYOP:
+ switch (node->pn_op) {
+ case JSOP_NEG:
+ Stream_write_string(f, "- ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_POS:
+ Stream_write_string(f, "+ ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_NOT:
+ Stream_write_string(f, "! ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_BITNOT:
+ Stream_write_string(f, "~ ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_TYPEOF:
+ Stream_write_string(f, "typeof ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_VOID:
+ Stream_write_string(f, "void ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ default:
+ fatal_source(file_id, node->pn_pos.begin.lineno, "unknown operator (%d)", node->pn_op);
+ break;
+ }
+ break;
+ case TOK_INC:
+ case TOK_DEC:
+ /*
+ This is not documented, but node->pn_op tells whether it is pre- or post-increment.
+ */
+ switch (node->pn_op) {
+ case JSOP_INCNAME:
+ case JSOP_INCPROP:
+ case JSOP_INCELEM:
+ Stream_write_string(f, "++");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_DECNAME:
+ case JSOP_DECPROP:
+ case JSOP_DECELEM:
+ Stream_write_string(f, "--");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case JSOP_NAMEINC:
+ case JSOP_PROPINC:
+ case JSOP_ELEMINC:
+ output_expression(node->pn_kid, f, parenthesize_object_literals);
+ Stream_write_string(f, "++");
+ break;
+ case JSOP_NAMEDEC:
+ case JSOP_PROPDEC:
+ case JSOP_ELEMDEC:
+ output_expression(node->pn_kid, f, parenthesize_object_literals);
+ Stream_write_string(f, "--");
+ break;
+ default:
+ abort();
+ break;
+ }
+ break;
+ case TOK_NEW:
+ Stream_write_string(f, "new ");
+ instrument_function_call(node, f);
+ break;
+ case TOK_DELETE:
+ Stream_write_string(f, "delete ");
+ output_expression(node->pn_kid, f, false);
+ break;
+ case TOK_DOT:
+ /* numeric literals must be parenthesized */
+ switch (node->pn_expr->pn_type) {
+ case TOK_NUMBER:
+ Stream_write_char(f, '(');
+ output_expression(node->pn_expr, f, false);
+ Stream_write_char(f, ')');
+ break;
+ default:
+ output_expression(node->pn_expr, f, true);
+ break;
+ }
+ /*
+ This may have originally been x['foo-bar']. Because the string 'foo-bar'
+ contains illegal characters, we have to use the subscript syntax instead of
+ the dot syntax.
+ */
+ assert(ATOM_IS_STRING(node->pn_atom));
+ {
+ JSString * s = ATOM_TO_STRING(node->pn_atom);
+ bool must_quote;
+ if (JSSTRING_LENGTH(s) == 0) {
+ must_quote = true;
+ }
+ else if (js_CheckKeyword(JSSTRING_CHARS(s), JSSTRING_LENGTH(s)) != TOK_EOF) {
+ must_quote = true;
+ }
+ else if (! js_IsIdentifier(s)) {
+ must_quote = true;
+ }
+ else {
+ must_quote = false;
+ }
+ if (must_quote) {
+ Stream_write_char(f, '[');
+ print_quoted_string_atom(node->pn_atom, f);
+ Stream_write_char(f, ']');
+ }
+ else {
+ Stream_write_char(f, '.');
+ print_string_atom(node->pn_atom, f);
+ }
+ }
+ break;
+ case TOK_LB:
+ output_expression(node->pn_left, f, false);
+ Stream_write_char(f, '[');
+ output_expression(node->pn_right, f, false);
+ Stream_write_char(f, ']');
+ break;
+ case TOK_LP:
+ instrument_function_call(node, f);
+ break;
+ case TOK_RB:
+ Stream_write_char(f, '[');
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p != node->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+ /* TOK_COMMA is a special case: a hole in the array */
+ if (p->pn_type != TOK_COMMA) {
+ output_expression(p, f, false);
+ }
+ }
+ if (node->pn_extra == PNX_ENDCOMMA) {
+ Stream_write_char(f, ',');
+ }
+ Stream_write_char(f, ']');
+ break;
+ case TOK_RC:
+ if (parenthesize_object_literals) {
+ Stream_write_char(f, '(');
+ }
+ Stream_write_char(f, '{');
+ for (struct JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ if (p->pn_type != TOK_COLON) {
+ fatal_source(file_id, p->pn_pos.begin.lineno, "unsupported node type (%d)", p->pn_type);
+ }
+ if (p != node->pn_head) {
+ Stream_write_string(f, ", ");
+ }
+
+ /* check whether this is a getter or setter */
+ switch (p->pn_op) {
+ case JSOP_GETTER:
+ case JSOP_SETTER:
+ if (p->pn_op == JSOP_GETTER) {
+ Stream_write_string(f, "get ");
+ }
+ else {
+ Stream_write_string(f, "set ");
+ }
+ output_expression(p->pn_left, f, false);
+ Stream_write_char(f, ' ');
+ if (p->pn_right->pn_type != TOK_FUNCTION) {
+ fatal_source(file_id, p->pn_pos.begin.lineno, "expected function");
+ }
+ instrument_function(p->pn_right, f, 0, FUNCTION_GETTER_OR_SETTER);
+ break;
+ default:
+ output_expression(p->pn_left, f, false);
+ Stream_write_string(f, ": ");
+ output_expression(p->pn_right, f, false);
+ break;
+ }
+ }
+ Stream_write_char(f, '}');
+ if (parenthesize_object_literals) {
+ Stream_write_char(f, ')');
+ }
+ break;
+ case TOK_RP:
+ Stream_write_char(f, '(');
+ output_expression(node->pn_kid, f, false);
+ Stream_write_char(f, ')');
+ break;
+ case TOK_NAME:
+ print_string_atom(node->pn_atom, f);
+ if (node->pn_expr != NULL) {
+ Stream_write_string(f, " = ");
+ output_expression(node->pn_expr, f, false);
+ }
+ break;
+ case TOK_STRING:
+ print_quoted_string_atom(node->pn_atom, f);
+ break;
+ case TOK_REGEXP:
+ assert(node->pn_op == JSOP_REGEXP);
+ {
+ JSObject * object = node->pn_pob->object;
+ jsval result;
+ js_regexp_toString(context, object, &result);
+ print_regex(result, f);
+ }
+ break;
+ case TOK_NUMBER:
+ /*
+ A 64-bit IEEE 754 floating point number has a 52-bit fraction.
+ 2^(-52) = 2.22 x 10^(-16)
+ Thus there are 16 significant digits.
+ To keep the output simple, special-case zero.
+ */
+ if (node->pn_dval == 0.0) {
+ if (signbit(node->pn_dval)) {
+ Stream_write_string(f, "-0");
+ }
+ else {
+ Stream_write_string(f, "0");
+ }
+ }
+ else if (node->pn_dval == INFINITY) {
+ Stream_write_string(f, "Number.POSITIVE_INFINITY");
+ }
+ else if (node->pn_dval == -INFINITY) {
+ Stream_write_string(f, "Number.NEGATIVE_INFINITY");
+ }
+ else if (isnan(node->pn_dval)) {
+ Stream_write_string(f, "Number.NaN");
+ }
+ else {
+ Stream_printf(f, "%.15g", node->pn_dval);
+ }
+ break;
+ case TOK_PRIMARY:
+ switch (node->pn_op) {
+ case JSOP_TRUE:
+ Stream_write_string(f, "true");
+ break;
+ case JSOP_FALSE:
+ Stream_write_string(f, "false");
+ break;
+ case JSOP_NULL:
+ Stream_write_string(f, "null");
+ break;
+ case JSOP_THIS:
+ Stream_write_string(f, "this");
+ break;
+ /* jsscan.h mentions `super' ??? */
+ default:
+ abort();
+ }
+ break;
+ case TOK_INSTANCEOF:
+ output_expression(node->pn_left, f, parenthesize_object_literals);
+ Stream_write_string(f, " instanceof ");
+ output_expression(node->pn_right, f, false);
+ break;
+ case TOK_IN:
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, " in ");
+ output_expression(node->pn_right, f, false);
+ break;
+ case TOK_LEXICALSCOPE:
+ assert(node->pn_arity == PN_NAME);
+ assert(node->pn_expr->pn_type == TOK_LET);
+ assert(node->pn_expr->pn_arity == PN_BINARY);
+ Stream_write_string(f, "let(");
+ assert(node->pn_expr->pn_left->pn_type == TOK_LP);
+ assert(node->pn_expr->pn_left->pn_arity == PN_LIST);
+ instrument_declarations(node->pn_expr->pn_left, f);
+ Stream_write_string(f, ") ");
+ output_expression(node->pn_expr->pn_right, f, true);
+ break;
+ case TOK_YIELD:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_write_string(f, "yield");
+ if (node->pn_kid != NULL) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_kid, f, true);
+ }
+ break;
+ case TOK_ARRAYCOMP:
+ assert(node->pn_arity == PN_LIST);
+ {
+ JSParseNode * block_node;
+ switch (node->pn_count) {
+ case 1:
+ block_node = node->pn_head;
+ break;
+ case 2:
+ block_node = node->pn_head->pn_next;
+ break;
+ default:
+ abort();
+ break;
+ }
+ Stream_write_char(f, '[');
+ output_array_comprehension_or_generator_expression(block_node, f);
+ Stream_write_char(f, ']');
+ }
+ break;
+ case TOK_VAR:
+ assert(node->pn_arity == PN_LIST);
+ Stream_write_string(f, "var ");
+ instrument_declarations(node, f);
+ break;
+ case TOK_LET:
+ assert(node->pn_arity == PN_LIST);
+ Stream_write_string(f, "let ");
+ instrument_declarations(node, f);
+ break;
+ default:
+ fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type);
+ }
+}
+
+static void output_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if) {
+ switch (node->pn_type) {
+ case TOK_FUNCTION:
+ instrument_function(node, f, indent, FUNCTION_NORMAL);
+ Stream_write_char(f, '\n');
+ break;
+ case TOK_LC:
+ assert(node->pn_arity == PN_LIST);
+/*
+ Stream_write_string(f, "{\n");
+*/
+ for (struct JSParseNode * p = node->pn_u.list.head; p != NULL; p = p->pn_next) {
+ instrument_statement(p, f, indent, false);
+ }
+/*
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+*/
+ break;
+ case TOK_IF:
+ {
+ assert(node->pn_arity == PN_TERNARY);
+
+ uint16_t line = node->pn_pos.begin.lineno;
+ if (! is_jscoverage_if) {
+ if (line > num_lines) {
+ fatal("file %s contains more than 65,535 lines", file_id);
+ }
+ if (line >= 2 && exclusive_directives[line - 2]) {
+ is_jscoverage_if = true;
+ }
+ }
+
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "if (");
+ output_expression(node->pn_kid1, f, false);
+ Stream_write_string(f, ") {\n");
+ if (is_jscoverage_if && node->pn_kid3) {
+ uint16_t else_start = node->pn_kid3->pn_pos.begin.lineno;
+ uint16_t else_end = node->pn_kid3->pn_pos.end.lineno + 1;
+ Stream_printf(f, "%*s", indent + 2, "");
+ Stream_printf(f, "_$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, else_start, else_end);
+ }
+ instrument_statement(node->pn_kid2, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+
+ if (node->pn_kid3 || is_jscoverage_if) {
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "else {\n");
+
+ if (is_jscoverage_if) {
+ uint16_t if_start = node->pn_kid2->pn_pos.begin.lineno + 1;
+ uint16_t if_end = node->pn_kid2->pn_pos.end.lineno + 1;
+ Stream_printf(f, "%*s", indent + 2, "");
+ Stream_printf(f, "_$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, if_start, if_end);
+ }
+
+ if (node->pn_kid3) {
+ instrument_statement(node->pn_kid3, f, indent + 2, is_jscoverage_if);
+ }
+
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+
+ break;
+ }
+ case TOK_SWITCH:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "switch (");
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, ") {\n");
+ {
+ JSParseNode * list = node->pn_right;
+ if (list->pn_type == TOK_LEXICALSCOPE) {
+ list = list->pn_expr;
+ }
+ for (struct JSParseNode * p = list->pn_head; p != NULL; p = p->pn_next) {
+ Stream_printf(f, "%*s", indent, "");
+ switch (p->pn_type) {
+ case TOK_CASE:
+ Stream_write_string(f, "case ");
+ output_expression(p->pn_left, f, false);
+ Stream_write_string(f, ":\n");
+ break;
+ case TOK_DEFAULT:
+ Stream_write_string(f, "default:\n");
+ break;
+ default:
+ abort();
+ break;
+ }
+ instrument_statement(p->pn_right, f, indent + 2, false);
+ }
+ }
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_CASE:
+ case TOK_DEFAULT:
+ abort();
+ break;
+ case TOK_WHILE:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "while (");
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, ") {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_DO:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "do {\n");
+ instrument_statement(node->pn_left, f, indent + 2, false);
+ Stream_write_string(f, "}\n");
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "while (");
+ output_expression(node->pn_right, f, false);
+ Stream_write_string(f, ");\n");
+ break;
+ case TOK_FOR:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ switch (node->pn_left->pn_type) {
+ case TOK_IN:
+ /* for/in */
+ assert(node->pn_left->pn_arity == PN_BINARY);
+ output_for_in(node, f);
+ break;
+ case TOK_FORHEAD:
+ /* for (;;) */
+ assert(node->pn_left->pn_arity == PN_TERNARY);
+ Stream_write_string(f, "for (");
+ if (node->pn_left->pn_kid1) {
+ output_expression(node->pn_left->pn_kid1, f, false);
+ }
+ Stream_write_string(f, ";");
+ if (node->pn_left->pn_kid2) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_left->pn_kid2, f, false);
+ }
+ Stream_write_string(f, ";");
+ if (node->pn_left->pn_kid3) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_left->pn_kid3, f, false);
+ }
+ Stream_write_char(f, ')');
+ break;
+ default:
+ abort();
+ break;
+ }
+ Stream_write_string(f, " {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_THROW:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "throw ");
+ output_expression(node->pn_u.unary.kid, f, false);
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_TRY:
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "try {\n");
+ instrument_statement(node->pn_kid1, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ if (node->pn_kid2) {
+ assert(node->pn_kid2->pn_type == TOK_RESERVED);
+ for (JSParseNode * scope = node->pn_kid2->pn_head; scope != NULL; scope = scope->pn_next) {
+ assert(scope->pn_type == TOK_LEXICALSCOPE);
+ JSParseNode * catch_node = scope->pn_expr;
+ assert(catch_node->pn_type == TOK_CATCH);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "catch (");
+ output_expression(catch_node->pn_kid1, f, false);
+ if (catch_node->pn_kid2) {
+ Stream_write_string(f, " if ");
+ output_expression(catch_node->pn_kid2, f, false);
+ }
+ Stream_write_string(f, ") {\n");
+ instrument_statement(catch_node->pn_kid3, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+ }
+ if (node->pn_kid3) {
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "finally {\n");
+ instrument_statement(node->pn_kid3, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+ break;
+ case TOK_CATCH:
+ abort();
+ break;
+ case TOK_BREAK:
+ case TOK_CONTINUE:
+ assert(node->pn_arity == PN_NAME || node->pn_arity == PN_NULLARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, node->pn_type == TOK_BREAK? "break": "continue");
+ if (node->pn_atom != NULL) {
+ Stream_write_char(f, ' ');
+ print_string_atom(node->pn_atom, f);
+ }
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_WITH:
+ assert(node->pn_arity == PN_BINARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "with (");
+ output_expression(node->pn_left, f, false);
+ Stream_write_string(f, ") {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_VAR:
+ Stream_printf(f, "%*s", indent, "");
+ output_expression(node, f, false);
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_RETURN:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "return");
+ if (node->pn_kid != NULL) {
+ Stream_write_char(f, ' ');
+ output_expression(node->pn_kid, f, true);
+ }
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_SEMI:
+ assert(node->pn_arity == PN_UNARY);
+ Stream_printf(f, "%*s", indent, "");
+ if (node->pn_kid != NULL) {
+ output_expression(node->pn_kid, f, true);
+ }
+ Stream_write_string(f, ";\n");
+ break;
+ case TOK_COLON:
+ {
+ assert(node->pn_arity == PN_NAME);
+ Stream_printf(f, "%*s", indent < 2? 0: indent - 2, "");
+ print_string_atom(node->pn_atom, f);
+ Stream_write_string(f, ":\n");
+ JSParseNode * labelled = node->pn_expr;
+ if (labelled->pn_type == TOK_LEXICALSCOPE) {
+ labelled = labelled->pn_expr;
+ }
+ if (labelled->pn_type == TOK_LC) {
+ /* labelled block */
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "{\n");
+ instrument_statement(labelled, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ }
+ else {
+ /*
+ This one is tricky: can't output instrumentation between the label and the
+ statement it's supposed to label, so use output_statement instead of
+ instrument_statement.
+ */
+ output_statement(labelled, f, indent, false);
+ }
+ break;
+ }
+ case TOK_LEXICALSCOPE:
+ /* let statement */
+ assert(node->pn_arity == PN_NAME);
+ switch (node->pn_expr->pn_type) {
+ case TOK_LET:
+ /* let statement */
+ assert(node->pn_expr->pn_arity == PN_BINARY);
+ instrument_statement(node->pn_expr, f, indent, false);
+ break;
+ case TOK_LC:
+ /* block */
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "{\n");
+ instrument_statement(node->pn_expr, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case TOK_FOR:
+ instrument_statement(node->pn_expr, f, indent, false);
+ break;
+ default:
+ abort();
+ break;
+ }
+ break;
+ case TOK_LET:
+ switch (node->pn_arity) {
+ case PN_BINARY:
+ /* let statement */
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "let (");
+ assert(node->pn_left->pn_type == TOK_LP);
+ assert(node->pn_left->pn_arity == PN_LIST);
+ instrument_declarations(node->pn_left, f);
+ Stream_write_string(f, ") {\n");
+ instrument_statement(node->pn_right, f, indent + 2, false);
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "}\n");
+ break;
+ case PN_LIST:
+ /* let definition */
+ Stream_printf(f, "%*s", indent, "");
+ output_expression(node, f, false);
+ Stream_write_string(f, ";\n");
+ break;
+ default:
+ abort();
+ break;
+ }
+ break;
+ case TOK_DEBUGGER:
+ Stream_printf(f, "%*s", indent, "");
+ Stream_write_string(f, "debugger;\n");
+ break;
+ case TOK_SEQ:
+ /*
+ This occurs with the statement:
+ for (var a = b in c) {}
+ */
+ assert(node->pn_arity == PN_LIST);
+ for (JSParseNode * p = node->pn_head; p != NULL; p = p->pn_next) {
+ instrument_statement(p, f, indent, false);
+ }
+ break;
+ default:
+ fatal_source(file_id, node->pn_pos.begin.lineno, "unsupported node type (%d)", node->pn_type);
+ }
+}
+
+/*
+See <Statements> in jsparse.h.
+TOK_FUNCTION is handled as a statement and as an expression.
+TOK_EXPORT, TOK_IMPORT are not handled.
+*/
+static void instrument_statement(JSParseNode * node, Stream * f, int indent, bool is_jscoverage_if) {
+ if (node->pn_type != TOK_LC && node->pn_type != TOK_LEXICALSCOPE) {
+ uint16_t line = node->pn_pos.begin.lineno;
+ if (line > num_lines) {
+ fatal("file %s contains more than 65,535 lines", file_id);
+ }
+
+ /* the root node has line number 0 */
+ if (line != 0) {
+ Stream_printf(f, "%*s", indent, "");
+ Stream_printf(f, "_$jscoverage['%s'][%d]++;\n", file_id, line);
+ lines[line - 1] = 1;
+ }
+ }
+ output_statement(node, f, indent, is_jscoverage_if);
+}
+
+static bool characters_start_with(const jschar * characters, size_t line_start, size_t line_end, const char * prefix) {
+ const jschar * characters_end = characters + line_end;
+ const jschar * cp = characters + line_start;
+ const char * bp = prefix;
+ for (;;) {
+ if (*bp == '\0') {
+ return true;
+ }
+ else if (cp == characters_end) {
+ return false;
+ }
+ else if (*cp != *bp) {
+ return false;
+ }
+ bp++;
+ cp++;
+ }
+}
+
+static bool characters_are_white_space(const jschar * characters, size_t line_start, size_t line_end) {
+ /* XXX - other Unicode space */
+ const jschar * end = characters + line_end;
+ for (const jschar * p = characters + line_start; p < end; p++) {
+ jschar c = *p;
+ if (c == 0x9 || c == 0xB || c == 0xC || c == 0x20 || c == 0xA0) {
+ continue;
+ }
+ else {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void error_reporter(JSContext * context, const char * message, JSErrorReport * report) {
+ warn_source(file_id, report->lineno, "%s", message);
+}
+
+void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output) {
+ file_id = id;
+
+ /* parse the javascript */
+ JSParseContext parse_context;
+ if (! js_InitParseContext(context, &parse_context, NULL, NULL, characters, num_characters, NULL, NULL, 1)) {
+ fatal("cannot create token stream from file %s", file_id);
+ }
+ JSErrorReporter old_error_reporter = JS_SetErrorReporter(context, error_reporter);
+ JSParseNode * node = js_ParseScript(context, global, &parse_context);
+ if (node == NULL) {
+ js_ReportUncaughtException(context);
+ fatal("parse error in file %s", file_id);
+ }
+ JS_SetErrorReporter(context, old_error_reporter);
+ num_lines = node->pn_pos.end.lineno;
+ lines = (char *) xmalloc(num_lines);
+ for (unsigned int i = 0; i < num_lines; i++) {
+ lines[i] = 0;
+ }
+
+ /* search code for conditionals */
+ exclusive_directives = xnew(bool, num_lines);
+ for (unsigned int i = 0; i < num_lines; i++) {
+ exclusive_directives[i] = false;
+ }
+
+ bool has_conditionals = false;
+ struct IfDirective * if_directives = NULL;
+ size_t line_number = 0;
+ size_t i = 0;
+ while (i < num_characters) {
+ if (line_number == UINT16_MAX) {
+ fatal("file %s contains more than 65,535 lines", file_id);
+ }
+ line_number++;
+ size_t line_start = i;
+ jschar c;
+ bool done = false;
+ while (! done && i < num_characters) {
+ c = characters[i];
+ switch (c) {
+ case '\r':
+ case '\n':
+ case 0x2028:
+ case 0x2029:
+ done = true;
+ break;
+ default:
+ i++;
+ }
+ }
+ size_t line_end = i;
+ if (i < num_characters) {
+ i++;
+ if (c == '\r' && i < num_characters && characters[i] == '\n') {
+ i++;
+ }
+ }
+
+ if (characters_start_with(characters, line_start, line_end, "//#JSCOVERAGE_IF")) {
+ has_conditionals = true;
+
+ if (characters_are_white_space(characters, line_start + 16, line_end)) {
+ exclusive_directives[line_number - 1] = true;
+ }
+ else {
+ struct IfDirective * if_directive = xnew(struct IfDirective, 1);
+ if_directive->condition_start = characters + line_start + 16;
+ if_directive->condition_end = characters + line_end;
+ if_directive->start_line = line_number;
+ if_directive->end_line = 0;
+ if_directive->next = if_directives;
+ if_directives = if_directive;
+ }
+ }
+ else if (characters_start_with(characters, line_start, line_end, "//#JSCOVERAGE_ENDIF")) {
+ for (struct IfDirective * p = if_directives; p != NULL; p = p->next) {
+ if (p->end_line == 0) {
+ p->end_line = line_number;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ An instrumented JavaScript file has 4 sections:
+ 1. initialization
+ 2. instrumented source code
+ 3. conditionals
+ 4. original source code
+ */
+
+ Stream * instrumented = Stream_new(0);
+ instrument_statement(node, instrumented, 0, false);
+ js_FinishParseContext(context, &parse_context);
+
+ /* write line number info to the output */
+ Stream_write_string(output, "/* automatically generated by JSCoverage - do not edit */\n");
+ Stream_write_string(output, "if (typeof _$jscoverage === 'undefined') _$jscoverage = {};\n");
+ Stream_printf(output, "if (! _$jscoverage['%s']) {\n", file_id);
+ Stream_printf(output, " _$jscoverage['%s'] = [];\n", file_id);
+ for (int i = 0; i < num_lines; i++) {
+ if (lines[i]) {
+ Stream_printf(output, " _$jscoverage['%s'][%d] = 0;\n", file_id, i + 1);
+ }
+ }
+ Stream_write_string(output, "}\n");
+ free(lines);
+ lines = NULL;
+ free(exclusive_directives);
+ exclusive_directives = NULL;
+
+ /* conditionals */
+ if (has_conditionals) {
+ Stream_printf(output, "_$jscoverage['%s'].conditionals = [];\n", file_id);
+ }
+
+ /* copy the instrumented source code to the output */
+ Stream_write(output, instrumented->data, instrumented->length);
+
+ /* conditionals */
+ for (struct IfDirective * if_directive = if_directives; if_directive != NULL; if_directive = if_directive->next) {
+ Stream_write_string(output, "if (!(");
+ print_javascript(if_directive->condition_start, if_directive->condition_end - if_directive->condition_start, output);
+ Stream_write_string(output, ")) {\n");
+ Stream_printf(output, " _$jscoverage['%s'].conditionals[%d] = %d;\n", file_id, if_directive->start_line, if_directive->end_line);
+ Stream_write_string(output, "}\n");
+ }
+
+ /* free */
+ while (if_directives != NULL) {
+ struct IfDirective * if_directive = if_directives;
+ if_directives = if_directives->next;
+ free(if_directive);
+ }
+
+ /* copy the original source to the output */
+ Stream_printf(output, "_$jscoverage['%s'].source = ", file_id);
+ jscoverage_write_source(id, characters, num_characters, output);
+ Stream_printf(output, ";\n");
+
+ Stream_delete(instrumented);
+
+ file_id = NULL;
+}
+
+void jscoverage_write_source(const char * id, const jschar * characters, size_t num_characters, Stream * output) {
+ Stream_write_string(output, "[");
+ if (jscoverage_highlight) {
+ Stream * highlighted_stream = Stream_new(num_characters);
+ jscoverage_highlight_js(context, id, characters, num_characters, highlighted_stream);
+ size_t i = 0;
+ while (i < highlighted_stream->length) {
+ if (i > 0) {
+ Stream_write_char(output, ',');
+ }
+
+ Stream_write_char(output, '"');
+ bool done = false;
+ while (! done) {
+ char c = highlighted_stream->data[i];
+ switch (c) {
+ case 0x8:
+ /* backspace */
+ Stream_write_string(output, "\\b");
+ break;
+ case 0x9:
+ /* horizontal tab */
+ Stream_write_string(output, "\\t");
+ break;
+ case 0xa:
+ /* line feed (new line) */
+ done = true;
+ break;
+ /* IE doesn't support this */
+ /*
+ case 0xb:
+ Stream_write_string(output, "\\v");
+ break;
+ */
+ case 0xc:
+ /* form feed */
+ Stream_write_string(output, "\\f");
+ break;
+ case 0xd:
+ /* carriage return */
+ done = true;
+ if (i + 1 < highlighted_stream->length && highlighted_stream->data[i + 1] == '\n') {
+ i++;
+ }
+ break;
+ case '"':
+ Stream_write_string(output, "\\\"");
+ break;
+ case '\\':
+ Stream_write_string(output, "\\\\");
+ break;
+ default:
+ Stream_write_char(output, c);
+ break;
+ }
+ i++;
+ if (i >= highlighted_stream->length) {
+ done = true;
+ }
+ }
+ Stream_write_char(output, '"');
+ }
+ Stream_delete(highlighted_stream);
+ }
+ else {
+ size_t i = 0;
+ while (i < num_characters) {
+ if (i > 0) {
+ Stream_write_char(output, ',');
+ }
+
+ Stream_write_char(output, '"');
+ bool done = false;
+ while (! done) {
+ jschar c = characters[i];
+ switch (c) {
+ case 0x8:
+ /* backspace */
+ Stream_write_string(output, "\\b");
+ break;
+ case 0x9:
+ /* horizontal tab */
+ Stream_write_string(output, "\\t");
+ break;
+ case 0xa:
+ /* line feed (new line) */
+ done = true;
+ break;
+ /* IE doesn't support this */
+ /*
+ case 0xb:
+ Stream_write_string(output, "\\v");
+ break;
+ */
+ case 0xc:
+ /* form feed */
+ Stream_write_string(output, "\\f");
+ break;
+ case 0xd:
+ /* carriage return */
+ done = true;
+ if (i + 1 < num_characters && characters[i + 1] == '\n') {
+ i++;
+ }
+ break;
+ case '"':
+ Stream_write_string(output, "\\\"");
+ break;
+ case '\\':
+ Stream_write_string(output, "\\\\");
+ break;
+ case '&':
+ Stream_write_string(output, "&amp;");
+ break;
+ case '<':
+ Stream_write_string(output, "&lt;");
+ break;
+ case '>':
+ Stream_write_string(output, "&gt;");
+ break;
+ case 0x2028:
+ case 0x2029:
+ done = true;
+ break;
+ default:
+ if (32 <= c && c <= 126) {
+ Stream_write_char(output, c);
+ }
+ else {
+ Stream_printf(output, "&#%d;", c);
+ }
+ break;
+ }
+ i++;
+ if (i >= num_characters) {
+ done = true;
+ }
+ }
+ Stream_write_char(output, '"');
+ }
+ }
+ Stream_write_string(output, "]");
+}
+
+void jscoverage_copy_resources(const char * destination_directory) {
+ copy_resource("jscoverage.html", destination_directory);
+ copy_resource("jscoverage.css", destination_directory);
+ copy_resource("jscoverage.js", destination_directory);
+ copy_resource("jscoverage-ie.css", destination_directory);
+ copy_resource("jscoverage-throbber.gif", destination_directory);
+ copy_resource("jscoverage-highlight.css", destination_directory);
+}
+
+/*
+coverage reports
+*/
+
+struct FileCoverageList {
+ FileCoverage * file_coverage;
+ struct FileCoverageList * next;
+};
+
+struct Coverage {
+ JSHashTable * coverage_table;
+ struct FileCoverageList * coverage_list;
+};
+
+static int compare_strings(const void * p1, const void * p2) {
+ return strcmp((const char *) p1, (const char *) p2) == 0;
+}
+
+Coverage * Coverage_new(void) {
+ Coverage * result = (Coverage *) xmalloc(sizeof(Coverage));
+ result->coverage_table = JS_NewHashTable(1024, JS_HashString, compare_strings, NULL, NULL, NULL);
+ if (result->coverage_table == NULL) {
+ fatal("cannot create hash table");
+ }
+ result->coverage_list = NULL;
+ return result;
+}
+
+void Coverage_delete(Coverage * coverage) {
+ JS_HashTableDestroy(coverage->coverage_table);
+ struct FileCoverageList * p = coverage->coverage_list;
+ while (p != NULL) {
+ free(p->file_coverage->coverage_lines);
+ if (p->file_coverage->source_lines != NULL) {
+ for (uint32 i = 0; i < p->file_coverage->num_source_lines; i++) {
+ free(p->file_coverage->source_lines[i]);
+ }
+ free(p->file_coverage->source_lines);
+ }
+ free(p->file_coverage->id);
+ free(p->file_coverage);
+ struct FileCoverageList * q = p;
+ p = p->next;
+ free(q);
+ }
+ free(coverage);
+}
+
+struct EnumeratorArg {
+ CoverageForeachFunction f;
+ void * p;
+};
+
+static intN enumerator(JSHashEntry * entry, intN i, void * arg) {
+ struct EnumeratorArg * enumerator_arg = (struct EnumeratorArg *) arg;
+ enumerator_arg->f((FileCoverage *) entry->value, i, enumerator_arg->p);
+ return 0;
+}
+
+void Coverage_foreach_file(Coverage * coverage, CoverageForeachFunction f, void * p) {
+ struct EnumeratorArg enumerator_arg;
+ enumerator_arg.f = f;
+ enumerator_arg.p = p;
+ JS_HashTableEnumerateEntries(coverage->coverage_table, enumerator, &enumerator_arg);
+}
+
+int jscoverage_parse_json(Coverage * coverage, const uint8_t * json, size_t length) {
+ int result = 0;
+
+ jschar * base = js_InflateString(context, (char *) json, &length);
+ if (base == NULL) {
+ fatal("out of memory");
+ }
+
+ jschar * parenthesized_json = xnew(jschar, addst(length, 2));
+ parenthesized_json[0] = '(';
+ memcpy(parenthesized_json + 1, base, mulst(length, sizeof(jschar)));
+ parenthesized_json[length + 1] = ')';
+
+ JS_free(context, base);
+
+ JSParseContext parse_context;
+ if (! js_InitParseContext(context, &parse_context, NULL, NULL, parenthesized_json, length + 2, NULL, NULL, 1)) {
+ free(parenthesized_json);
+ return -1;
+ }
+ JSParseNode * root = js_ParseScript(context, global, &parse_context);
+ free(parenthesized_json);
+
+ JSParseNode * semi = NULL;
+ JSParseNode * object = NULL;
+
+ if (root == NULL) {
+ result = -1;
+ goto done;
+ }
+
+ /* root node must be TOK_LC */
+ if (root->pn_type != TOK_LC) {
+ result = -1;
+ goto done;
+ }
+ semi = root->pn_u.list.head;
+
+ /* the list must be TOK_SEMI and it must contain only one element */
+ if (semi->pn_type != TOK_SEMI || semi->pn_next != NULL) {
+ result = -1;
+ goto done;
+ }
+ object = semi->pn_kid;
+
+ /* this must be an object literal */
+ if (object->pn_type != TOK_RC) {
+ result = -1;
+ goto done;
+ }
+
+ for (JSParseNode * p = object->pn_head; p != NULL; p = p->pn_next) {
+ /* every element of this list must be TOK_COLON */
+ if (p->pn_type != TOK_COLON) {
+ result = -1;
+ goto done;
+ }
+
+ /* the key must be a string representing the file */
+ JSParseNode * key = p->pn_left;
+ if (key->pn_type != TOK_STRING || ! ATOM_IS_STRING(key->pn_atom)) {
+ result = -1;
+ goto done;
+ }
+ char * id_bytes = JS_GetStringBytes(ATOM_TO_STRING(key->pn_atom));
+
+ /* the value must be an object literal OR an array */
+ JSParseNode * value = p->pn_right;
+ if (! (value->pn_type == TOK_RC || value->pn_type == TOK_RB)) {
+ result = -1;
+ goto done;
+ }
+
+ JSParseNode * array = NULL;
+ JSParseNode * source = NULL;
+ if (value->pn_type == TOK_RB) {
+ /* an array */
+ array = value;
+ }
+ else if (value->pn_type == TOK_RC) {
+ /* an object literal */
+ if (value->pn_count != 2) {
+ result = -1;
+ goto done;
+ }
+ for (JSParseNode * element = value->pn_head; element != NULL; element = element->pn_next) {
+ if (element->pn_type != TOK_COLON) {
+ result = -1;
+ goto done;
+ }
+ JSParseNode * left = element->pn_left;
+ if (left->pn_type != TOK_STRING || ! ATOM_IS_STRING(left->pn_atom)) {
+ result = -1;
+ goto done;
+ }
+ const char * s = JS_GetStringBytes(ATOM_TO_STRING(left->pn_atom));
+ if (strcmp(s, "coverage") == 0) {
+ array = element->pn_right;
+ if (array->pn_type != TOK_RB) {
+ result = -1;
+ goto done;
+ }
+ }
+ else if (strcmp(s, "source") == 0) {
+ source = element->pn_right;
+ if (source->pn_type != TOK_RB) {
+ result = -1;
+ goto done;
+ }
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+ }
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+
+ if (array == NULL) {
+ result = -1;
+ goto done;
+ }
+
+ /* look up the file in the coverage table */
+ FileCoverage * file_coverage = (FileCoverage *) JS_HashTableLookup(coverage->coverage_table, id_bytes);
+ if (file_coverage == NULL) {
+ /* not there: create a new one */
+ char * id = xstrdup(id_bytes);
+ file_coverage = (FileCoverage *) xmalloc(sizeof(FileCoverage));
+ file_coverage->id = id;
+ file_coverage->num_coverage_lines = array->pn_count;
+ file_coverage->coverage_lines = xnew(int, array->pn_count);
+ file_coverage->source_lines = NULL;
+
+ /* set coverage for all lines */
+ uint32 i = 0;
+ for (JSParseNode * element = array->pn_head; element != NULL; element = element->pn_next, i++) {
+ if (element->pn_type == TOK_NUMBER) {
+ file_coverage->coverage_lines[i] = (int) element->pn_dval;
+ }
+ else if (element->pn_type == TOK_PRIMARY && element->pn_op == JSOP_NULL) {
+ file_coverage->coverage_lines[i] = -1;
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+ }
+ assert(i == array->pn_count);
+
+ /* add to the hash table */
+ JS_HashTableAdd(coverage->coverage_table, id, file_coverage);
+ struct FileCoverageList * coverage_list = (FileCoverageList *) xmalloc(sizeof(struct FileCoverageList));
+ coverage_list->file_coverage = file_coverage;
+ coverage_list->next = coverage->coverage_list;
+ coverage->coverage_list = coverage_list;
+ }
+ else {
+ /* sanity check */
+ assert(strcmp(file_coverage->id, id_bytes) == 0);
+ if (file_coverage->num_coverage_lines != array->pn_count) {
+ result = -2;
+ goto done;
+ }
+
+ /* merge the coverage */
+ uint32 i = 0;
+ for (JSParseNode * element = array->pn_head; element != NULL; element = element->pn_next, i++) {
+ if (element->pn_type == TOK_NUMBER) {
+ if (file_coverage->coverage_lines[i] == -1) {
+ result = -2;
+ goto done;
+ }
+ file_coverage->coverage_lines[i] += (int) element->pn_dval;
+ }
+ else if (element->pn_type == TOK_PRIMARY && element->pn_op == JSOP_NULL) {
+ if (file_coverage->coverage_lines[i] != -1) {
+ result = -2;
+ goto done;
+ }
+ }
+ else {
+ result = -1;
+ goto done;
+ }
+ }
+ assert(i == array->pn_count);
+ }
+
+ /* if this JSON file has source, use it */
+ if (file_coverage->source_lines == NULL && source != NULL) {
+ file_coverage->num_source_lines = source->pn_count;
+ file_coverage->source_lines = xnew(char *, source->pn_count);
+ uint32 i = 0;
+ for (JSParseNode * element = source->pn_head; element != NULL; element = element->pn_next, i++) {
+ if (element->pn_type != TOK_STRING) {
+ result = -1;
+ goto done;
+ }
+ file_coverage->source_lines[i] = xstrdup(JS_GetStringBytes(ATOM_TO_STRING(element->pn_atom)));
+ }
+ assert(i == source->pn_count);
+ }
+ }
+
+done:
+ js_FinishParseContext(context, &parse_context);
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument-js.h b/tools/node_modules/expresso/deps/jscoverage/instrument-js.h
new file mode 100644
index 0000000..07c60ab
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument-js.h
@@ -0,0 +1,81 @@
+/*
+ instrument-js.h - JavaScript instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef INSTRUMENT_JS_H_
+#define INSTRUMENT_JS_H_
+
+/* ISO C99 specifies that C++ code must define this to get UINT16_MAX etc. */
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include "stream.h"
+#include "util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum FileType {
+ FILE_TYPE_JS,
+ FILE_TYPE_HTML,
+ FILE_TYPE_OTHER
+};
+
+extern bool jscoverage_mozilla;
+
+void jscoverage_set_js_version(const char * version);
+
+void jscoverage_init(void);
+
+void jscoverage_cleanup(void);
+
+void jscoverage_instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output);
+
+void jscoverage_copy_resources(const char * destination_directory);
+
+typedef struct Coverage Coverage;
+
+typedef struct FileCoverage {
+ char * id;
+
+ int * coverage_lines;
+ char ** source_lines;
+
+ /* SpiderMonkey uses uint32 for array lengths */
+ uint32_t num_coverage_lines;
+ uint32_t num_source_lines;
+} FileCoverage;
+
+Coverage * Coverage_new(void);
+
+void Coverage_delete(Coverage * coverage);
+
+typedef void (*CoverageForeachFunction) (const FileCoverage * file_coverage, int i, void * p);
+
+void Coverage_foreach_file(Coverage * coverage, CoverageForeachFunction f, void * p);
+
+int jscoverage_parse_json(Coverage * coverage, const uint8_t * data, size_t length) __attribute__((warn_unused_result));
+
+void jscoverage_write_source(const char * id, const uint16_t * characters, size_t num_characters, Stream * output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INSTRUMENT_JS_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument.c b/tools/node_modules/expresso/deps/jscoverage/instrument.c
new file mode 100644
index 0000000..d19b690
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument.c
@@ -0,0 +1,226 @@
+/*
+ instrument.c - file and directory instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "instrument.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "encoding.h"
+#include "global.h"
+#include "instrument-js.h"
+#include "resource-manager.h"
+#include "util.h"
+
+static int g_verbose = 0;
+
+static int string_ends_with(const char * s, const char * suffix) {
+ size_t length = strlen(s);
+ size_t suffix_length = strlen(suffix);
+ if (length < suffix_length) {
+ return 0;
+ }
+ return strcasecmp(s + (length - suffix_length), suffix) == 0;
+}
+
+static enum FileType get_file_type(const char * file) {
+ if (string_ends_with(file, ".js")) {
+ return FILE_TYPE_JS;
+ }
+ else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
+ return FILE_TYPE_HTML;
+ }
+ else {
+ return FILE_TYPE_OTHER;
+ }
+}
+
+static void check_same_file(const char * file1, const char * file2) {
+ if (is_same_file(file1, file2)) {
+ fatal("source and destination are the same");
+ }
+}
+
+static void check_contains_file(const char * file1, const char * file2) {
+ if (contains_file(file1, file2)) {
+ fatal("%s contains %s", file1, file2);
+ }
+}
+
+static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
+ if (g_verbose) {
+ printf("Instrumenting file %s\n", id);
+ }
+
+ /* check if they are the same */
+ char * canonical_source_file = make_canonical_path(source_file);
+ char * canonical_destination_file = make_canonical_path(destination_file);
+ check_same_file(canonical_source_file, canonical_destination_file);
+ free(canonical_source_file);
+ free(canonical_destination_file);
+
+ if (instrumenting) {
+ enum FileType file_type = get_file_type(source_file);
+ switch (file_type) {
+ case FILE_TYPE_OTHER:
+ case FILE_TYPE_HTML:
+ copy_file(source_file, destination_file);
+ break;
+ case FILE_TYPE_JS:
+ {
+ FILE * input = xfopen(source_file, "rb");
+ FILE * output = xfopen(destination_file, "wb");
+
+ Stream * input_stream = Stream_new(0);
+ Stream * output_stream = Stream_new(0);
+
+ Stream_write_file_contents(input_stream, input);
+
+ size_t num_characters = input_stream->length;
+ uint16_t * characters = NULL;
+ int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ fatal("encoding %s not supported", jscoverage_encoding);
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ fatal("error decoding %s in file %s", jscoverage_encoding, id);
+ }
+ jscoverage_instrument_js(id, characters, num_characters, output_stream);
+ free(characters);
+
+ if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
+ fatal("cannot write to file: %s", destination_file);
+ }
+
+ Stream_delete(input_stream);
+ Stream_delete(output_stream);
+
+ fclose(input);
+ fclose(output);
+ }
+ break;
+ }
+ }
+ else {
+ copy_file(source_file, destination_file);
+ }
+}
+
+void jscoverage_instrument(const char * source,
+ const char * destination,
+ int verbose,
+ char ** exclude,
+ int num_exclude,
+ char ** no_instrument,
+ int num_no_instrument)
+{
+ assert(source != NULL);
+ assert(destination != NULL);
+
+ g_verbose = verbose;
+
+ /* check if they are the same */
+ check_same_file(source, destination);
+
+ /* check if source directory is an ancestor of destination directory */
+ check_contains_file(source, destination);
+
+ /* check that the source exists and is a directory */
+ struct stat buf;
+ xstat(source, &buf);
+ if (! S_ISDIR(buf.st_mode)) {
+ fatal("not a directory: %s", source);
+ }
+
+ /* if the destination directory exists, check that it is a jscoverage directory */
+ if (stat(destination, &buf) == 0) {
+ /* it exists */
+ if (! S_ISDIR(buf.st_mode)) {
+ fatal("not a directory: %s", destination);
+ }
+ if (! directory_is_empty(destination)) {
+ char * expected_file = NULL;
+ if (jscoverage_mozilla) {
+ char * modules_directory = make_path(destination, "modules");
+ expected_file = make_path(modules_directory, "jscoverage.jsm");
+ free(modules_directory);
+ }
+ else {
+ expected_file = make_path(destination, "jscoverage.html");
+ }
+ if (stat(expected_file, &buf) == -1) {
+ fatal("refusing to overwrite directory: %s", destination);
+ }
+ free(expected_file);
+ }
+ }
+ else if (errno == ENOENT) {
+ xmkdir(destination);
+ }
+ else {
+ fatal("cannot stat directory: %s", destination);
+ }
+
+ /* finally: copy the directory */
+ struct DirListEntry * list = make_recursive_dir_list(source);
+ for (struct DirListEntry * p = list; p != NULL; p = p->next) {
+ char * s = make_path(source, p->name);
+ char * d = make_path(destination, p->name);
+
+ /* check if it's on the exclude list */
+ for (int i = 0; i < num_exclude; i++) {
+ char * x = make_path(source, exclude[i]);
+ if (is_same_file(x, s) || contains_file(x, s)) {
+ free(x);
+ goto cleanup;
+ }
+ free(x);
+ }
+
+ char * dd = make_dirname(d);
+ mkdirs(dd);
+ free(dd);
+
+ int instrument_this = 1;
+
+ /* check if it's on the no-instrument list */
+ for (int i = 0; i < num_no_instrument; i++) {
+ char * ni = make_path(source, no_instrument[i]);
+ if (is_same_file(ni, s) || contains_file(ni, s)) {
+ instrument_this = 0;
+ }
+ free(ni);
+ }
+
+ instrument_file(s, d, p->name, instrument_this);
+
+ cleanup:
+ free(s);
+ free(d);
+ }
+
+ free_dir_list(list);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/instrument.h b/tools/node_modules/expresso/deps/jscoverage/instrument.h
new file mode 100644
index 0000000..a8720b0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/instrument.h
@@ -0,0 +1,31 @@
+/*
+ instrument.h - file and directory instrumentation routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef INSTRUMENT_H_
+#define INSTRUMENT_H_
+
+void jscoverage_instrument(const char * source,
+ const char * destination,
+ int verbose,
+ char ** exclude,
+ int num_exclude,
+ char ** no_instrument,
+ int num_no_instrument);
+
+#endif /* INSTRUMENT_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile b/tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile
new file mode 100644
index 0000000..2548cf6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/GNUmakefile
@@ -0,0 +1,15 @@
+overrides = DISABLE_JIT=1 OBJROOT=obj BUILD_OPT=1
+uname = $(shell uname)
+ifeq "$(findstring CYGWIN,$(uname))" "CYGWIN"
+overrides += OS_CONFIG=Cygwin OS_ARCH=Cygwin
+else
+ifeq "$(findstring MINGW,$(uname))" "MINGW"
+overrides += OS_CONFIG=MSYS OS_ARCH=MSYS
+endif
+endif
+
+all:
+ $(MAKE) -f Makefile.ref $(overrides)
+
+clean:
+ $(MAKE) -f Makefile.ref $(overrides) clean
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref b/tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref
new file mode 100644
index 0000000..97803e9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/Makefile.ref
@@ -0,0 +1,483 @@
+# -*- Mode: makefile -*-
+# vim: ft=make
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Michael Ang <mang@subcarrier.org>
+# Kevin Buhr <buhr@stat.wisc.edu>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# JSRef GNUmake makefile.
+#
+# Note: dependency rules are missing for some files (some
+# .h, all .msg, etc.) Re-make clean if in doubt.
+#
+
+
+DEPTH = .
+
+include config.mk
+
+#NS_USE_NATIVE = 1
+
+ifndef NANOJIT_ARCH
+$(warning NANOJIT_ARCH not defined in config/$(OS_CONFIG).mk, JIT disabled)
+else
+ifdef DISABLE_JIT
+$(warning disabling JIT per build specification)
+else
+ENABLE_JIT=1
+endif
+endif
+
+ifdef ENABLE_JIT
+DEFINES += -DJS_TRACER
+DEFINES += -DFEATURE_NANOJIT
+INCLUDES += -Inanojit
+endif
+
+#ifndef BUILD_OPT
+#DEFINES += -Ivprof
+#endif
+
+ifdef NARCISSUS
+DEFINES += -DNARCISSUS
+endif
+
+# Look in OBJDIR to find jsautocfg.h, jsautokw.h, and js-config.h
+INCLUDES += -I. -I$(OBJDIR)
+
+ifdef JS_THREADSAFE
+DEFINES += -DJS_THREADSAFE
+INCLUDES += -I$(DIST)/include/nspr
+ifdef USE_MSVC
+OTHER_LIBS += $(DIST)/lib/libnspr$(NSPR_LIBSUFFIX).lib
+else
+OTHER_LIBS += -L$(DIST)/lib -lnspr$(NSPR_LIBSUFFIX)
+endif
+endif
+
+ifdef JS_NO_THIN_LOCKS
+DEFINES += -DJS_USE_ONLY_NSPR_LOCKS
+endif
+
+ifdef JS_HAS_FILE_OBJECT
+DEFINES += -DJS_HAS_FILE_OBJECT
+endif
+
+ifdef JS_GC_ZEAL
+DEFINES += -DJS_GC_ZEAL
+endif
+
+#
+# XCFLAGS may be set in the environment or on the gmake command line
+#
+#CFLAGS += -DDEBUG -DDEBUG_brendan -DJS_ARENAMETER -DJS_HASHMETER -DJS_DUMP_PROPTREE_STATS -DJS_DUMP_SCOPE_METERS -DJS_SCOPE_DEPTH_METER -DJS_BASIC_STATS
+CFLAGS += $(OS_CFLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+
+LDFLAGS = $(XLDFLAGS)
+LDFLAGS += $(OS_LDFLAGS)
+
+ifdef MOZ_SHARK
+DEFINES += -DMOZ_SHARK
+CFLAGS += -F/System/Library/PrivateFrameworks
+LDFLAGS += -F/System/Library/PrivateFrameworks -framework CHUD
+endif
+ifdef MOZ_CALLGRIND
+DEFINES += -DMOZ_CALLGRIND
+endif
+ifdef MOZ_VTUNE
+DEFINES += -DMOZ_VTUNE
+CXXFLAGS += -IC:/Program\ Files/Intel/VTune/Analyzer/Include
+OTHER_LIBS += C:/Program\ Files/Intel/VTune/Analyzer/Lib/VtuneApi.lib
+endif
+
+ifndef NO_LIBM
+LDFLAGS += -lm
+endif
+
+# Prevent floating point errors caused by VC++ optimizations
+ifeq ($(OS_ARCH),WINNT)
+_MSC_VER = $(shell $(CXX) 2>&1 | sed -n 's/.*Compiler Version \([0-9]*\)\.\([0-9]*\).*/\1\2/p')
+ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
+CFLAGS += -Op
+else
+CFLAGS += -fp:precise
+endif
+endif # WINNT
+
+#
+# Server-related changes :
+#
+ifdef NES40
+DEFINES += -DNES40
+endif
+
+#
+# Line editing support.
+# Define JS_READLINE or JS_EDITLINE to enable line editing in the
+# js command-line interpreter.
+#
+ifdef JS_READLINE
+# For those platforms with the readline library installed.
+DEFINES += -DEDITLINE
+PROG_LIBS += -lreadline -ltermcap
+else
+ifdef JS_EDITLINE
+# Use the editline library, built locally.
+PREDIRS += editline
+DEFINES += -DEDITLINE
+PROG_LIBS += $(OBJDIR)/editline/libedit.a
+endif
+endif
+
+# For purify
+PURE_CFLAGS = -DXP_UNIX $(OPTIMIZER) $(PURE_OS_CFLAGS) $(DEFINES) \
+ $(INCLUDES) $(XCFLAGS)
+
+#
+# JS file lists
+#
+JS_HFILES = \
+ jsarray.h \
+ jsatom.h \
+ jsbool.h \
+ jscntxt.h \
+ jsdate.h \
+ jsemit.h \
+ jsexn.h \
+ jsfun.h \
+ jsgc.h \
+ jsinterp.h \
+ jsiter.h \
+ jslibmath.h \
+ jslock.h \
+ jsmath.h \
+ jsnum.h \
+ jsobj.h \
+ json.h \
+ jsopcode.h \
+ jsparse.h \
+ jsarena.h \
+ jsclist.h \
+ jsdhash.h \
+ jsdtoa.h \
+ jshash.h \
+ jslong.h \
+ jstypes.h \
+ jsprvtd.h \
+ jspubtd.h \
+ jsregexp.h \
+ jsscan.h \
+ jsscope.h \
+ jsscript.h \
+ jsstr.h \
+ jsversion.h \
+ jsxdrapi.h \
+ jsxml.h \
+ $(NULL)
+
+ifdef ENABLE_JIT
+JS_HFILES += \
+ jstracer.h \
+ nanojit/Assembler.h \
+ nanojit/LIR.h \
+ nanojit/Native$(NANOJIT_ARCH).h \
+ nanojit/avmplus.h \
+ nanojit/vm_fops.h \
+ nanojit/Fragmento.h \
+ nanojit/Native.h \
+ nanojit/RegAlloc.h \
+ nanojit/nanojit.h \
+ nanojit/TraceTreeDrawer.h \
+ $(NULL)
+endif
+
+ifndef BUILD_OPT
+#JS_HFILES += \
+# vprof/vprof.h \
+# $(NULL)
+endif
+
+API_HFILES = \
+ jsapi.h \
+ jsdbgapi.h \
+ $(NULL)
+
+OTHER_HFILES = \
+ jsbit.h \
+ jscompat.h \
+ jscpucfg.h \
+ jsotypes.h \
+ jsstddef.h \
+ prmjtime.h \
+ resource.h \
+ jsopcode.tbl \
+ jsproto.tbl \
+ js.msg \
+ jsshell.msg \
+ jskeyword.tbl \
+ $(NULL)
+
+ifdef ENABLE_JIT
+OTHER_HFILES += builtins.tbl
+endif
+
+ifndef PREBUILT_CPUCFG
+OTHER_HFILES += $(OBJDIR)/jsautocfg.h
+endif
+OTHER_HFILES += $(OBJDIR)/jsautokw.h $(OBJDIR)/js-config.h
+
+HFILES = $(JS_HFILES) $(API_HFILES) $(OTHER_HFILES)
+
+JS_CPPFILES = \
+ jsapi.cpp \
+ jsarena.cpp \
+ jsarray.cpp \
+ jsatom.cpp \
+ jsbool.cpp \
+ jscntxt.cpp \
+ jsdate.cpp \
+ jsdbgapi.cpp \
+ jsdhash.cpp \
+ jsdtoa.cpp \
+ jsemit.cpp \
+ jsexn.cpp \
+ jsfun.cpp \
+ jsgc.cpp \
+ jshash.cpp \
+ jsinterp.cpp \
+ jsinvoke.cpp \
+ jsiter.cpp \
+ jslock.cpp \
+ jslog2.cpp \
+ jslong.cpp \
+ jsmath.cpp \
+ jsnum.cpp \
+ jsobj.cpp \
+ json.cpp \
+ jsopcode.cpp \
+ jsparse.cpp \
+ jsprf.cpp \
+ jsregexp.cpp \
+ jsscan.cpp \
+ jsscope.cpp \
+ jsscript.cpp \
+ jsstr.cpp \
+ jsutil.cpp \
+ jsxdrapi.cpp \
+ jsxml.cpp \
+ prmjtime.cpp \
+ $(NULL)
+
+ifdef ENABLE_JIT
+JS_CPPFILES += \
+ jsbuiltins.cpp \
+ jstracer.cpp \
+ nanojit/Assembler.cpp \
+ nanojit/Fragmento.cpp \
+ nanojit/LIR.cpp \
+ nanojit/Native$(NANOJIT_ARCH).cpp \
+ nanojit/RegAlloc.cpp \
+ nanojit/avmplus.cpp \
+ $(NULL)
+
+ifdef DEBUG
+JS_CPPFILES += nanojit/TraceTreeDrawer.cpp
+endif
+endif
+
+ifndef BUILD_OPT
+#JS_CPPFILES += \
+# vprof/vprof.cpp \
+# $(NULL)
+endif
+
+ifdef JS_LIVECONNECT
+DIRS += liveconnect
+endif
+
+ifdef JS_HAS_FILE_OBJECT
+JS_CPPFILES += jsfile.cpp
+JS_HFILES += jsfile.h
+endif
+
+LIB_CPPFILES = $(JS_CPPFILES)
+LIB_ASFILES := $(wildcard *_$(OS_ARCH).s)
+PROG_CPPFILES = js.cpp
+
+ifdef USE_MSVC
+LIBRARY = $(OBJDIR)/js32.lib
+SHARED_LIBRARY = $(OBJDIR)/js32.dll
+PROGRAM = $(OBJDIR)/js.exe
+else
+LIBRARY = $(OBJDIR)/libjs.a
+SHARED_LIBRARY = $(OBJDIR)/libjs.$(SO_SUFFIX)
+PROGRAM = $(OBJDIR)/js
+endif
+
+include rules.mk
+
+MOZ_DEPTH = ../..
+include jsconfig.mk
+
+nsinstall-target:
+ cd ../../config; $(MAKE) OBJDIR=$(OBJDIR) OBJDIR_NAME=$(OBJDIR)
+
+#
+# Automatic header generation
+#
+
+AUTO_HEADERS = \
+ $(OBJDIR)/jsautokw.h \
+ $(OBJDIR)/jsautooplen.h \
+ $(NULL)
+
+$(OBJDIR)/jsautokw.h: jskeyword.tbl
+
+$(OBJDIR)/jsautooplen.h: jsopcode.tbl
+
+GARBAGE += $(AUTO_HEADERS)
+GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen$(HOST_BIN_SUFFIX))
+
+ifdef USE_MSVC
+
+GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.obj)
+
+$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(OPTIMIZER) $<
+ link.exe -out:"$(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX)" $(EXE_LINK_FLAGS) $(OBJDIR)/js$*gen.obj
+ $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
+else
+
+GARBAGE += $(AUTO_HEADERS:$(OBJDIR)/jsauto%.h=$(OBJDIR)/js%gen.d)
+$(AUTO_HEADERS): $(OBJDIR)/jsauto%.h: js%gen.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $(CFLAGS) $(OPTIMIZER) $(LDFLAGS) $<
+ $(OBJDIR)/js$*gen$(HOST_BIN_SUFFIX) $@
+
+endif
+
+# force creation of autoheaders before compiling any source that may use them
+$(LIB_OBJS) : $(AUTO_HEADERS)
+
+#
+# An installed header file describing configuration options that affect
+# the API.
+#
+
+# Avoid rebuilding unless js-config.h's contents actually change. The
+# timestamp on js-config.h.stamp corresponds to the last time we
+# checked that js-config.h was up to date. If the stamp changes but
+# js-config.h does not, then make concludes that targets depending on
+# js-config.h don't need to be rebuilt. The dummy '@true' rule here
+# keeps make from concluding that js-config.h never changes.
+$(OBJDIR)/js-config.h: $(OBJDIR)/js-config.h.stamp
+ @true
+
+js-config-switch=$(if $(value $($1)),-e 's/\#undef $1/\#define $1/')
+$(OBJDIR)/js-config.h.stamp: js-config.h.in Makefile.ref
+ sed < $< > $(@:.stamp=.tmp) \
+ $(call js-config-switch,JS_THREADSAFE) \
+ $(call js-config-switch,JS_GC_ZEAL) \
+ -e :dummy
+ if ! [ -f $(@:.stamp=) ] || ! cmp $(@:.stamp=.tmp) $(@:.stamp=); then \
+ mv $(@:.stamp=.tmp) $(@:.stamp=); \
+ fi
+ touch $@
+
+GARBAGE += $(OBJDIR)/js-config.h $(OBJDIR)/js-config.h.stamp
+
+# Force creation of js-config.h before compiling any source that may use it.
+$(LIB_OBJS) : $(OBJDIR)/js-config.h
+
+#
+# JS shell executable
+#
+
+ifdef USE_MSVC
+$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
+ link.exe -out:"$@" $(EXE_LINK_FLAGS) $^
+else
+$(PROGRAM): $(PROG_OBJS) $(LIBRARY)
+ $(CXX) -o $@ $(CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) $(OTHER_LIBS) \
+ $(PROG_LIBS)
+endif
+
+$(PROGRAM).pure: $(PROG_OBJS) $(LIBRARY)
+ purify $(PUREFLAGS) \
+ $(CXX) -o $@ $(PURE_OS_CFLAGS) $(PROG_OBJS) $(LIBRARY) $(LDFLAGS) \
+ $(OTHER_LIBS) $(PROG_LIBS)
+
+ifndef PREBUILT_CPUCFG
+$(filter-out jscpucfg.h $(OBJDIR)/jsautocfg.h, $(HFILES)) $(CPPFILES): $(OBJDIR)/jsautocfg.h
+
+$(OBJDIR)/jsautocfg.h: $(OBJDIR)/jscpucfg
+ rm -f $@
+ $(OBJDIR)/jscpucfg > $@
+
+$(OBJDIR)/jscpucfg: $(OBJDIR)/jscpucfg.o
+ $(CXX) $(OS_LDFLAGS) -o $@ $(OBJDIR)/jscpucfg.o
+
+GARBAGE += $(OBJDIR)/jsautocfg.h $(OBJDIR)/jscpucfg \
+ $(OBJDIR)/jscpucfg.o $(OBJDIR)/jscpucfg.d
+endif
+
+# Automatic make dependencies files
+DEPENDENCIES = $(CPPFILES:%.cpp=$(OBJDIR)/%.d)
+
+#
+# Hardwire dependencies for some files
+#
+ifdef USE_MSVC
+OBJ=obj
+else
+OBJ=o
+endif
+
+$(OBJDIR)/jsinvoke.$(OBJ): jsinterp.h jsinterp.cpp
+$(OBJDIR)/jsinvoke.obj : jsinterp.h jsinterp.cpp
+
+-include $(DEPENDENCIES)
+
+TARNAME = jsref.tar
+TARFILES = files `cat files`
+
+SUFFIXES: .i
+%.i: %.cpp
+ $(CXX) -C -E $(CFLAGS) $< > $*.i
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/README.html b/tools/node_modules/expresso/deps/jscoverage/js/README.html
new file mode 100644
index 0000000..6eb1567
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/README.html
@@ -0,0 +1,54 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (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.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is Mozilla Communicator client code, released
+ - March 31, 1998.
+ -
+ - The Initial Developer of the Original Code is
+ - Netscape Communications Corporation.
+ - Portions created by the Initial Developer are Copyright (C) 1998-1999
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s):
+ -
+ - Alternatively, the contents of this file may be used under the terms of
+ - either of the GNU General Public License Version 2 or later (the "GPL"),
+ - or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ - in which case the provisions of the GPL or the LGPL are applicable instead
+ - of those above. If you wish to allow use of your version of this file only
+ - under the terms of either the GPL or the LGPL, and not to allow others to
+ - use your version of this file under the terms of the MPL, indicate your
+ - decision by deleting the provisions above and replace them with the notice
+ - and other provisions required by the GPL or the LGPL. If you do not delete
+ - the provisions above, a recipient may use your version of this file under
+ - the terms of any one of the MPL, the GPL or the LGPL.
+ -
+ - ***** END LICENSE BLOCK ***** -->
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta http-equiv="Refresh"
+ content="0;URL=http://developer.mozilla.org/en/docs/SpiderMonkey">
+ <title>SpiderMonkey README</title>
+</head>
+<body>
+
+<h1>SpiderMonkey README</h1>
+
+<p>See the
+<a href="http://developer.mozilla.org/en/docs/SpiderMonkey">SpiderMonkey
+pages</a> on the Mozilla Developer Center</a>.
+
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp b/tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp
new file mode 100644
index 0000000..fc162d9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/SpiderMonkey.rsp
@@ -0,0 +1,11 @@
+mozilla/js/src/*
+mozilla/js/src/config/*
+mozilla/js/src/liveconnect/*
+mozilla/js/src/liveconnect/_jni/*
+mozilla/js/src/liveconnect/classes/*
+mozilla/js/src/liveconnect/classes/netscape/*
+mozilla/js/src/liveconnect/classes/netscape/javascript/*
+mozilla/js/src/liveconnect/config/*
+mozilla/js/src/liveconnect/macbuild/*
+mozilla/js/src/liveconnect/macbuild/JavaSession/*
+mozilla/js/src/macbuild/*
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/aclocal.m4 b/tools/node_modules/expresso/deps/jscoverage/js/aclocal.m4
new file mode 100644
index 0000000..538065c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/aclocal.m4
@@ -0,0 +1,9 @@
+dnl
+dnl Local autoconf macros used with mozilla
+dnl The contents of this file are under the Public Domain.
+dnl
+
+builtin(include, build/autoconf/pkg.m4)dnl
+builtin(include, build/autoconf/nspr.m4)dnl
+builtin(include, build/autoconf/altoptions.m4)dnl
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/bench.sh b/tools/node_modules/expresso/deps/jscoverage/js/bench.sh
new file mode 100755
index 0000000..8b7fe75
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/bench.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+X="var d = Date.now();";
+for i in t/*.js; do X="$X load(\"$i\");"; done
+X="$X print(Date.now() - d);"
+echo $X | (./Darwin_OPT.OBJ/js -j || ./Linux_All_OPT.OBJ/js -j)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl
new file mode 100644
index 0000000..973dd86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/acoutput-fast.pl
@@ -0,0 +1,202 @@
+#! /usr/bin/env perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# acoutput-fast.pl - Quickly create makefiles that are in a common format.
+#
+# Most of the makefiles in mozilla only refer to two configure variables:
+# @srcdir@
+# @top_srcdir@
+# However, configure does not know any better and it runs sed on each file
+# with over 150 replacement rules (slow as molasses).
+#
+# This script takes a list of makefiles as input. For example,
+#
+# echo $MAKEFILES | acoutput-fast.pl
+#
+# The script creates each Makefile that only references @srcdir@ and
+# @top_srcdir@. For other files, it lists them in a shell command that is
+# printed to stdout:
+#
+# CONFIG_FILES="unhandled_files..."; export CONFIG_FILES
+#
+# This command can be used to have config.status create the unhandled
+# files. For example,
+#
+# eval "echo $MAKEFILES | acoutput-fast.pl"
+# AC_OUTPUT($MAKEFILES)
+#
+# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+#use File::Basename;
+sub dirname {
+ my $dir = $_[0];
+ return '.' if not $dir =~ m%/%;
+ $dir =~ s%/[^/][^/]*$%%;
+ return $dir;
+}
+
+# Create one directory. Assumes it doesn't already exist.
+# Will create parent(s) if needed.
+sub create_directory {
+ my $dir = $_[0];
+ my $parent = dirname($dir);
+ create_directory($parent) if not -d $parent;
+ mkdir "$dir",0777;
+}
+
+# Create all the directories at once.
+# This can be much faster than calling mkdir() for each one.
+sub create_directories {
+ my @makefiles = @_;
+ my @dirs = ();
+ my $ac_file;
+ foreach $ac_file (@makefiles) {
+ push @dirs, dirname($ac_file);
+ }
+ # Call mkdir with the directories sorted by subdir count (how many /'s)
+ if (@dirs) {
+ foreach $dir (@dirs) {
+ if (not -d $dir) {
+ print STDERR "Creating directory $dir\n";
+ create_directory($dir);
+ }
+ }
+ }
+}
+
+while($arg = shift) {
+ if ($arg =~ /^--srcdir=/) {
+ $ac_given_srcdir = (split /=/, $arg)[1];
+ }
+ if ($arg =~ /^--cygwin-srcdir/) {
+ $ac_cygwin_srcdir = (split /=/, $arg)[1];
+ }
+}
+
+if (!$ac_given_srcdir) {
+ $ac_given_srcdir = $0;
+ $ac_given_srcdir =~ s|/?build/autoconf/.*$||;
+ $ac_given_srcdir = '.' if $ac_given_srcdir eq '';
+}
+
+if (!$ac_cygwin_srcdir) {
+ $ac_cygwin_srcdir = $ac_given_srcdir;
+}
+
+# Read list of makefiles from the stdin or,
+# from files listed on the command-line.
+#
+@makefiles=();
+push @makefiles, split while (<STDIN>);
+
+# Create all the directories at once.
+# This can be much faster than calling mkdir() for each one.
+create_directories(@makefiles);
+
+# Output the makefiles.
+#
+@unhandled=();
+foreach $ac_file (@makefiles) {
+ if (not $ac_file =~ /Makefile$/ or $ac_file =~ /:/) {
+ push @unhandled, $ac_file;
+ next;
+ }
+ $ac_file_in = "$ac_given_srcdir/$ac_file.in";
+ $ac_dir = dirname($ac_file);
+ if ($ac_dir eq '.') {
+ $ac_dir_suffix = '';
+ $ac_dots = '';
+ } else {
+ $ac_dir_suffix = "/$ac_dir";
+ $ac_dir_suffix =~ s%^/\./%/%;
+ $ac_dots = $ac_dir_suffix;
+ $ac_dots =~ s%/[^/]*%../%g;
+ }
+ if ($ac_given_srcdir eq '.') {
+ $srcdir = '.';
+ if ($ac_dots eq '') {
+ $top_srcdir = '.'
+ } else {
+ $top_srcdir = $ac_dots;
+ $top_srcdir =~ s%/$%%;
+ }
+ } elsif ($ac_cygwin_srcdir =~ m%^/% or $ac_cygwin_srcdir =~ m%^.:/%) {
+ $srcdir = "$ac_cygwin_srcdir$ac_dir_suffix";
+ $top_srcdir = "$ac_cygwin_srcdir";
+ } else {
+ $srcdir = "$ac_dots$ac_cygwin_srcdir$ac_dir_suffix";
+ $top_srcdir = "$ac_dots$ac_cygwin_srcdir";
+ }
+
+ if (-e $ac_file) {
+ next if -M _ < -M $ac_file_in;
+ print STDERR "updating $ac_file\n";
+ } else {
+ print STDERR "creating $ac_file\n";
+ }
+
+ open (INFILE, "<$ac_file_in")
+ or ( warn "can't read $ac_file_in: No such file or directory\n" and next);
+ open (OUTFILE, ">$ac_file")
+ or ( warn "Unable to create $ac_file\n" and next);
+
+ while (<INFILE>) {
+ #if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
+ # warn "Two defines on a line:$ac_file:$.:$_";
+ # push @unhandled, $ac_file;
+ # last;
+ #}
+
+ s/\@srcdir\@/$srcdir/g;
+ s/\@top_srcdir\@/$top_srcdir/g;
+
+ if (/\@[_a-zA-Z]*\@/) {
+ warn "Unknown variable:$ac_file:$.:$_";
+ push @unhandled, $ac_file;
+ last;
+ }
+ print OUTFILE;
+ }
+ close INFILE;
+ close OUTFILE;
+}
+
+# Print the shell command to be evaluated by configure.
+#
+print "CONFIG_FILES=\"".join(' ', @unhandled)."\"; export CONFIG_FILES\n";
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4 b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4
new file mode 100644
index 0000000..f9db0a5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/altoptions.m4
@@ -0,0 +1,154 @@
+dnl ***** BEGIN LICENSE BLOCK *****
+dnl Version: MPL 1.1/GPL 2.0/LGPL 2.1
+dnl
+dnl The contents of this file are subject to the Mozilla Public License Version
+dnl 1.1 (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
+dnl http://www.mozilla.org/MPL/
+dnl
+dnl Software distributed under the License is distributed on an "AS IS" basis,
+dnl WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+dnl for the specific language governing rights and limitations under the
+dnl License.
+dnl
+dnl The Original Code is mozilla.org code.
+dnl
+dnl The Initial Developer of the Original Code is
+dnl Netscape Communications Corporation.
+dnl Portions created by the Initial Developer are Copyright (C) 1999
+dnl the Initial Developer. All Rights Reserved.
+dnl
+dnl Contributor(s):
+dnl
+dnl Alternatively, the contents of this file may be used under the terms of
+dnl either of the GNU General Public License Version 2 or later (the "GPL"),
+dnl or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+dnl in which case the provisions of the GPL or the LGPL are applicable instead
+dnl of those above. If you wish to allow use of your version of this file only
+dnl under the terms of either the GPL or the LGPL, and not to allow others to
+dnl use your version of this file under the terms of the MPL, indicate your
+dnl decision by deleting the provisions above and replace them with the notice
+dnl and other provisions required by the GPL or the LGPL. If you do not delete
+dnl the provisions above, a recipient may use your version of this file under
+dnl the terms of any one of the MPL, the GPL or the LGPL.
+dnl
+dnl ***** END LICENSE BLOCK *****
+
+dnl altoptions.m4 - An alternative way of specifying command-line options.
+dnl These macros are needed to support a menu-based configurator.
+dnl This file also includes the macro, AM_READ_MYCONFIG, for reading
+dnl the 'myconfig.m4' file.
+
+dnl Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+
+dnl MOZ_ARG_ENABLE_BOOL( NAME, HELP, IF-YES [, IF-NO [, ELSE]])
+dnl MOZ_ARG_DISABLE_BOOL( NAME, HELP, IF-NO [, IF-YES [, ELSE]])
+dnl MOZ_ARG_ENABLE_STRING( NAME, HELP, IF-SET [, ELSE])
+dnl MOZ_ARG_ENABLE_BOOL_OR_STRING( NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
+dnl MOZ_ARG_WITH_BOOL( NAME, HELP, IF-YES [, IF-NO [, ELSE])
+dnl MOZ_ARG_WITHOUT_BOOL( NAME, HELP, IF-NO [, IF-YES [, ELSE])
+dnl MOZ_ARG_WITH_STRING( NAME, HELP, IF-SET [, ELSE])
+dnl MOZ_ARG_HEADER(Comment)
+dnl MOZ_CHECK_PTHREADS( NAME, IF-YES [, ELSE ])
+dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
+
+
+dnl MOZ_TWO_STRING_TEST(NAME, VAL, STR1, IF-STR1, STR2, IF-STR2 [, ELSE])
+AC_DEFUN([MOZ_TWO_STRING_TEST],
+[if test "[$2]" = "[$3]"; then
+ ifelse([$4], , :, [$4])
+ elif test "[$2]" = "[$5]"; then
+ ifelse([$6], , :, [$6])
+ else
+ ifelse([$7], ,
+ [AC_MSG_ERROR([Option, [$1], does not take an argument ([$2]).])],
+ [$7])
+ fi])
+
+dnl MOZ_ARG_ENABLE_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE]])
+AC_DEFUN([MOZ_ARG_ENABLE_BOOL],
+[AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_DISABLE_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE]])
+AC_DEFUN([MOZ_ARG_DISABLE_BOOL],
+[AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], no, [$3], yes, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_ENABLE_STRING(NAME, HELP, IF-SET [, ELSE])
+AC_DEFUN([MOZ_ARG_ENABLE_STRING],
+[AC_ARG_ENABLE([$1], [$2], [$3], [$4])])
+
+dnl MOZ_ARG_ENABLE_BOOL_OR_STRING(NAME, HELP, IF-YES, IF-NO, IF-SET[, ELSE]]])
+AC_DEFUN([MOZ_ARG_ENABLE_BOOL_OR_STRING],
+[ifelse([$5], ,
+ [errprint([Option, $1, needs an "IF-SET" argument.
+])
+ m4exit(1)],
+ [AC_ARG_ENABLE([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$enableval], yes, [$3], no, [$4], [$5])],
+ [$6])])])
+
+dnl MOZ_ARG_WITH_BOOL(NAME, HELP, IF-YES [, IF-NO [, ELSE])
+AC_DEFUN([MOZ_ARG_WITH_BOOL],
+[AC_ARG_WITH([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$withval], yes, [$3], no, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_WITHOUT_BOOL(NAME, HELP, IF-NO [, IF-YES [, ELSE])
+AC_DEFUN([MOZ_ARG_WITHOUT_BOOL],
+[AC_ARG_WITH([$1], [$2],
+ [MOZ_TWO_STRING_TEST([$1], [$withval], no, [$3], yes, [$4])],
+ [$5])])
+
+dnl MOZ_ARG_WITH_STRING(NAME, HELP, IF-SET [, ELSE])
+AC_DEFUN([MOZ_ARG_WITH_STRING],
+[AC_ARG_WITH([$1], [$2], [$3], [$4])])
+
+dnl MOZ_ARG_HEADER(Comment)
+dnl This is used by webconfig to group options
+define(MOZ_ARG_HEADER, [# $1])
+
+dnl
+dnl Apparently, some systems cannot properly check for the pthread
+dnl library unless <pthread.h> is included so we need to test
+dnl using it
+dnl
+dnl MOZ_CHECK_PTHREADS(lib, success, failure)
+AC_DEFUN([MOZ_CHECK_PTHREADS],
+[
+AC_MSG_CHECKING([for pthread_create in -l$1])
+echo "
+ #include <pthread.h>
+ #include <stdlib.h>
+ void *foo(void *v) { int a = 1; }
+ int main() {
+ pthread_t t;
+ if (!pthread_create(&t, 0, &foo, 0)) {
+ pthread_join(t, 0);
+ }
+ exit(0);
+ }" > dummy.c ;
+ echo "${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS" 1>&5;
+ ${CC-cc} -o dummy${ac_exeext} dummy.c $CFLAGS $CPPFLAGS -l[$1] $LDFLAGS $LIBS 2>&5;
+ _res=$? ;
+ rm -f dummy.c dummy${ac_exeext} ;
+ if test "$_res" = "0"; then
+ AC_MSG_RESULT([yes])
+ [$2]
+ else
+ AC_MSG_RESULT([no])
+ [$3]
+ fi
+])
+
+dnl MOZ_READ_MYCONFIG() - Read in 'myconfig.sh' file
+AC_DEFUN([MOZ_READ_MOZCONFIG],
+[AC_REQUIRE([AC_INIT_BINSH])dnl
+# Read in '.mozconfig' script to set the initial options.
+# See the mozconfig2configure script for more details.
+_AUTOCONF_TOOLS_DIR=`dirname [$]0`/[$1]/build/autoconf
+. $_AUTOCONF_TOOLS_DIR/mozconfig2configure])
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess
new file mode 100644
index 0000000..a20b311
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.guess
@@ -0,0 +1,1481 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-10-13'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit ;;
+#### MozillaHack
+# Netscape's hacked uname
+ xx:WINNT:* | xx:WIN95:*)
+ echo i586-pc-msvc
+ exit ;;
+### End MozillaHack
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+ ;;
+ or32:Linux:*:*)
+ echo or32-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && {
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit
+ }
+ test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+#### MozillaHack
+ *:*OpenVMS*:*:*)
+ case "${UNAME_SYSTEM}" in
+ POSIX_for_OpenVMS_AXP) echo alpha-dec-openvmsposix ;;
+ POSIX_for_OpenVMS_VAX) echo vax-dec-openvmsposix ;;
+ OpenVMS) echo alpha-dec-openvms ;;
+ *) echo unknown-dec-openvms ;;
+ esac
+ exit ;;
+#### End MozillaHack
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ c34*)
+ echo c34-convex-bsd
+ exit ;;
+ c38*)
+ echo c38-convex-bsd
+ exit ;;
+ c4*)
+ echo c4-convex-bsd
+ exit ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
+and
+ http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub
new file mode 100644
index 0000000..2d91b11
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/config.sub
@@ -0,0 +1,1595 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+timestamp='2005-10-13'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+#### MozillaHack
+# mips*el
+#### End MozillaHack
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | bfin \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+ | mips | mipsbe | mipseb | mips*el | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | ms1 \
+ | msp430 \
+ | ns16k | ns32k \
+ | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m32c)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+#### MozillaHack
+# mips*el
+#### End MozillaHack
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mips*el-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | ms1-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+ | xstormy16-* | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ m32c-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+#### MozillaHack
+ i386-msvc | msvc)
+ basic_machine=i386-pc
+ os=-msvc
+ ;;
+#### End MozillaHack
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+#### MozillaHack
+# msvc
+#### End MozillaHack
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -msvc* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-haiku)
+ os=-haiku
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh
new file mode 100644
index 0000000..0ff4b6a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/install-sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5; it is not part of GNU.
+#
+# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+
+instcmd="$mvprog"
+chmodcmd=""
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+fi
+
+if [ x"$dst" = x ]
+then
+ echo "install: no destination specified"
+ exit 1
+fi
+
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+if [ -d $dst ]
+then
+ dst="$dst"/`basename $src`
+fi
+
+# Make a temp file name in the proper directory.
+
+dstdir=`dirname $dst`
+dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+$doit $instcmd $src $dsttmp
+
+# and set any options; do chmod last to preserve setuid bits
+
+if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
+if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
+if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
+if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
+
+# Now rename the file to the real destination.
+
+$doit $rmcmd $dst
+$doit $mvcmd $dsttmp $dst
+
+
+exit 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile
new file mode 100644
index 0000000..5343f6f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/make-makefile
@@ -0,0 +1,315 @@
+#! /usr/bin/env perl
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# make-makefiles - Quickly create Makefiles for subdirectories.
+# Also, creates any needed subdirectories.
+#
+# usage: make-makefiles [ -t <topsrcdir> -p <print_topsrcdir> -d <depth> ] [ <subdir> | <subdir>/Makefile ] ...
+
+# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+#$debug = 1;
+
+# Determine various tree path variables
+#
+($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
+
+$object_fullpath = `pwd`;
+chdir $depth;
+$object_root = `pwd`;
+chomp $object_fullpath;
+chomp $object_root;
+
+# $source_subdir is the path from the object root to where
+# 'make-makefile' was called. For example, if make-makefile was
+# called from "mozilla/gfx/src", then $source_subdir would be
+# "gfx/src/".
+$source_subdir = "$object_fullpath/";
+my $quoted_object_root = quotemeta($object_root);
+$source_subdir =~ s|^$quoted_object_root/||;
+
+# Prefix makefiles with $source_subdir so that paths
+# will be relative to the top of the object tree.
+#
+for $makefile (@makefiles) {
+ $makefile = "$source_subdir$makefile";
+}
+
+create_directories(@makefiles);
+
+# Find the path to the source directory based on how 'make-makefile'
+# was invoked. The path is either relative to the object directory
+# or an absolute path.
+$given_srcdir = find_srcdir($topsrcdir, $depth);
+$pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
+
+if ($debug) {
+ warn "object_fullpath = $object_fullpath\n";
+ warn "object_root = $object_root\n";
+ warn "source_subdir = $source_subdir\n";
+ warn "makefiles = @makefiles\n";
+ warn "given_srcdir = $given_srcdir\n";
+}
+
+@unhandled = update_makefiles($given_srcdir, $pgiven_srcdir, @makefiles);
+
+run_config_status(@unhandled);
+
+# end of Main
+############################################################
+
+sub dirname {
+ return $_[0] =~ /(.*)\/.*/ ? "$1" : '.';
+}
+
+# find_depth: Pull the value of DEPTH out of a Makefile (or Makefile.in)
+sub find_depth {
+ my $depth = '';
+ open(MAKEFILE, "<$_[0]") || die "Unable to open $_[0]: $!\n";
+ while (<MAKEFILE>) {
+ next unless /^DEPTH\s*=\s*(\..*)/;
+ $depth = $1;
+ last;
+ }
+ close MAKEFILE;
+ return $depth;
+}
+
+sub parse_arguments {
+ my @args = @_;
+ my $depth = '';
+ my $topsrcdir = '';
+ my $ptopsrcdir;
+ my @makefiles = ();
+
+ while (1) {
+ if ($args[0] eq '-d') {
+ $depth = $args[1];
+ shift @args;
+ shift @args;
+ } elsif ($args[0] eq '-t') {
+ $topsrcdir = $args[1];
+ shift @args;
+ shift @args;
+ } elsif ($args[0] eq '-p') {
+ $ptopsrcdir = $args[1];
+ shift @args;
+ shift @args;
+ } else {
+ last;
+ }
+ }
+
+ if ($topsrcdir eq '') {
+ $topsrcdir = $0; # Figure out topsrcdir based on program name.
+ $topsrcdir =~ s|/?build/autoconf/.*$||;
+ }
+ if ($ptopsrcdir eq '') {
+ $ptopsrcdir = $topsrcdir;
+ }
+ if ($depth eq '') {
+ # Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
+ if (-e "Makefile.in") {
+ $depth = find_depth("Makefile.in");
+ } elsif (-e "Makefile") {
+ $depth = find_depth("Makefile");
+ } elsif (-e "../Makefile") {
+ $depth = "../".find_depth("../Makefile");
+ $depth =~ s/\/\.$//;
+ } else {
+ warn "Unable to determine depth (e.g. ../..) to root of objdir tree.\n";
+ die "No Makefile(.in) present. Try running with '-d <depth>'\n";
+ }
+ }
+
+ # Build the list of makefiles to generate
+ #
+ @makefiles = ();
+ my $makefile;
+ foreach $makefile (@args) {
+ $makefile =~ s/\.in$//;
+ $makefile =~ s/\/$//;
+ $makefile =~ /Makefile$/ or $makefile .= "/Makefile";
+ push @makefiles, "$makefile";
+ }
+ @makefiles = "Makefile" unless @args;
+
+ return ($topsrcdir, $ptopsrcdir, $depth, @makefiles);
+}
+
+
+# Create all the directories at once.
+# This can be much faster than calling mkdir() for each one.
+sub create_directories {
+ my @makefiles = @_;
+ my @dirs = ();
+ my $ac_file;
+ foreach $ac_file (@makefiles) {
+ push @dirs, dirname($ac_file);
+ }
+ # Call mkdir with the directories sorted by subdir count (how many /'s)
+ system "mkdir -p ". join(' ', map("\"$_\"", @dirs)) if @dirs;
+}
+
+# Find the top of the source directory
+# (Assuming that the executable is in $top_srcdir/build/autoconf)
+sub find_srcdir {
+ my ($ac_given_srcdir, $depth) = @_;
+
+ if ($debug) {
+ print "ac_given_srcdir = $ac_given_srcdir\n";
+ print "depth = $depth\n";
+ }
+ if ($ac_given_srcdir =~ /^\./ and $depth ne '.') {
+ my $quoted_depth = quotemeta($depth);
+ $ac_given_srcdir =~ s|^$quoted_depth/?||;
+ }
+ if ($debug) {
+ print "ac_given_srcdir = $ac_given_srcdir\n";
+ }
+ $ac_given_srcdir = '.' if $ac_given_srcdir eq '';
+ return $ac_given_srcdir;
+}
+
+# Output the makefiles.
+#
+sub update_makefiles {
+ my ($ac_given_srcdir, $pac_given_srcdir, @makefiles) = @_;
+ my @unhandled=();
+
+ my $ac_file;
+ foreach $ac_file (@makefiles) {
+ my $ac_file_in = "$ac_given_srcdir/${ac_file}.in";
+ my $ac_dir = dirname($ac_file);
+ my $ac_dots = '';
+ my $ac_dir_suffix = '';
+ my $srcdir = '.';
+ my $top_srcdir = '.';
+
+ # Determine $srcdir and $top_srcdir
+ #
+ if ($ac_dir ne '.') {
+ $ac_dir_suffix = "/$ac_dir";
+ $ac_dir_suffix =~ s%^/\./%/%;
+ $ac_dots = $ac_dir_suffix;
+ # Remove .. components from the provided dir suffix, and
+ # also the forward path components they were reversing.
+ my $backtracks = $ac_dots =~ s%\.\.(/|$)%%g;
+ while ($backtracks--) {
+ $ac_dots =~ s%/[^/]*%%;
+ }
+ $ac_dots =~ s%/[^/]*%../%g;
+ }
+ if ($ac_given_srcdir eq '.') {
+ if ($ac_dots ne '') {
+ $top_srcdir = $ac_dots;
+ $top_srcdir =~ s%/$%%;
+ }
+ } elsif ($pac_given_srcdir =~ m%^/% or $pac_given_srcdir =~ m%^.:/%) {
+ $srcdir = "$pac_given_srcdir$ac_dir_suffix";
+ $top_srcdir = "$pac_given_srcdir";
+ } else {
+ if ($debug) {
+ print "ac_dots = $ac_dots\n";
+ print "ac_dir_suffix = $ac_dir_suffix\n";
+ }
+ $srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix";
+ $top_srcdir = "$ac_dots$ac_given_srcdir";
+ }
+
+ if ($debug) {
+ print "ac_dir = $ac_dir\n";
+ print "ac_file = $ac_file\n";
+ print "ac_file_in = $ac_file_in\n";
+ print "srcdir = $srcdir\n";
+ print "top_srcdir = $top_srcdir\n";
+ print "cwd = " . `pwd` . "\n";
+ }
+
+ # Copy the file and make substitutions.
+ # @srcdir@ -> value of $srcdir
+ # @top_srcdir@ -> value of $top_srcdir
+ #
+ if (-e $ac_file) {
+ next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date.
+ warn "updating $ac_file\n";
+ } else {
+ warn "creating $ac_file\n";
+ }
+
+ open INFILE, "<$ac_file_in" or do {
+ warn "$0: Cannot read $ac_file_in: No such file or directory\n";
+ next;
+ };
+ open OUTFILE, ">$ac_file" or do {
+ warn "$0: Unable to create $ac_file\n";
+ next;
+ };
+
+ while (<INFILE>) {
+ #if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) {
+ # #warn "Two defines on a line:$ac_file:$.:$_";
+ # push @unhandled, $ac_file;
+ # last;
+ #}
+
+ s/\@srcdir\@/$srcdir/g;
+ s/\@top_srcdir\@/$top_srcdir/g;
+
+ if (/\@[_a-zA-Z]*\@/) {
+ #warn "Unknown variable:$ac_file:$.:$_";
+ push @unhandled, $ac_file;
+ last;
+ }
+ print OUTFILE;
+ }
+ close INFILE;
+ close OUTFILE;
+ }
+ return @unhandled;
+}
+
+sub run_config_status {
+ my @unhandled = @_;
+
+ # Run config.status with any unhandled files.
+ #
+ if (@unhandled) {
+ $ENV{CONFIG_FILES}= join ' ', @unhandled;
+ system "./config.status";
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh
new file mode 100644
index 0000000..c579a9d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/match-dir.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# This script will match a dir with a set of dirs.
+#
+# Usage: match-dir.sh match [dir1 dir2 ... dirn]
+#
+# Send comments, improvements, bugs to ramiro@netscape.com
+#
+
+if [ -f Makefile ]; then
+ MAKEFILE="Makefile"
+else
+ if [ -f Makefile.in ]; then
+ MAKEFILE="Makefile.in"
+ else
+ echo
+ echo "There ain't no 'Makefile' or 'Makefile.in' over here: $pwd, dude."
+ echo
+ exit 1
+ fi
+fi
+
+# Use DEPTH in the Makefile.in to determine the depth
+depth=`grep -w DEPTH ${MAKEFILE} | grep "\.\." | awk -F"=" '{ print $2; }'`
+cwd=`pwd`
+
+# Determine the depth count
+n=`echo $depth | tr '/' ' ' | wc -w`
+
+cd $depth
+objdir=`pwd`
+
+path=`echo $cwd | sed "s|^${objdir}/||"`
+
+match=$path
+
+for i in $*
+do
+# echo "Looking for $match in $i"
+
+ echo $i | grep -q -x $match
+
+ if [ $? -eq 0 ]
+ then
+ echo "1"
+
+ exit 0
+ fi
+
+# echo "Looking for $i in $match"
+
+ echo $match | grep -q $i
+
+ if [ $? -eq 0 ]
+ then
+ echo "1"
+
+ exit 0
+ fi
+done
+
+echo "0"
+
+exit 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m4 b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m4
new file mode 100644
index 0000000..d21df69
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/nspr.m4
@@ -0,0 +1,82 @@
+# -*- tab-width: 4; -*-
+# Configure paths for NSPR
+# Public domain - Chris Seawood <cls@seawood.org> 2001-04-05
+# Based upon gtk.m4 (also PD) by Owen Taylor
+
+dnl AM_PATH_NSPR([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for NSPR, and define NSPR_CFLAGS and NSPR_LIBS
+AC_DEFUN([AM_PATH_NSPR],
+[dnl
+
+AC_ARG_WITH(nspr-prefix,
+ [ --with-nspr-prefix=PFX Prefix where NSPR is installed],
+ nspr_config_prefix="$withval",
+ nspr_config_prefix="")
+
+AC_ARG_WITH(nspr-exec-prefix,
+ [ --with-nspr-exec-prefix=PFX
+ Exec prefix where NSPR is installed],
+ nspr_config_exec_prefix="$withval",
+ nspr_config_exec_prefix="")
+
+ if test -n "$nspr_config_exec_prefix"; then
+ nspr_config_args="$nspr_config_args --exec-prefix=$nspr_config_exec_prefix"
+ if test -z "$NSPR_CONFIG"; then
+ NSPR_CONFIG=$nspr_config_exec_prefix/bin/nspr-config
+ fi
+ fi
+ if test -n "$nspr_config_prefix"; then
+ nspr_config_args="$nspr_config_args --prefix=$nspr_config_prefix"
+ if test -z "$NSPR_CONFIG"; then
+ NSPR_CONFIG=$nspr_config_prefix/bin/nspr-config
+ fi
+ fi
+
+ unset ac_cv_path_NSPR_CONFIG
+ AC_PATH_PROG(NSPR_CONFIG, nspr-config, no)
+ min_nspr_version=ifelse([$1], ,4.0.0,$1)
+ AC_MSG_CHECKING(for NSPR - version >= $min_nspr_version)
+
+ no_nspr=""
+ if test "$NSPR_CONFIG" = "no"; then
+ no_nspr="yes"
+ else
+ NSPR_CFLAGS=`$NSPR_CONFIG $nspr_config_args --cflags`
+ NSPR_LIBS=`$NSPR_CONFIG $nspr_config_args --libs`
+
+ nspr_config_major_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ nspr_config_minor_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ nspr_config_micro_version=`$NSPR_CONFIG $nspr_config_args --version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ min_nspr_major_version=`echo $min_nspr_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ min_nspr_minor_version=`echo $min_nspr_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ min_nspr_micro_version=`echo $min_nspr_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+ if test "$nspr_config_major_version" -ne "$min_nspr_major_version"; then
+ no_nspr="yes"
+ elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&
+ test "$nspr_config_minor_version" -lt "$min_nspr_minor_version"; then
+ no_nspr="yes"
+ elif test "$nspr_config_major_version" -eq "$min_nspr_major_version" &&
+ test "$nspr_config_minor_version" -eq "$min_nspr_minor_version" &&
+ test "$nspr_config_micro_version" -lt "$min_nspr_micro_version"; then
+ no_nspr="yes"
+ fi
+ fi
+
+ if test -z "$no_nspr"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$2], , :, [$2])
+ else
+ AC_MSG_RESULT(no)
+ fi
+
+
+ AC_SUBST(NSPR_CFLAGS)
+ AC_SUBST(NSPR_LIBS)
+
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m4 b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m4
new file mode 100644
index 0000000..d84d210
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/pkg.m4
@@ -0,0 +1,59 @@
+# PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+# defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+# also defines GSTUFF_PKG_ERRORS on error
+AC_DEFUN([PKG_CHECK_MODULES],
+[succeeded=no
+
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "$PKG_CONFIG" = "no" ; then
+ echo "*** The pkg-config script could not be found. Make sure it is"
+ echo "*** in your path, or set the PKG_CONFIG environment variable"
+ echo "*** to the full path to pkg-config."
+ echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+ else
+ PKG_CONFIG_MIN_VERSION=0.9.0
+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+ AC_MSG_CHECKING(for $2)
+
+ if $PKG_CONFIG --exists "$2" ; then
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+ AC_MSG_RESULT($$1_CFLAGS)
+
+ AC_MSG_CHECKING($1_LIBS)
+ ## Remove evil flags like -Wl,--export-dynamic
+ $1_LIBS="`$PKG_CONFIG --libs \"$2\" |sed s/-Wl,--export-dynamic//g`"
+ AC_MSG_RESULT($$1_LIBS)
+ else
+ $1_CFLAGS=""
+ $1_LIBS=""
+ ## If we have a custom action on failure, don't print errors, but
+ ## do set a variable so people can do so.
+ $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ ifelse([$4], ,echo $$1_PKG_ERRORS,)
+ fi
+
+ AC_SUBST($1_CFLAGS)
+ AC_SUBST($1_LIBS)
+ else
+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+ echo "*** See http://www.freedesktop.org/software/pkgconfig"
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ ifelse([$3], , :, [$3])
+ else
+ if test "$COMPILE_ENVIRONMENT"; then
+ ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+ fi
+ fi
+])
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh
new file mode 100644
index 0000000..42f78eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/autoconf/update-makefile.sh
@@ -0,0 +1,118 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# This script will generate a single Makefile from a Makefile.in using
+# the config.status script.
+#
+# The config.status script is generated the first time you run
+# ./configure.
+#
+#
+# Usage: update-makefile.sh
+#
+# Send comments, improvements, bugs to ramiro@netscape.com
+#
+
+update_makefile_usage() {
+ _progname=`expr //$0 : '.*/\(.*\)'`
+ cat <<END_USAGE 2>&1
+
+Usage: $_progname [-h -u] [<keyword>]
+ -d <dir> Subdir to update
+ -h Print usage
+END_USAGE
+}
+
+# Parse the command-line options
+#
+subdir=
+while getopts d:h OPT; do
+ case $OPT in
+ d) # Make sure "subdir" has exactly one ending slash
+ subdir=`echo $OPTARG | sed 's/\/$//;'`"/" ;;
+ \?|h) update_makefile_usage
+ exit 1
+ ;;
+ esac
+done
+
+
+# find_depth: Pull the value of DEPTH out of Makefile (or Makefile.in)
+find_depth() {
+ egrep '^DEPTH[ ]*=[ ]*\.' $1 | awk -F= '{ print $2; }'
+}
+
+# The Makefile to create
+target_makefile=`pwd`"/${subdir}Makefile"
+
+# Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
+if [ -f Makefile.in ]
+then
+ depth=`find_depth Makefile.in`
+elif [ -f Makefile ]
+then
+ depth=`find_depth Makefile`
+elif [ -f ../Makefile ]
+then
+ depth="../"`find_depth Makefile`
+else
+ echo
+ echo "There ain't no 'Makefile' or 'Makefile.in' over here: $pwd"
+ echo
+ exit
+fi
+
+# 'cd' to the root of the tree to run "config.status" there
+cd $depth
+
+# Strip the tree root off the Makefile's path
+#
+root_path=`pwd`
+target_makefile=`expr $target_makefile : $root_path'/\(.*\)'`
+
+# Make sure config.status exists
+#
+if [ -f config.status ]
+then
+ CONFIG_FILES=$target_makefile ./config.status
+else
+ echo
+ echo "There ain't no 'config.status' over here: $pwd"
+ echo
+fi
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper b/tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper
new file mode 100644
index 0000000..679f0a1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/cygwin-wrapper
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Stupid wrapper to avoid win32 dospath/cygdrive issues
+# Try not to spawn programs from within this file. If the stuff in here looks royally
+# confusing, see bug: http://bugzilla.mozilla.org/show_bug.cgi?id=206643
+# and look at the older versions of this file that are easier to read, but
+# do basically the same thing
+#
+
+prog=$1
+shift
+if test -z "$prog"; then
+ exit 0
+fi
+
+# If $CYGDRIVE_MOUNT was not set in configure, give $mountpoint the results of mount -p
+mountpoint=$CYGDRIVE_MOUNT
+if test -z "$mountpoint"; then
+ mountpoint=`mount -p`
+ if test -z "$mountpoint"; then
+ print "Cannot determine cygwin mount points. Exiting"
+ exit 1
+ fi
+fi
+
+# Delete everything but "/cygdrive" (or other mountpoint) from mount=`mount -p`
+mountpoint=${mountpoint#*/}
+mountpoint=/${mountpoint%%[!A-Za-z0-9_]*}
+mountpoint=${mountpoint%/}
+
+args=""
+up=""
+if test "${prog}" = "-up"; then
+ up=1
+ prog=${1}
+ shift
+fi
+
+process=1
+
+# Convert the mountpoint in parameters to Win32 filenames
+# For instance: /cygdrive/c/foo -> c:/foo
+for i in "${@}"
+do
+ if test "${i}" = "-wrap"; then
+ process=1
+ else
+ if test "${i}" = "-nowrap"; then
+ process=
+ else
+ if test -n "${process}"; then
+ if test -n "${up}"; then
+ pathname=${i#-I[a-zA-Z]:/}
+ if ! test "${pathname}" = "${i}"; then
+ no_i=${i#-I}
+ driveletter=${no_i%%:*}
+ i=-I${mountpoint}/${driveletter}/${pathname}
+ fi
+ else
+ eval 'leader=${i%%'${mountpoint}'/[a-zA-Z]/*}'
+ if ! test "${leader}" = "${i}"; then
+ eval 'pathname=${i#'${leader}${mountpoint}'/[a-zA-Z]/}'
+ eval 'no_mountpoint=${i#'${leader}${mountpoint}'/}'
+ driveletter=${no_mountpoint%%/*}
+ i=${leader}${driveletter}:/${pathname}
+ fi
+ fi
+ fi
+
+ args="${args} ${i}"
+ fi
+ fi
+done
+
+exec $prog $args
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/hcc b/tools/node_modules/expresso/deps/jscoverage/js/build/hcc
new file mode 100644
index 0000000..adadbe4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/hcc
@@ -0,0 +1,111 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Fix brain-damaged compilers that don't understand -o and -c together
+#
+CC=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
+shift
+DASH_C=0
+DASH_O=0
+DUMMY="XxxXxxX"
+GET_OBJECT=0
+OBJ="${DUMMY}"
+OBJECT="${DUMMY}"
+
+for i in $*
+do
+ [ "${CHECK_O}" = yes ] && {
+ case $i in
+ ./*/*.o) OBJECT="$i"
+ OPTS="${OPTS} -o"
+ DASH_O=1
+ ;;
+ ./*.o) OBJECT="`basename $i`"
+ i=""
+ DASH_O=1
+ ;;
+ *.o) if [ $i = `basename $i` ]
+ then
+ OBJECT="$i"
+ i=""
+ else
+ OPTS="${OPTS} -o"
+ fi
+ DASH_O=1
+ ;;
+ *) OPTS="${OPTS} -o $i"
+ DASH_O=1
+ i=""
+ ;;
+ esac
+ CHECK_O=no
+ }
+ case $i in
+ -c) DASH_C=1
+ OPTS="${OPTS} -c"
+ ;;
+ -o) CHECK_O=yes
+ ;;
+ *.c) C_SRC=$i
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .c name
+ OBJ=`basename $C_SRC .c`.o
+ ;;
+ *.s) S_SRC=$i
+ OPTS="${OPTS} $i"
+# or the .o from the .s name
+ OBJ=`basename $S_SRC .s`.o
+ ;;
+ *.o) OBJECT=$i
+ OPTS="${OPTS} $i"
+ ;;
+ *) OPTS="${OPTS} $i"
+ ;;
+ esac
+done
+
+${CC} ${OPTS} || exit $?
+
+# if there was no -c and -o we're done
+[ $DASH_C = 1 -a $DASH_O = 1 ] || exit 0
+
+# if $OBJ and $OBJECT are the same we're done
+[ $OBJ = $OBJECT ] && exit 0
+
+[ -f $OBJ ] && mv -f $OBJ $OBJECT
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/hcpp b/tools/node_modules/expresso/deps/jscoverage/js/build/hcpp
new file mode 100644
index 0000000..ea55fa4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/hcpp
@@ -0,0 +1,155 @@
+#!/bin/sh
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Wrapper for brain-damaged compilers that don't understand -o and -c together.
+#
+CXX=`echo $1 | sed -e "s|'||g" -e 's|"||g'`
+shift
+DUMMY="XxxXxxX"
+DASH_C=0
+DASH_O=0
+GET_OBJECT=0
+C_SRC="${DUMMY}"
+CC_SRC="${DUMMY}"
+CPP_SRC="${DUMMY}"
+S_SRC="${DUMMY}"
+OBJECT="${DUMMY}"
+NEW_i="${DUMMY}"
+PLATFORM=`uname -s`
+
+for i in $*
+do
+ [ ${GET_OBJECT} -eq 1 ] && {
+ case $i in
+ ./*/*.o) OBJECT="$i"
+ OPTS="${OPTS} -o"
+ DASH_O=1
+ ;;
+ ./*.o) OBJECT="`basename $i`"
+ i=""
+ DASH_O=1
+ ;;
+ *.o) if [ $i = `basename $i` ]
+ then
+ i=""
+ else
+ OPTS="${OPTS} -o"
+ DASH_O=1
+ fi
+ ;;
+ *) OPTS="${OPTS} -o $i"
+ DASH_O=1
+ i=""
+ ;;
+ esac
+ GET_OBJECT=0
+ }
+ case $i in
+ -c)
+ DASH_C=1
+ OPTS="${OPTS} -c"
+ ;;
+ -o)
+ GET_OBJECT=1
+ ;;
+ *.c)
+ C_SRC="$i"
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .c name
+ OBJ=`basename ${C_SRC} .c`.o
+ ;;
+ +.*)
+ OPTS="${OPTS} $i"
+ ;;
+ *.cpp)
+ CPP_SRC="$i"
+ if [ "${PLATFORM}" = "SCO_SV" ]; then
+ OPTS="${OPTS} +.cpp $i"
+ elif [ "${PLATFORM}" = "IRIX" ]; then
+ NEW_i=`basename ${CPP_SRC} .cpp`.C
+ rm -f ${NEW_i}
+ cp $i ${NEW_i}
+ OPTS="${OPTS} ${NEW_i}"
+ else
+ OPTS="${OPTS} $i"
+ fi
+# cc always creates the .o from the .cpp name
+ OBJ=`basename ${CPP_SRC} .cpp`.o
+ ;;
+ *.cc)
+ CC_SRC="$i"
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .cc name
+ OBJ=`basename ${CC_SRC} .cc`.o
+ ;;
+ *.s)
+ S_SRC="$i"
+ OPTS="${OPTS} $i"
+# cc always creates the .o from the .s name
+ OBJ=`basename ${S_SRC} .s`.o
+ ;;
+ *.o) OBJECT=$i
+ OPTS="${OPTS} $i"
+ ;;
+ *) OPTS="${OPTS} $i"
+ ;;
+ esac
+done
+
+${CXX} ${OPTS} || exit $?
+rm -f ${NEW_i}
+
+# Really only needed for NSPR now.
+if [ "${PLATFORM}" = "IRIX" -a "$OBJ" != "$OBJECT" ]; then
+ OBJ=$OBJECT
+fi
+
+# LAME!!!
+if [ -f -O ]; then
+ mv -f -- -O ${OBJECT}
+fi
+
+# if there was no -c and -o we're done
+[ ${DASH_C} -eq 1 -a ${DASH_O} -eq 1 ] || exit 0
+
+# if $OBJ and $OBJECT are the same we're done
+[ $OBJ = $OBJECT ] && exit 0
+
+[ -f $OBJ ] && mv -f $OBJ $OBJECT
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl
new file mode 100644
index 0000000..380e4ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/mddepend.pl
@@ -0,0 +1,165 @@
+#!/usr/bin/env perl
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is this file as it was released upon March 8, 1999.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# mddepend.pl - Reads in dependencies generated my -MD flag. Prints list
+# of objects that need to be rebuilt. These can then be added to the
+# PHONY target. Using this script copes with the problem of header
+# files that have been removed from the build.
+#
+# Usage:
+# mddepend.pl <output_file> <dependency_files...>
+#
+# Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com).
+
+use strict;
+
+use constant DEBUG => 0;
+
+my $outfile = shift @ARGV;
+my $silent = $ENV{MAKEFLAGS} =~ /^\w*s|\s-s/;
+
+my $line = '';
+my %alldeps;
+# Parse dependency files
+while (<>) {
+ s/\r?\n$//; # Handle both unix and DOS line endings
+ $line .= $_;
+ if ($line =~ /\\$/) {
+ chop $line;
+ next;
+ }
+
+ my ($obj,$rest) = split /\s*:\s+/, $line, 2;
+ $line = '';
+ next if !$obj || !$rest;
+
+ my @deps = split /\s+/, $rest;
+ push @{$alldeps{$obj}}, @deps;
+ if (DEBUG >= 2) {
+ foreach my $dep (@deps) { print "add $obj $dep\n"; }
+ }
+}
+
+# Test dependencies
+my %modtimes; # cache
+my @objs; # force rebuild on these
+OBJ_LOOP: foreach my $obj (keys %alldeps) {
+ my $mtime = (stat $obj)[9] or next;
+
+ my %not_in_cache;
+ my $deps = $alldeps{$obj};
+ foreach my $dep_file (@{$deps}) {
+ my $dep_mtime = $modtimes{$dep_file};
+ if (not defined $dep_mtime) {
+ print "Skipping $dep_file for $obj, will stat() later\n" if DEBUG >= 2;
+ $not_in_cache{$dep_file} = 1;
+ next;
+ }
+
+ print "Found $dep_file in cache\n" if DEBUG >= 2;
+
+ if ($dep_mtime > $mtime) {
+ print "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
+ }
+ elsif ($dep_mtime == -1) {
+ print "Couldn't stat $dep_file for $obj\n" if DEBUG;
+ }
+ else {
+ print "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
+ next;
+ }
+
+ push @objs, $obj; # dependency is missing or newer
+ next OBJ_LOOP; # skip checking the rest of the dependencies
+ }
+
+ foreach my $dep_file (keys %not_in_cache) {
+ print "STAT $dep_file for $obj\n" if DEBUG >= 2;
+ my $dep_mtime = $modtimes{$dep_file} = (stat $dep_file)[9] || -1;
+
+ if ($dep_mtime > $mtime) {
+ print "$dep_file($dep_mtime) newer than $obj($mtime)\n" if DEBUG;
+ }
+ elsif ($dep_mtime == -1) {
+ print "Couldn't stat $dep_file for $obj\n" if DEBUG;
+ }
+ else {
+ print "$dep_file($dep_mtime) older than $obj($mtime)\n" if DEBUG >= 2;
+ next;
+ }
+
+ push @objs, $obj; # dependency is missing or newer
+ next OBJ_LOOP; # skip checking the rest of the dependencies
+ }
+
+ # If we get here it means nothing needs to be done for $obj
+}
+
+# Output objects to rebuild (if needed).
+if (@objs) {
+ my $old_output;
+ my $new_output = "@objs: FORCE\n";
+
+ # Read in the current dependencies file.
+ open(OLD, "<$outfile")
+ and $old_output = <OLD>;
+ close(OLD);
+
+ # Only write out the dependencies if they are different.
+ if ($new_output ne $old_output) {
+ open(OUT, ">$outfile") and print OUT "$new_output";
+ print "Updating dependencies file, $outfile\n" unless $silent;
+ if (DEBUG) {
+ print "new: $new_output\n";
+ print "was: $old_output\n" if $old_output ne '';
+ }
+ }
+} elsif (-s $outfile) {
+ # Remove the old dependencies because all objects are up to date.
+ print "Removing old dependencies file, $outfile\n" unless $silent;
+
+ if (DEBUG) {
+ my $old_output;
+ open(OLD, "<$outfile")
+ and $old_output = <OLD>;
+ close(OLD);
+ print "was: $old_output\n";
+ }
+
+ unlink $outfile;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl
new file mode 100644
index 0000000..1b40bda
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/unix/uniq.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/env perl
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is this file as it was released upon December 26, 2000.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2000
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Christopher Seawood <cls@seawood.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+use Getopt::Std;
+
+getopts('rs');
+$regexp = 1 if (defined($opt_r));
+$sort = 1 if (defined($opt_s));
+
+undef @out;
+if ($sort) {
+ @in = sort @ARGV;
+} else {
+ @in = @ARGV;
+}
+foreach $d (@in) {
+ if ($regexp) {
+ $found = 0;
+ foreach $dir (@out) {
+ $found++, last if ($d =~ m/^$dir\// || $d eq $dir);
+ }
+ push @out, $d if (!$found);
+ } else {
+ push @out, $d if (!grep(/^$d$/, @out));
+ }
+}
+print "@out\n"
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py b/tools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py
new file mode 100755
index 0000000..528c4ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/build/win32/pgomerge.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+# Usage: pgomerge.py <binary basename> <dist/bin>
+# Gathers .pgc files from dist/bin and merges them into
+# $PWD/$basename.pgd using pgomgr, then deletes them.
+# No errors if any of these files don't exist.
+
+import sys, os, os.path, subprocess
+if not sys.platform == "win32":
+ raise Exception("This script was only meant for Windows.")
+
+def MergePGOFiles(basename, pgddir, pgcdir):
+ """Merge pgc files produced from an instrumented binary
+ into the pgd file for the second pass of profile-guided optimization
+ with MSVC. |basename| is the name of the DLL or EXE without the
+ extension. |pgddir| is the path that contains <basename>.pgd
+ (should be the objdir it was built in). |pgcdir| is the path
+ containing basename!N.pgc files, which is probably dist/bin.
+ Calls pgomgr to merge each pgc file into the pgd, then deletes
+ the pgc files."""
+ if not os.path.isdir(pgddir) or not os.path.isdir(pgcdir):
+ return
+ pgdfile = os.path.abspath(os.path.join(pgddir, basename + ".pgd"))
+ if not os.path.isfile(pgdfile):
+ return
+ for file in os.listdir(pgcdir):
+ if file.startswith(basename) and file.endswith(".pgc"):
+ try:
+ pgcfile = os.path.normpath(os.path.join(pgcdir, file))
+ subprocess.call(['pgomgr', '-merge',
+ pgcfile,
+ pgdfile])
+ os.remove(pgcfile)
+ except OSError:
+ pass
+
+if __name__ == '__main__':
+ if len(sys.argv) != 3:
+ print >>sys.stderr, "Usage: pgomerge.py <binary basename> <dist/bin>"
+ sys.exit(1)
+ MergePGOFiles(sys.argv[1], os.getcwd(), sys.argv[2])
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl b/tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl
new file mode 100644
index 0000000..a725d97
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/builtins.tbl
@@ -0,0 +1,98 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * June 22, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Andreas Gal <gal@uci.edu>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * This file declares builtin functions that can be called from JITted code.
+ * Each line starts with "BUILTIN" and an integer, the number of arguments the
+ * builtin takes. Builtins with no arguments are not supported.
+ *
+ * The macro arguments are:
+ *
+ * - 'extern' to indicate extern linkage for these functions and the associated
+ * CallInfo.
+ *
+ * - The return type. This identifier must name one of the _JS_TYPEINFO_*
+ * macros defined in jsbuiltins.h.
+ *
+ * - The builtin name. Prefixed with "js_" this gives the native function name.
+ *
+ * - The parameter types.
+ *
+ * - The cse flag. 1 if the builtin call can be optimized away by common
+ * subexpression elimination; otherwise 0. This should be 1 only if the
+ * function is idempotent and the return value is determined solely by the
+ * arguments.
+ *
+ * - The fold flag. Reserved. The same as cse for now.
+ */
+
+/*
+ * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
+ * Do not use bool FASTCALL, use JSBool only!
+ */
+
+BUILTIN2(extern, JSVAL, js_BoxDouble, CONTEXT, DOUBLE, 1, 1)
+BUILTIN2(extern, JSVAL, js_BoxInt32, CONTEXT, INT32, 1, 1)
+BUILTIN1(extern, DOUBLE, js_UnboxDouble, JSVAL, 1, 1)
+BUILTIN1(extern, INT32, js_UnboxInt32, JSVAL, 1, 1)
+BUILTIN2(extern, DOUBLE, js_dmod, DOUBLE, DOUBLE, 1, 1)
+BUILTIN2(extern, INT32, js_imod, INT32, INT32, 1, 1)
+BUILTIN1(extern, INT32, js_DoubleToInt32, DOUBLE, 1, 1)
+BUILTIN1(extern, UINT32, js_DoubleToUint32, DOUBLE, 1, 1)
+
+BUILTIN2(extern, DOUBLE, js_StringToNumber, CONTEXT, STRING, 1, 1)
+BUILTIN2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, 1)
+BUILTIN3(extern, JSVAL, js_Any_getprop, CONTEXT, OBJECT, STRING, 0, 0)
+BUILTIN4(extern, BOOL, js_Any_setprop, CONTEXT, OBJECT, STRING, JSVAL, 0, 0)
+BUILTIN3(extern, JSVAL, js_Any_getelem, CONTEXT, OBJECT, INT32, 0, 0)
+BUILTIN4(extern, BOOL, js_Any_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0)
+BUILTIN3(extern, OBJECT, js_FastValueToIterator, CONTEXT, UINT32, JSVAL, 0, 0)
+BUILTIN2(extern, JSVAL, js_FastCallIteratorNext, CONTEXT, OBJECT, 0, 0)
+BUILTIN2(FRIEND, BOOL, js_CloseIterator, CONTEXT, JSVAL, 0, 0)
+BUILTIN2(extern, SIDEEXIT, js_CallTree, INTERPSTATE, FRAGMENT, 0, 0)
+BUILTIN2(extern, OBJECT, js_FastNewObject, CONTEXT, OBJECT, 0, 0)
+BUILTIN3(extern, BOOL, js_AddProperty, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
+BUILTIN3(extern, BOOL, js_HasNamedProperty, CONTEXT, OBJECT, STRING, 0, 0)
+BUILTIN3(extern, BOOL, js_HasNamedPropertyInt32, CONTEXT, OBJECT, INT32, 0, 0)
+BUILTIN3(extern, JSVAL, js_CallGetter, CONTEXT, OBJECT, SCOPEPROP, 0, 0)
+BUILTIN2(extern, STRING, js_TypeOfObject, CONTEXT, OBJECT, 1, 1)
+BUILTIN2(extern, STRING, js_TypeOfBoolean, CONTEXT, INT32, 1, 1)
+BUILTIN2(extern, DOUBLE, js_BooleanOrUndefinedToNumber, CONTEXT, INT32, 1, 1)
+BUILTIN2(extern, STRING, js_BooleanOrUndefinedToString, CONTEXT, INT32, 1, 1)
+BUILTIN2(extern, STRING, js_ObjectToString, CONTEXT, OBJECT, 0, 0)
+BUILTIN1(extern, OBJECT, js_Arguments, CONTEXT, 0, 0)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config.mk b/tools/node_modules/expresso/deps/jscoverage/js/config.mk
new file mode 100644
index 0000000..ddd96ed
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config.mk
@@ -0,0 +1,206 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifdef JS_DIST
+DIST = $(JS_DIST)
+else
+DIST = $(DEPTH)/../../dist
+endif
+
+# Set os+release dependent make variables
+OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/))
+
+# Attempt to differentiate between SunOS 5.4 and x86 5.4
+OS_CPUARCH := $(shell uname -m)
+ifeq ($(OS_CPUARCH),i86pc)
+OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH)
+else
+ifeq ($(OS_ARCH),AIX)
+OS_RELEASE := $(shell uname -v).$(shell uname -r)
+else
+OS_RELEASE := $(shell uname -r)
+endif
+endif
+ifeq ($(OS_ARCH),IRIX64)
+OS_ARCH := IRIX
+endif
+
+# Handle output from win32 unames other than Netscape's version
+ifeq (,$(filter-out Windows_95 Windows_98 CYGWIN_95-4.0 CYGWIN_98-4.10, $(OS_ARCH)))
+ OS_ARCH := WIN95
+endif
+ifeq ($(OS_ARCH),WIN95)
+ OS_ARCH := WINNT
+ OS_RELEASE := 4.0
+endif
+ifeq ($(OS_ARCH), Windows_NT)
+ OS_ARCH := WINNT
+ OS_MINOR_RELEASE := $(shell uname -v)
+ ifeq ($(OS_MINOR_RELEASE),00)
+ OS_MINOR_RELEASE = 0
+ endif
+ OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE)
+endif
+ifeq (CYGWIN_NT,$(findstring CYGWIN_NT,$(OS_ARCH)))
+ OS_RELEASE := $(patsubst CYGWIN_NT-%,%,$(OS_ARCH))
+ OS_ARCH := WINNT
+endif
+ifeq ($(OS_ARCH), CYGWIN32_NT)
+ OS_ARCH := WINNT
+endif
+ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH)))
+ OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH))
+ OS_ARCH := WINNT
+endif
+
+# Virtually all Linux versions are identical.
+# Any distinctions are handled in linux.h
+ifeq ($(OS_ARCH),Linux)
+OS_CONFIG := Linux_All
+else
+ifeq ($(OS_ARCH),dgux)
+OS_CONFIG := dgux
+else
+ifeq ($(OS_ARCH),Darwin)
+OS_CONFIG := Darwin
+else
+ifeq ($(OS_ARCH),Darwin64)
+OS_CONFIG := Darwin64
+else
+OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE)
+endif
+endif
+endif
+endif
+
+ASFLAGS =
+DEFINES =
+
+ifeq ($(OS_ARCH), WINNT)
+INSTALL = nsinstall
+CP = cp
+else
+INSTALL = $(DIST)/bin/nsinstall
+CP = cp
+endif
+
+ifdef BUILD_OPT
+ifdef USE_MSVC
+OPTIMIZER = -O2 -GL
+INTERP_OPTIMIZER = -O2 -GL
+BUILTINS_OPTIMIZER = -O2 -GL
+LDFLAGS += -LTCG
+else
+OPTIMIZER = -Os -fstrict-aliasing -fno-exceptions -fno-rtti -Wstrict-aliasing=2
+BUILTINS_OPTIMIZER = -O9 -fstrict-aliasing -fno-exceptions -fno-rtti
+INTERP_OPTIMIZER = -O3 -fstrict-aliasing -fno-exceptions -fno-rtti
+endif
+DEFINES += -UDEBUG -DNDEBUG -UDEBUG_$(USER)
+OBJDIR_TAG = _OPT
+else
+ifdef USE_MSVC
+OPTIMIZER = -Zi
+INTERP_OPTIMIZER = -Zi
+BUILTINS_OPTIMIZER = $(INTERP_OPTIMIZER)
+else
+OPTIMIZER = -g3 -fstrict-aliasing -fno-exceptions -fno-rtti -Wstrict-aliasing=2
+INTERP_OPTIMIZER = -g3 -fstrict-aliasing -fno-exceptions -fno-rtti
+BUILTINS_OPTIMIZER = $(INTERP_OPTIMIZER)
+endif
+DEFINES += -DDEBUG -DDEBUG_$(USER)
+OBJDIR_TAG = _DBG
+endif
+
+SO_SUFFIX = so
+
+NS_USE_NATIVE = 1
+
+# Java stuff
+CLASSDIR = $(DEPTH)/liveconnect/classes
+JAVA_CLASSES = $(patsubst %.java,%.class,$(JAVA_SRCS))
+TARGETS += $(addprefix $(CLASSDIR)/$(OBJDIR)/$(JARPATH)/, $(JAVA_CLASSES))
+JAVAC = $(JDK)/bin/javac
+JAVAC_FLAGS = -classpath "$(CLASSPATH)" -d $(CLASSDIR)/$(OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ SEP = ;
+else
+ SEP = :
+endif
+CLASSPATH = $(JDK)/lib/classes.zip$(SEP)$(CLASSDIR)/$(OBJDIR)
+
+include $(DEPTH)/ref-config/$(OS_CONFIG).mk
+
+ifndef OBJ_SUFFIX
+ifdef USE_MSVC
+OBJ_SUFFIX = obj
+else
+OBJ_SUFFIX = o
+endif
+endif
+
+ifndef HOST_BIN_SUFFIX
+ifeq ($(OS_ARCH),WINNT)
+HOST_BIN_SUFFIX = .exe
+else
+HOST_BIN_SUFFIX =
+endif
+endif
+
+# Name of the binary code directories
+ifdef OBJROOT
+# prepend $(DEPTH) to the root unless it is an absolute path
+OBJDIR = $(if $(filter /%,$(OBJROOT)),$(OBJROOT),$(DEPTH)/$(OBJROOT))
+else
+ifeq ($(DEPTH),.)
+OBJDIR = $(OS_CONFIG)$(OBJDIR_TAG).$(if $(BUILD_IDG),OBJD,OBJ)
+else
+OBJDIR = $(DEPTH)/$(OS_CONFIG)$(OBJDIR_TAG).$(if $(BUILD_IDG),OBJD,OBJ)
+endif
+endif
+
+VPATH = $(OBJDIR)
+
+LCJAR = js15lc30.jar
+
+# Library name
+LIBDIR := lib
+ifeq ($(CPU_ARCH), x86_64)
+LIBDIR := lib64
+endif
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in
new file mode 100644
index 0000000..39f9912
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/Makefile.in
@@ -0,0 +1,106 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Robert Ginda <rginda@netscape.com>
+# John Taylor <jtaylor@netscape.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+# For sanity's sake, we compile nsinstall without the wrapped system
+# headers, so that we can use it to set up the wrapped system headers.
+VISIBILITY_FLAGS =
+
+ifneq (,$(CROSS_COMPILE)$(filter-out WINNT OS2,$(OS_ARCH)))
+ifneq ($(OS_ARCH), WINCE)
+HOST_PROGRAM = nsinstall$(HOST_BIN_SUFFIX)
+HOST_CSRCS = nsinstall.c pathsub.c
+endif
+endif
+
+PLSRCS = nfspwd.pl revdepth.pl
+
+TARGETS = $(HOST_PROGRAM) $(PLSRCS:.pl=) $(SIMPLE_PROGRAMS)
+
+# IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
+# a recursive rule for finding nsinstall and the Perl scripts.
+ifdef NSBUILDROOT
+override NSBUILDROOT :=
+endif
+
+ifdef GNU_CC
+MODULE_OPTIMIZE_FLAGS = -O3
+endif
+
+ifndef COMPILER_DEPEND
+ifndef MOZ_NATIVE_MAKEDEPEND
+DIRS += mkdepend
+endif
+endif
+
+include $(topsrcdir)/config/config.mk
+
+# Do not install util programs
+NO_INSTALL=1
+
+include $(topsrcdir)/config/rules.mk
+
+export:: $(TARGETS)
+ifdef HOST_PROGRAM
+ $(INSTALL) $(HOST_PROGRAM) $(DIST)/bin
+endif
+
+ifdef WRAP_SYSTEM_INCLUDES
+export::
+ if test ! -d system_wrappers; then mkdir system_wrappers; fi
+ $(PERL) $(srcdir)/preprocessor.pl $(DEFINES) $(ACDEFINES) \
+ -DBUILD_STATIC_LIBS=$(BUILD_STATIC_LIBS) \
+ $(srcdir)/system-headers | $(PERL) $(srcdir)/make-system-wrappers.pl system_wrappers
+ $(INSTALL) system_wrappers $(DIST)/include
+
+GARBAGE_DIRS += system_wrappers
+endif
+
+FORCE:
+
+ifdef MKDEPEND_DIR
+clean clobber realclean clobber_all::
+ cd $(MKDEPEND_DIR); $(MAKE) $@
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm b/tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm
new file mode 100644
index 0000000..8dd1449
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/Moz/Milestone.pm
@@ -0,0 +1,232 @@
+#!/usr/bin/perl -w
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Netscape Communications Corporation
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+package Moz::Milestone;
+use strict;
+
+use vars qw($officialMilestone
+ $milestone);
+
+local $Moz::Milestone::milestone;
+local $Moz::Milestone::officialMilestone;
+
+#
+# Usage: getOfficialMilestone($milestoneFile)
+# Returns full milestone (x.x.x.x[ab12pre+])
+#
+sub getOfficialMilestone($) {
+ my $mfile = $_[0];
+ open(FILE,"$mfile") ||
+ die ("Can't open $mfile for reading!");
+
+ my $num = <FILE>;
+ while($num =~ /^\s*#/ || $num !~ /^\d/) {
+ $num = <FILE>;
+ }
+
+ close(FILE);
+ if ($num !~ /^\d/) { return; }
+ chomp($num);
+ # Remove extra ^M caused by using dos-mode line-endings
+ chop $num if (substr($num, -1, 1) eq "\r");
+ $Moz::Milestone::officialMilestone = $num;
+ $Moz::Milestone::milestone = &getMilestoneNum;
+ return $num;
+}
+
+#
+# Usage: getMilestoneNum($num)
+# Returns: milestone without a + if it exists.
+#
+sub getMilestoneNum {
+ if (defined($Moz::Milestone::milestone)) {
+ return $Moz::Milestone::milestone;
+ }
+
+ if (defined($Moz::Milestone::officialMilestone)) {
+ $Moz::Milestone::milestone = $Moz::Milestone::officialMilestone;
+ } else {
+ $Moz::Milestone::milestone = $_[0];
+ }
+
+ if ($Moz::Milestone::milestone =~ /\+$/) { # for x.x.x+, strip off the +
+ $Moz::Milestone::milestone =~ s/\+$//;
+ }
+
+ return $Moz::Milestone::milestone;
+}
+
+#
+# Usage: getMilestoneQualifier($num)
+# Returns: + if it exists.
+#
+sub getMilestoneQualifier {
+ my $milestoneQualifier;
+ if (defined($Moz::Milestone::officialMilestone)) {
+ $milestoneQualifier = $Moz::Milestone::officialMilestone;
+ } else {
+ $milestoneQualifier = $_[0];
+ }
+
+ if ($milestoneQualifier =~ /\+$/) {
+ return "+";
+ }
+}
+
+sub getMilestoneMajor {
+ my $milestoneMajor;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMajor = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMajor = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMajor);
+ return $parts[0];
+}
+
+sub getMilestoneMinor {
+ my $milestoneMinor;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMinor = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMinor = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMinor);
+
+ if ($#parts < 1 ) { return 0; }
+ return $parts[1];
+}
+
+sub getMilestoneMini {
+ my $milestoneMini;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMini = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMini = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMini);
+
+ if ($#parts < 2 ) { return 0; }
+ return $parts[2];
+}
+
+sub getMilestoneMicro {
+ my $milestoneMicro;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneMicro = $Moz::Milestone::milestone;
+ } else {
+ $milestoneMicro = $_[0];
+ }
+ my @parts = split(/\./,$milestoneMicro);
+
+ if ($#parts < 3 ) { return 0; }
+ return $parts[3];
+}
+
+sub getMilestoneAB {
+ my $milestoneAB;
+ if (defined($Moz::Milestone::milestone)) {
+ $milestoneAB = $Moz::Milestone::milestone;
+ } else {
+ $milestoneAB = $_[0];
+ }
+
+ if ($milestoneAB =~ /a/) { return "alpha"; }
+ if ($milestoneAB =~ /b/) { return "beta"; }
+ return "final";
+}
+
+#
+# build_file($template_file,$output_file)
+#
+sub build_file($$) {
+ my @FILE;
+ my @MILESTONE_PARTS;
+ my $MINI_VERSION = 0;
+ my $MICRO_VERSION = 0;
+ my $OFFICIAL = 0;
+ my $QUALIFIER = "";
+
+ if (!defined($Moz::Milestone::milestone)) { die("$0: no milestone file set!\n"); }
+ @MILESTONE_PARTS = split(/\./, &getMilestoneNum);
+ if ($#MILESTONE_PARTS >= 2) {
+ $MINI_VERSION = 1;
+ } else {
+ $MILESTONE_PARTS[2] = 0;
+ }
+ if ($#MILESTONE_PARTS >= 3) {
+ $MICRO_VERSION = 1;
+ } else {
+ $MILESTONE_PARTS[3] = 0;
+ }
+ if (! &getMilestoneQualifier) {
+ $OFFICIAL = 1;
+ } else {
+ $QUALIFIER = "+";
+ }
+
+ if (-e $_[0]) {
+ open(FILE, "$_[0]") || die("$0: Can't open $_[0] for reading!\n");
+ @FILE = <FILE>;
+ close(FILE);
+
+ open(FILE, ">$_[1]") || die("$0: Can't open $_[1] for writing!\n");
+
+ #
+ # There will be more of these based on what we need for files.
+ #
+ foreach(@FILE) {
+ s/__MOZ_MAJOR_VERSION__/$MILESTONE_PARTS[0]/g;
+ s/__MOZ_MINOR_VERSION__/$MILESTONE_PARTS[1]/g;
+ s/__MOZ_MINI_VERSION__/$MILESTONE_PARTS[2]/g;
+ s/__MOZ_MICRO_VERSION__/$MILESTONE_PARTS[3]/g;
+ if ($MINI_VERSION) {
+ s/__MOZ_OPTIONAL_MINI_VERSION__/.$MILESTONE_PARTS[2]/g;
+ }
+ if ($MICRO_VERSION) {
+ s/__MOZ_OPTIONAL_MICRO_VERSION__/.$MILESTONE_PARTS[3]/g;
+ }
+
+ print FILE $_;
+ }
+ close(FILE);
+ } else {
+ die("$0: $_[0] doesn't exist for autoversioning!\n");
+ }
+
+}
+
+1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in b/tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in
new file mode 100644
index 0000000..d82e614
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/autoconf.mk.in
@@ -0,0 +1,349 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is this file as it was released upon August 6, 1998.
+#
+# The Initial Developer of the Original Code is
+# Christopher Seawood.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Benjamin Smedberg <benjamin@smedbergs.us>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# A netscape style .mk file for autoconf builds
+
+INCLUDED_AUTOCONF_MK = 1
+USE_AUTOCONF = 1
+MOZILLA_CLIENT = 1
+target = @target@
+ac_configure_args = @ac_configure_args@
+BUILD_MODULES = @BUILD_MODULES@
+MOZILLA_VERSION = @MOZILLA_VERSION@
+
+MOZ_BUILD_APP = @MOZ_BUILD_APP@
+MOZ_APP_NAME = @MOZ_APP_NAME@
+MOZ_APP_DISPLAYNAME = @MOZ_APP_DISPLAYNAME@
+MOZ_APP_VERSION = @MOZ_APP_VERSION@
+
+MOZ_PKG_SPECIAL = @MOZ_PKG_SPECIAL@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+includedir = @includedir@
+libdir = @libdir@
+datadir = @datadir@
+mandir = @mandir@
+
+installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)
+sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION)
+
+DIST = $(DEPTH)/dist
+
+MOZ_JS_LIBS = @MOZ_JS_LIBS@
+
+MOZ_SYNC_BUILD_FILES = @MOZ_SYNC_BUILD_FILES@
+
+MOZ_DEBUG = @MOZ_DEBUG@
+MOZ_DEBUG_MODULES = @MOZ_DEBUG_MODULES@
+MOZ_PROFILE_MODULES = @MOZ_PROFILE_MODULES@
+MOZ_DEBUG_ENABLE_DEFS = @MOZ_DEBUG_ENABLE_DEFS@
+MOZ_DEBUG_DISABLE_DEFS = @MOZ_DEBUG_DISABLE_DEFS@
+MOZ_DEBUG_FLAGS = @MOZ_DEBUG_FLAGS@
+MOZ_DEBUG_LDFLAGS=@MOZ_DEBUG_LDFLAGS@
+MOZ_DBGRINFO_MODULES = @MOZ_DBGRINFO_MODULES@
+MOZ_EXTENSIONS = @MOZ_EXTENSIONS@
+MOZ_IMG_DECODERS= @MOZ_IMG_DECODERS@
+MOZ_IMG_ENCODERS= @MOZ_IMG_ENCODERS@
+MOZ_JSDEBUGGER = @MOZ_JSDEBUGGER@
+MOZ_PERF_METRICS = @MOZ_PERF_METRICS@
+MOZ_LEAKY = @MOZ_LEAKY@
+MOZ_MEMORY = @MOZ_MEMORY@
+MOZ_JPROF = @MOZ_JPROF@
+MOZ_SHARK = @MOZ_SHARK@
+MOZ_CALLGRIND = @MOZ_CALLGRIND@
+MOZ_VTUNE = @MOZ_VTUNE@
+DEHYDRA_PATH = @DEHYDRA_PATH@
+
+ENABLE_EAZEL_PROFILER=@ENABLE_EAZEL_PROFILER@
+EAZEL_PROFILER_CFLAGS=@EAZEL_PROFILER_CFLAGS@
+EAZEL_PROFILER_LIBS=@EAZEL_PROFILER_LIBS@
+GC_LEAK_DETECTOR = @GC_LEAK_DETECTOR@
+NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
+INCREMENTAL_LINKER = @INCREMENTAL_LINKER@
+MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@
+BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@
+ENABLE_TESTS = @ENABLE_TESTS@
+JS_ULTRASPARC_OPTS = @JS_ULTRASPARC_OPTS@
+JS_STATIC_BUILD = @JS_STATIC_BUILD@
+
+TAR=@TAR@
+
+# The MOZ_UI_LOCALE var is used to build a particular locale. Do *not*
+# use the var to change any binary files. Do *not* use this var unless you
+# write rules for the "clean-locale" and "locale" targets.
+MOZ_UI_LOCALE = @MOZ_UI_LOCALE@
+
+MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS = @MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS@
+MOZ_COMPONENT_NSPR_LIBS=@MOZ_COMPONENT_NSPR_LIBS@
+
+MOZ_FIX_LINK_PATHS=@MOZ_FIX_LINK_PATHS@
+
+XPCOM_FROZEN_LDOPTS=@XPCOM_FROZEN_LDOPTS@
+XPCOM_LIBS=@XPCOM_LIBS@
+MOZ_TIMELINE=@MOZ_TIMELINE@
+
+ENABLE_STRIP = @ENABLE_STRIP@
+PKG_SKIP_STRIP = @PKG_SKIP_STRIP@
+
+MOZ_POST_DSO_LIB_COMMAND = @MOZ_POST_DSO_LIB_COMMAND@
+MOZ_POST_PROGRAM_COMMAND = @MOZ_POST_PROGRAM_COMMAND@
+
+MOZ_BUILD_ROOT = @MOZ_BUILD_ROOT@
+
+MOZ_INSURE = @MOZ_INSURE@
+MOZ_INSURIFYING = @MOZ_INSURIFYING@
+MOZ_INSURE_DIRS = @MOZ_INSURE_DIRS@
+MOZ_INSURE_EXCLUDE_DIRS = @MOZ_INSURE_EXCLUDE_DIRS@
+
+MOZ_NATIVE_NSPR = @MOZ_NATIVE_NSPR@
+
+CROSS_COMPILE = @CROSS_COMPILE@
+
+WCHAR_CFLAGS = @WCHAR_CFLAGS@
+
+OS_CPPFLAGS = @CPPFLAGS@
+OS_CFLAGS = $(OS_CPPFLAGS) @CFLAGS@
+OS_CXXFLAGS = $(OS_CPPFLAGS) @CXXFLAGS@
+OS_LDFLAGS = @LDFLAGS@
+
+OS_COMPILE_CFLAGS = $(OS_CPPFLAGS) @COMPILE_CFLAGS@
+OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) @COMPILE_CXXFLAGS@
+
+OS_INCLUDES = $(NSPR_CFLAGS)
+OS_LIBS = @LIBS@
+ACDEFINES = @MOZ_DEFINES@
+
+WARNINGS_AS_ERRORS = @WARNINGS_AS_ERRORS@
+
+MOZ_OPTIMIZE = @MOZ_OPTIMIZE@
+MOZ_OPTIMIZE_FLAGS = @MOZ_OPTIMIZE_FLAGS@
+MOZ_OPTIMIZE_LDFLAGS = @MOZ_OPTIMIZE_LDFLAGS@
+MOZ_OPTIMIZE_SIZE_TWEAK = @MOZ_OPTIMIZE_SIZE_TWEAK@
+
+MOZ_RTTI_FLAGS_ON = @_MOZ_RTTI_FLAGS_ON@
+
+MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE = @MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE@
+PROFILE_GEN_CFLAGS = @PROFILE_GEN_CFLAGS@
+PROFILE_GEN_LDFLAGS = @PROFILE_GEN_LDFLAGS@
+PROFILE_USE_CFLAGS = @PROFILE_USE_CFLAGS@
+PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLAGS@
+
+WIN_TOP_SRC = @WIN_TOP_SRC@
+CYGWIN_WRAPPER = @CYGWIN_WRAPPER@
+AS_PERL = @AS_PERL@
+CYGDRIVE_MOUNT = @CYGDRIVE_MOUNT@
+AR = @AR@
+AR_FLAGS = @AR_FLAGS@
+AR_EXTRACT = @AR_EXTRACT@
+AR_LIST = @AR_LIST@
+AR_DELETE = @AR_DELETE@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AS_DASH_C_FLAG = @AS_DASH_C_FLAG@
+LD = @LD@
+RC = @RC@
+RCFLAGS = @RCFLAGS@
+WINDRES = @WINDRES@
+USE_SHORT_LIBNAME = @USE_SHORT_LIBNAME@
+IMPLIB = @IMPLIB@
+FILTER = @FILTER@
+BIN_FLAGS = @BIN_FLAGS@
+MIDL = @MIDL@
+MIDL_FLAGS = @MIDL_FLAGS@
+_MSC_VER = @_MSC_VER@
+
+DLL_PREFIX = @DLL_PREFIX@
+LIB_PREFIX = @LIB_PREFIX@
+OBJ_SUFFIX = @OBJ_SUFFIX@
+LIB_SUFFIX = @LIB_SUFFIX@
+DLL_SUFFIX = @DLL_SUFFIX@
+BIN_SUFFIX = @BIN_SUFFIX@
+ASM_SUFFIX = @ASM_SUFFIX@
+IMPORT_LIB_SUFFIX = @IMPORT_LIB_SUFFIX@
+USE_N32 = @USE_N32@
+HAVE_64BIT_OS = @HAVE_64BIT_OS@
+
+# Temp hack. It is not my intention to leave this crap in here for ever.
+# Im talking to fur right now to solve the problem without introducing
+# NS_USE_NATIVE to the build system -ramiro.
+NS_USE_NATIVE = @NS_USE_NATIVE@
+
+CC = @CC@
+CXX = @CXX@
+
+CC_VERSION = @CC_VERSION@
+CXX_VERSION = @CXX_VERSION@
+
+GNU_AS = @GNU_AS@
+GNU_LD = @GNU_LD@
+GNU_CC = @GNU_CC@
+GNU_CXX = @GNU_CXX@
+HAVE_GCC3_ABI = @HAVE_GCC3_ABI@
+INTEL_CC = @INTEL_CC@
+INTEL_CXX = @INTEL_CXX@
+
+HOST_CC = @HOST_CC@
+HOST_CXX = @HOST_CXX@
+HOST_CFLAGS = @HOST_CFLAGS@
+HOST_CXXFLAGS = @HOST_CXXFLAGS@
+HOST_OPTIMIZE_FLAGS = @HOST_OPTIMIZE_FLAGS@
+HOST_NSPR_MDCPUCFG = @HOST_NSPR_MDCPUCFG@
+HOST_AR = @HOST_AR@
+HOST_AR_FLAGS = @HOST_AR_FLAGS@
+HOST_LD = @HOST_LD@
+HOST_RANLIB = @HOST_RANLIB@
+HOST_BIN_SUFFIX = @HOST_BIN_SUFFIX@
+
+HOST_OS_ARCH = @HOST_OS_ARCH@
+host_cpu = @host_cpu@
+host_vendor = @host_vendor@
+host_os = @host_os@
+
+TARGET_NSPR_MDCPUCFG = @TARGET_NSPR_MDCPUCFG@
+TARGET_CPU = @TARGET_CPU@
+TARGET_VENDOR = @TARGET_VENDOR@
+TARGET_OS = @TARGET_OS@
+TARGET_MD_ARCH = @TARGET_MD_ARCH@
+TARGET_XPCOM_ABI = @TARGET_XPCOM_ABI@
+
+AUTOCONF = @AUTOCONF@
+PERL = @PERL@
+PYTHON = @PYTHON@
+RANLIB = @RANLIB@
+WHOAMI = @WHOAMI@
+UNZIP = @UNZIP@
+ZIP = @ZIP@
+XARGS = @XARGS@
+STRIP = @STRIP@
+DOXYGEN = @DOXYGEN@
+MAKE = @MAKE@
+PBBUILD_BIN = @PBBUILD@
+SDP = @SDP@
+NSINSTALL_BIN = @NSINSTALL_BIN@
+
+NSPR_CONFIG = @NSPR_CONFIG@
+NSPR_CFLAGS = @NSPR_CFLAGS@
+NSPR_LIBS = @NSPR_LIBS@
+
+USE_DEPENDENT_LIBS = @USE_DEPENDENT_LIBS@
+
+# MKSHLIB_FORCE_ALL is used to force the linker to include all object
+# files present in an archive. MKSHLIB_UNFORCE_ALL reverts the linker
+# to normal behavior. Makefile's that create shared libraries out of
+# archives use these flags to force in all of the .o files in the
+# archives into the shared library.
+WRAP_MALLOC_LIB = @WRAP_MALLOC_LIB@
+WRAP_MALLOC_CFLAGS = @WRAP_MALLOC_CFLAGS@
+DSO_CFLAGS = @DSO_CFLAGS@
+DSO_PIC_CFLAGS = @DSO_PIC_CFLAGS@
+MKSHLIB = @MKSHLIB@
+MKCSHLIB = @MKCSHLIB@
+MKSHLIB_FORCE_ALL = @MKSHLIB_FORCE_ALL@
+MKSHLIB_UNFORCE_ALL = @MKSHLIB_UNFORCE_ALL@
+DSO_LDOPTS = @DSO_LDOPTS@
+DLL_SUFFIX = @DLL_SUFFIX@
+
+NO_LD_ARCHIVE_FLAGS = @NO_LD_ARCHIVE_FLAGS@
+
+MOZ_TOOLKIT_REGISTRY_CFLAGS = \
+ $(TK_CFLAGS)
+
+MOZ_NATIVE_MAKEDEPEND = @SYSTEM_MAKEDEPEND@
+
+# Used for LD_LIBRARY_PATH
+LIBS_PATH = @LIBS_PATH@
+
+MOZ_AUTO_DEPS = @MOZ_AUTO_DEPS@
+COMPILER_DEPEND = @COMPILER_DEPEND@
+MDDEPDIR := @MDDEPDIR@
+
+MOZ_DEMANGLE_SYMBOLS = @MOZ_DEMANGLE_SYMBOLS@
+
+# XXX - these need to be cleaned up and have real checks added -cls
+CM_BLDTYPE=dbg
+AWT_11=1
+MOZ_BITS=32
+OS_TARGET=@OS_TARGET@
+OS_ARCH=@OS_ARCH@
+OS_RELEASE=@OS_RELEASE@
+OS_TEST=@OS_TEST@
+
+TARGET_DEVICE = @TARGET_DEVICE@
+
+# For AIX build
+AIX_OBJMODEL = @AIX_OBJMODEL@
+
+# For OS/2 build
+MOZ_OS2_TOOLS = @MOZ_OS2_TOOLS@
+MOZ_OS2_USE_DECLSPEC = @MOZ_OS2_USE_DECLSPEC@
+MOZ_OS2_HIGH_MEMORY = @MOZ_OS2_HIGH_MEMORY@
+
+MOZILLA_OFFICIAL = @MOZILLA_OFFICIAL@
+BUILD_OFFICIAL = @BUILD_OFFICIAL@
+MOZ_MILESTONE_RELEASE = @MOZ_MILESTONE_RELEASE@
+
+# Win32 options
+MOZ_PROFILE = @MOZ_PROFILE@
+MOZ_BROWSE_INFO = @MOZ_BROWSE_INFO@
+MOZ_TOOLS_DIR = @MOZ_TOOLS_DIR@
+MOZ_DEBUG_SYMBOLS = @MOZ_DEBUG_SYMBOLS@
+MOZ_QUANTIFY = @MOZ_QUANTIFY@
+MSMANIFEST_TOOL = @MSMANIFEST_TOOL@
+WIN32_REDIST_DIR = @WIN32_REDIST_DIR@
+WIN32_CRT_SRC_DIR = @WIN32_CRT_SRC_DIR@
+WIN32_CUSTOM_CRT_DIR = @WIN32_CUSTOM_CRT_DIR@
+
+# Codesighs tools option, enables win32 mapfiles.
+MOZ_MAPINFO = @MOZ_MAPINFO@
+
+WINCE = @WINCE@
+
+MACOS_SDK_DIR = @MACOS_SDK_DIR@
+NEXT_ROOT = @NEXT_ROOT@
+GCC_VERSION = @GCC_VERSION@
+XCODEBUILD_VERSION= @XCODEBUILD_VERSION@
+HAS_XCODE_2_1 = @HAS_XCODE_2_1@
+UNIVERSAL_BINARY= @UNIVERSAL_BINARY@
+HAVE_DTRACE= @HAVE_DTRACE@
+
+VISIBILITY_FLAGS = @VISIBILITY_FLAGS@
+WRAP_SYSTEM_INCLUDES = @WRAP_SYSTEM_INCLUDES@
+
+HAVE_ARM_SIMD= @HAVE_ARM_SIMD@
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py
new file mode 100644
index 0000000..916696e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-dirs.py
@@ -0,0 +1,108 @@
+# check-sync-dirs.py --- check that one directory is an exact subset of another
+#
+# Usage: python check-sync-dirs.py COPY ORIGINAL
+#
+# Check that the files present in the directory tree COPY are exact
+# copies of their counterparts in the directory tree ORIGINAL. COPY
+# need not have all the files in ORIGINAL, but COPY may not have files
+# absent from ORIGINAL.
+#
+# Each directory in COPY may have a file named
+# 'check-sync-exceptions', which lists files in COPY that need not be
+# the same as the corresponding file in ORIGINAL, or exist at all in
+# ORIGINAL. (The 'check-sync-exceptions' file itself is always
+# treated as exceptional.) Blank lines and '#' comments in the file
+# are ignored.
+
+import sys
+import os
+from os.path import join
+import filecmp
+import textwrap
+import fnmatch
+
+if len(sys.argv) != 3:
+ print >> sys.stderr, "Usage: %s COPY ORIGINAL" % sys.argv[0]
+ sys.exit(1)
+
+copy = sys.argv[1]
+original = sys.argv[2]
+
+# Ignore detritus left lying around by editing tools.
+ignored_patterns = ['*~', '.#*', '#*#', '*.orig', '*.rej']
+
+# Return the contents of FILENAME, a 'check-sync-exceptions' file, as
+# a dictionary whose keys are exactly the list of filenames, along
+# with the basename of FILENAME itself. If FILENAME does not exist,
+# return the empty dictionary.
+def read_exceptions(filename):
+ if (os.path.exists(filename)):
+ f = file(filename)
+ exceptions={}
+ for line in f:
+ line = line.strip()
+ if line != '' and line[0] != '#':
+ exceptions[line] = None
+ exceptions[os.path.basename (filename)] = None
+ f.close()
+ return exceptions
+ else:
+ return {}
+
+# Return true if FILENAME matches any pattern in the list of filename
+# patterns PATTERNS.
+def fnmatch_any(filename, patterns):
+ for pattern in patterns:
+ if fnmatch.fnmatch(filename, pattern):
+ return True
+ return False
+
+# Check the contents of the directory tree COPY against ORIGINAL. For each
+# file that differs, apply REPORT to COPY, ORIGINAL, and the file's
+# relative path. COPY and ORIGINAL should be absolute. Ignore files
+# that match patterns given in the list IGNORE.
+def check(copy, original, ignore, report):
+ os.chdir(copy)
+ for (dirpath, dirnames, filenames) in os.walk('.'):
+ exceptions = read_exceptions(join(dirpath, 'check-sync-exceptions'))
+ for filename in filenames:
+ if filename in exceptions:
+ continue
+ if fnmatch_any(filename, ignore):
+ continue
+ relative_name = join(dirpath, filename)
+ original_name = join(original, relative_name)
+ if (os.path.exists(original_name)
+ and filecmp.cmp(relative_name, original_name)):
+ continue
+ report(copy, original, relative_name)
+
+
+differences_found = False
+
+# Print an error message for DIFFERING, which was found to differ
+# between COPY and ORIGINAL. Set the global variable differences_found.
+def report(copy, original, differing):
+ global differences_found
+ if not differences_found:
+ print >> sys.stderr, "TEST-FAIL | build file copies are not in sync"
+ print >> sys.stderr, "file(s) found in: %s" % (copy)
+ print >> sys.stderr, ("differ from their originals in: %s"
+ % (original))
+ print >> sys.stderr, "file differs: %s" % (differing)
+ differences_found = True
+
+check(os.path.abspath(copy),
+ os.path.abspath(original),
+ ignored_patterns,
+ report)
+
+if differences_found:
+ msg=('''In general, the files in '%s' should always be exact copies of
+originals in '%s'. A change made to one should also be made to the
+other. See 'check-sync-dirs.py' for more details.'''
+ % (copy, original))
+ print >> sys.stderr, textwrap.fill(msg, 75)
+ sys.exit(1)
+
+sys.exit(0)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions
new file mode 100644
index 0000000..7c0bc47
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/check-sync-exceptions
@@ -0,0 +1,6 @@
+Makefile.in
+autoconf.mk.in
+check-sync-dirs.py
+
+# This is a copy of nspr's config/make-system-wrappers.pl.
+make-system-wrappers.pl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/config.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/config.mk
new file mode 100644
index 0000000..d19ca4a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/config.mk
@@ -0,0 +1,884 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Benjamin Smedberg <benjamin@smedbergs.us>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# config.mk
+#
+# Determines the platform and builds the macros needed to load the
+# appropriate platform-specific .mk file, then defines all (most?)
+# of the generic macros.
+#
+
+# Define an include-at-most-once flag
+INCLUDED_CONFIG_MK = 1
+
+EXIT_ON_ERROR = set -e; # Shell loops continue past errors without this.
+
+ifndef topsrcdir
+topsrcdir = $(DEPTH)
+endif
+
+ifndef INCLUDED_AUTOCONF_MK
+include $(DEPTH)/config/autoconf.mk
+endif
+ifndef INCLUDED_INSURE_MK
+ifdef MOZ_INSURIFYING
+include $(topsrcdir)/config/insure.mk
+endif
+endif
+
+COMMA = ,
+
+# Sanity check some variables
+CHECK_VARS := \
+ XPI_NAME \
+ LIBRARY_NAME \
+ MODULE \
+ DEPTH \
+ SHORT_LIBNAME \
+ XPI_PKGNAME \
+ INSTALL_EXTENSION_ID \
+ $(NULL)
+
+# checks for internal spaces or trailing spaces in the variable
+# named by $x
+check-variable = $(if $(filter-out 0 1,$(words $($(x))z)),$(error Spaces are not allowed in $(x)))
+
+$(foreach x,$(CHECK_VARS),$(check-variable))
+
+# FINAL_TARGET specifies the location into which we copy end-user-shipped
+# build products (typelibs, components, chrome).
+#
+# It will usually be the well-loved $(DIST)/bin, today, but can also be an
+# XPI-contents staging directory for ambitious and right-thinking extensions.
+FINAL_TARGET = $(if $(XPI_NAME),$(DIST)/xpi-stage/$(XPI_NAME),$(DIST)/bin)
+
+# MAKE_JARS_TARGET is a staging area for make-jars.pl. When packaging in
+# the jar format, make-jars leaves behind a directory structure that's not
+# needed in $(FINAL_TARGET). For both, flat, and symlink, the directory
+# structure contains the chrome, so leave it in $(FINAL_TARGET).
+ifeq (jar,$(MOZ_CHROME_FILE_FORMAT))
+MAKE_JARS_TARGET = $(if $(XPI_NAME),$(FINAL_TARGET).stage,$(DIST)/chrome-stage)
+else
+MAKE_JARS_TARGET = $(FINAL_TARGET)
+endif
+
+#
+# The VERSION_NUMBER is suffixed onto the end of the DLLs we ship.
+# Since the longest of these is 5 characters without the suffix,
+# be sure to not set VERSION_NUMBER to anything longer than 3
+# characters for Win16's sake.
+#
+VERSION_NUMBER = 50
+
+ifeq ($(HOST_OS_ARCH),WINNT)
+win_srcdir := $(subst $(topsrcdir),$(WIN_TOP_SRC),$(srcdir))
+BUILD_TOOLS = $(WIN_TOP_SRC)/build/unix
+else
+win_srcdir := $(srcdir)
+BUILD_TOOLS = $(topsrcdir)/build/unix
+endif
+
+CONFIG_TOOLS = $(MOZ_BUILD_ROOT)/config
+AUTOCONF_TOOLS = $(topsrcdir)/build/autoconf
+
+ifeq ($(OS_ARCH),QNX)
+ifeq ($(OS_TARGET),NTO)
+LD := qcc -Vgcc_ntox86 -nostdlib
+else
+LD := $(CC)
+endif
+endif
+ifeq ($(OS_ARCH),BeOS)
+BEOS_ADDON_WORKAROUND = 1
+endif
+
+#
+# Strip off the excessively long version numbers on these platforms,
+# but save the version to allow multiple versions of the same base
+# platform to be built in the same tree.
+#
+ifneq (,$(filter FreeBSD HP-UX IRIX Linux NetBSD OpenBSD OSF1 SunOS,$(OS_ARCH)))
+OS_RELEASE := $(basename $(OS_RELEASE))
+
+# Allow the user to ignore the OS_VERSION, which is usually irrelevant.
+ifdef WANT_MOZILLA_CONFIG_OS_VERSION
+OS_VERS := $(suffix $(OS_RELEASE))
+OS_VERSION := $(shell echo $(OS_VERS) | sed 's/-.*//')
+endif
+
+endif
+
+OS_CONFIG := $(OS_ARCH)$(OS_RELEASE)
+
+FINAL_LINK_LIBS = $(DEPTH)/config/final-link-libs
+FINAL_LINK_COMPS = $(DEPTH)/config/final-link-comps
+FINAL_LINK_COMP_NAMES = $(DEPTH)/config/final-link-comp-names
+
+MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
+MOZ_WIDGET_SUPPORT_LIBS = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
+
+ifdef MOZ_MEMORY
+ifneq ($(OS_ARCH),WINNT)
+JEMALLOC_LIBS = $(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME,jemalloc) $(MKSHLIB_UNFORCE_ALL)
+endif
+endif
+
+# determine debug-related options
+_DEBUG_CFLAGS :=
+_DEBUG_LDFLAGS :=
+
+ifndef MOZ_DEBUG
+ # global debugging is disabled
+ # check if it was explicitly enabled for this module
+ ifneq (, $(findstring $(MODULE), $(MOZ_DEBUG_MODULES)))
+ MOZ_DEBUG:=1
+ endif
+else
+ # global debugging is enabled
+ # check if it was explicitly disabled for this module
+ ifneq (, $(findstring ^$(MODULE), $(MOZ_DEBUG_MODULES)))
+ MOZ_DEBUG:=
+ endif
+endif
+
+ifdef MOZ_DEBUG
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_ENABLE_DEFS)
+ XULPPFLAGS += $(MOZ_DEBUG_ENABLE_DEFS)
+else
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_DISABLE_DEFS)
+ XULPPFLAGS += $(MOZ_DEBUG_DISABLE_DEFS)
+endif
+
+# determine if -g should be passed to the compiler, based on
+# the current module, and the value of MOZ_DBGRINFO_MODULES
+
+ifdef MOZ_DEBUG
+ MOZ_DBGRINFO_MODULES += ALL_MODULES
+ pattern := ALL_MODULES ^ALL_MODULES
+else
+ MOZ_DBGRINFO_MODULES += ^ALL_MODULES
+ pattern := ALL_MODULES ^ALL_MODULES
+endif
+
+ifdef MODULE
+ # our current Makefile specifies a module name - add it to our pattern
+ pattern += $(MODULE) ^$(MODULE)
+endif
+
+# start by finding the first relevant module name
+# (remember that the order of the module names in MOZ_DBGRINFO_MODULES
+# is reversed from the order the user specified to configure -
+# this allows the user to put general names at the beginning
+# of the list, and to override them with explicit module names later
+# in the list)
+
+first_match:=$(firstword $(filter $(pattern), $(MOZ_DBGRINFO_MODULES)))
+
+ifeq ($(first_match), $(MODULE))
+ # the user specified explicitly that
+ # this module should be compiled with -g
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_FLAGS)
+ _DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
+else
+ ifeq ($(first_match), ^$(MODULE))
+ # the user specified explicitly that this module
+ # should not be compiled with -g (nothing to do)
+ else
+ ifeq ($(first_match), ALL_MODULES)
+ # the user didn't mention this module explicitly,
+ # but wanted all modules to be compiled with -g
+ _DEBUG_CFLAGS += $(MOZ_DEBUG_FLAGS)
+ _DEBUG_LDFLAGS += $(MOZ_DEBUG_LDFLAGS)
+ else
+ ifeq ($(first_match), ^ALL_MODULES)
+ # the user didn't mention this module explicitly,
+ # but wanted all modules to be compiled without -g (nothing to do)
+ endif
+ endif
+ endif
+endif
+
+
+# append debug flags
+# (these might have been above when processing MOZ_DBGRINFO_MODULES)
+OS_CFLAGS += $(_DEBUG_CFLAGS)
+OS_CXXFLAGS += $(_DEBUG_CFLAGS)
+OS_LDFLAGS += $(_DEBUG_LDFLAGS)
+
+# MOZ_PROFILE equivs for win32
+ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
+ifdef MOZ_DEBUG
+ifneq (,$(MOZ_BROWSE_INFO)$(MOZ_BSCFILE))
+OS_CFLAGS += -FR
+OS_CXXFLAGS += -FR
+endif
+else # ! MOZ_DEBUG
+
+# MOZ_DEBUG_SYMBOLS generates debug symbols in separate PDB files.
+# Used for generating an optimized build with debugging symbols.
+# Used in the Windows nightlies to generate symbols for crash reporting.
+ifdef MOZ_DEBUG_SYMBOLS
+OS_CXXFLAGS += -Zi -UDEBUG -DNDEBUG
+OS_CFLAGS += -Zi -UDEBUG -DNDEBUG
+OS_LDFLAGS += -DEBUG -OPT:REF -OPT:nowin98
+endif
+
+ifdef MOZ_QUANTIFY
+# -FIXED:NO is needed for Quantify to work, but it increases the size
+# of executables, so only use it if building for Quantify.
+WIN32_EXE_LDFLAGS += -FIXED:NO
+
+# We need -OPT:NOICF to prevent identical methods from being merged together.
+# Otherwise, Quantify doesn't know which method was actually called when it's
+# showing you the profile.
+OS_LDFLAGS += -OPT:NOICF
+endif
+
+#
+# Handle trace-malloc in optimized builds.
+# No opt to give sane callstacks.
+#
+ifdef NS_TRACE_MALLOC
+MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
+OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF -OPT:nowin98
+endif # NS_TRACE_MALLOC
+
+endif # MOZ_DEBUG
+endif # WINNT && !GNU_CC
+
+#
+# Build using PIC by default
+# Do not use PIC if not building a shared lib (see exceptions below)
+#
+
+ifndef BUILD_STATIC_LIBS
+_ENABLE_PIC=1
+endif
+ifneq (,$(FORCE_SHARED_LIB)$(FORCE_USE_PIC))
+_ENABLE_PIC=1
+endif
+
+# In Firefox, all components are linked into either libxul or the static
+# meta-component, and should be compiled with PIC.
+ifdef MOZ_META_COMPONENT
+_ENABLE_PIC=1
+endif
+
+# If module is going to be merged into the nsStaticModule,
+# make sure that the entry points are translated and
+# the module is built static.
+
+ifdef IS_COMPONENT
+ifdef EXPORT_LIBRARY
+ifneq (,$(BUILD_STATIC_LIBS))
+ifdef MODULE_NAME
+DEFINES += -DXPCOM_TRANSLATE_NSGM_ENTRY_POINT=1
+FORCE_STATIC_LIB=1
+endif
+endif
+endif
+endif
+
+# Determine if module being compiled is destined
+# to be merged into libxul
+
+ifdef MOZ_ENABLE_LIBXUL
+ifdef LIBXUL_LIBRARY
+ifdef IS_COMPONENT
+ifdef MODULE_NAME
+DEFINES += -DXPCOM_TRANSLATE_NSGM_ENTRY_POINT=1
+else
+$(error Component makefile does not specify MODULE_NAME.)
+endif
+endif
+FORCE_STATIC_LIB=1
+_ENABLE_PIC=1
+SHORT_LIBNAME=
+endif
+endif
+
+# If we are building this component into an extension/xulapp, it cannot be
+# statically linked. In the future we may want to add a xulapp meta-component
+# build option.
+
+ifdef XPI_NAME
+_ENABLE_PIC=1
+ifdef IS_COMPONENT
+EXPORT_LIBRARY=
+FORCE_STATIC_LIB=
+FORCE_SHARED_LIB=1
+endif
+endif
+
+#
+# Disable PIC if necessary
+#
+
+ifndef _ENABLE_PIC
+DSO_CFLAGS=
+ifeq ($(OS_ARCH)_$(HAVE_GCC3_ABI),Darwin_1)
+DSO_PIC_CFLAGS=-mdynamic-no-pic
+else
+DSO_PIC_CFLAGS=
+endif
+endif
+
+# This comes from configure
+ifdef MOZ_PROFILE_GUIDED_OPTIMIZE_DISABLE
+NO_PROFILE_GUIDED_OPTIMIZE = 1
+endif
+
+# Enable profile-based feedback
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+ifdef MOZ_PROFILE_GENERATE
+# No sense in profiling tools
+ifndef INTERNAL_TOOLS
+OS_CFLAGS += $(PROFILE_GEN_CFLAGS)
+OS_CXXFLAGS += $(PROFILE_GEN_CFLAGS)
+OS_LDFLAGS += $(PROFILE_GEN_LDFLAGS)
+ifeq (WINNT,$(OS_ARCH))
+AR_FLAGS += -LTCG
+endif
+endif # INTERNAL_TOOLS
+endif # MOZ_PROFILE_GENERATE
+
+ifdef MOZ_PROFILE_USE
+ifndef INTERNAL_TOOLS
+OS_CFLAGS += $(PROFILE_USE_CFLAGS)
+OS_CXXFLAGS += $(PROFILE_USE_CFLAGS)
+OS_LDFLAGS += $(PROFILE_USE_LDFLAGS)
+ifeq (WINNT,$(OS_ARCH))
+AR_FLAGS += -LTCG
+endif
+endif # INTERNAL_TOOLS
+endif # MOZ_PROFILE_USE
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+
+
+# Does the makefile specifies the internal XPCOM API linkage?
+ifneq (,$(MOZILLA_INTERNAL_API)$(LIBXUL_LIBRARY))
+DEFINES += -DMOZILLA_INTERNAL_API
+endif
+
+# Force XPCOM/widget/gfx methods to be _declspec(dllexport) when we're
+# building libxul libraries
+ifdef MOZ_ENABLE_LIBXUL
+ifdef LIBXUL_LIBRARY
+DEFINES += \
+ -D_IMPL_NS_COM \
+ -DEXPORT_XPT_API \
+ -DEXPORT_XPTC_API \
+ -D_IMPL_NS_COM_OBSOLETE \
+ -D_IMPL_NS_GFX \
+ -D_IMPL_NS_WIDGET \
+ -DIMPL_XREAPI \
+ -DIMPL_NS_NET \
+ -DIMPL_THEBES \
+ $(NULL)
+
+ifndef MOZ_NATIVE_ZLIB
+DEFINES += -DZLIB_INTERNAL
+endif
+endif
+endif
+
+# Force _all_ exported methods to be |_declspec(dllexport)| when we're
+# building them into the executable.
+
+ifeq (,$(filter-out WINNT WINCE OS2, $(OS_ARCH)))
+ifdef BUILD_STATIC_LIBS
+DEFINES += \
+ -D_IMPL_NS_GFX \
+ -D_IMPL_NS_MSG_BASE \
+ -D_IMPL_NS_WIDGET \
+ $(NULL)
+endif
+endif
+
+# Flags passed to make-jars.pl
+
+MAKE_JARS_FLAGS = \
+ -t $(topsrcdir) \
+ -f $(MOZ_CHROME_FILE_FORMAT) \
+ $(NULL)
+
+ifdef USE_EXTENSION_MANIFEST
+MAKE_JARS_FLAGS += -e
+endif
+
+ifdef BOTH_MANIFESTS
+MAKE_JARS_FLAGS += --both-manifests
+endif
+
+TAR_CREATE_FLAGS = -cvhf
+
+ifeq ($(OS_ARCH),BSD_OS)
+TAR_CREATE_FLAGS = -cvLf
+endif
+
+ifeq ($(OS_ARCH),OS2)
+TAR_CREATE_FLAGS = -cvf
+endif
+
+#
+# Personal makefile customizations go in these optional make include files.
+#
+MY_CONFIG := $(DEPTH)/config/myconfig.mk
+MY_RULES := $(DEPTH)/config/myrules.mk
+
+#
+# Default command macros; can be overridden in <arch>.mk.
+#
+CCC = $(CXX)
+NFSPWD = $(CONFIG_TOOLS)/nfspwd
+PURIFY = purify $(PURIFYOPTIONS)
+QUANTIFY = quantify $(QUANTIFYOPTIONS)
+ifdef CROSS_COMPILE
+XPIDL_COMPILE = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/host/bin/host_xpidl$(HOST_BIN_SUFFIX)
+XPIDL_LINK = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/host/bin/host_xpt_link$(HOST_BIN_SUFFIX)
+else
+XPIDL_COMPILE = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/bin/xpidl$(BIN_SUFFIX)
+XPIDL_LINK = $(CYGWIN_WRAPPER) $(LIBXUL_DIST)/bin/xpt_link$(BIN_SUFFIX)
+endif
+
+# Java macros
+JAVA_GEN_DIR = _javagen
+JAVA_DIST_DIR = $(DEPTH)/$(JAVA_GEN_DIR)
+JAVA_IFACES_PKG_NAME = org/mozilla/interfaces
+
+REQ_INCLUDES = -I$(srcdir) -I. $(foreach d,$(REQUIRES),-I$(DIST)/include/$d) -I$(DIST)/include
+ifdef LIBXUL_SDK
+REQ_INCLUDES_SDK = $(foreach d,$(REQUIRES),-I$(LIBXUL_SDK)/include/$d) -I$(LIBXUL_SDK)/include
+endif
+
+INCLUDES = $(LOCAL_INCLUDES) $(REQ_INCLUDES) $(REQ_INCLUDES_SDK) -I$(PUBLIC) $(OS_INCLUDES)
+
+ifndef MOZILLA_INTERNAL_API
+INCLUDES += -I$(LIBXUL_DIST)/sdk/include
+endif
+
+# The entire tree should be subject to static analysis using the XPCOM
+# script. Additional scripts may be added by specific subdirectories.
+
+DEHYDRA_SCRIPT = $(topsrcdir)/xpcom/analysis/static-checking.js
+
+DEHYDRA_MODULES = \
+ $(topsrcdir)/xpcom/analysis/final.js \
+ $(NULL)
+
+TREEHYDRA_MODULES = \
+ $(topsrcdir)/xpcom/analysis/outparams.js \
+ $(topsrcdir)/xpcom/analysis/stack.js \
+ $(topsrcdir)/xpcom/analysis/flow.js \
+ $(NULL)
+
+DEHYDRA_ARGS = \
+ --topsrcdir=$(topsrcdir) \
+ --objdir=$(DEPTH) \
+ --dehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(DEHYDRA_MODULES))) \
+ --treehydra-modules=$(subst $(NULL) ,$(COMMA),$(strip $(TREEHYDRA_MODULES))) \
+ $(NULL)
+
+DEHYDRA_FLAGS = -fplugin=$(DEHYDRA_PATH) -fplugin-arg='$(DEHYDRA_SCRIPT) $(DEHYDRA_ARGS)'
+
+ifdef DEHYDRA_PATH
+OS_CXXFLAGS += $(DEHYDRA_FLAGS)
+endif
+
+CFLAGS = $(OS_CFLAGS)
+CXXFLAGS = $(OS_CXXFLAGS)
+LDFLAGS = $(OS_LDFLAGS) $(MOZ_FIX_LINK_PATHS)
+
+# Allow each module to override the *default* optimization settings
+# by setting MODULE_OPTIMIZE_FLAGS if the developer has not given
+# arguments to --enable-optimize
+ifdef MOZ_OPTIMIZE
+ifeq (1,$(MOZ_OPTIMIZE))
+ifdef MODULE_OPTIMIZE_FLAGS
+CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MODULE_OPTIMIZE_FLAGS)
+else
+CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MODULE_OPTIMIZE_FLAGS
+else
+CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+CXXFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MOZ_OPTIMIZE == 1
+LDFLAGS += $(MOZ_OPTIMIZE_LDFLAGS)
+endif # MOZ_OPTIMIZE
+
+ifdef CROSS_COMPILE
+HOST_CFLAGS += $(HOST_OPTIMIZE_FLAGS)
+else
+ifdef MOZ_OPTIMIZE
+ifeq (1,$(MOZ_OPTIMIZE))
+ifdef MODULE_OPTIMIZE_FLAGS
+HOST_CFLAGS += $(MODULE_OPTIMIZE_FLAGS)
+else
+HOST_CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MODULE_OPTIMIZE_FLAGS
+else
+HOST_CFLAGS += $(MOZ_OPTIMIZE_FLAGS)
+endif # MOZ_OPTIMIZE == 1
+endif # MOZ_OPTIMIZE
+endif # CROSS_COMPILE
+
+
+ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
+#// Currently, unless USE_STATIC_LIBS is defined, the multithreaded
+#// DLL version of the RTL is used...
+#//
+#//------------------------------------------------------------------------
+ifdef USE_STATIC_LIBS
+RTL_FLAGS=-MT # Statically linked multithreaded RTL
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+ifndef MOZ_NO_DEBUG_RTL
+RTL_FLAGS=-MTd # Statically linked multithreaded MSVC4.0 debug RTL
+endif
+endif # MOZ_DEBUG || NS_TRACE_MALLOC
+
+else # !USE_STATIC_LIBS
+
+RTL_FLAGS=-MD # Dynamically linked, multithreaded RTL
+ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
+ifndef MOZ_NO_DEBUG_RTL
+RTL_FLAGS=-MDd # Dynamically linked, multithreaded MSVC4.0 debug RTL
+endif
+endif # MOZ_DEBUG || NS_TRACE_MALLOC
+endif # USE_STATIC_LIBS
+endif # WINNT && !GNU_CC
+
+ifeq ($(OS_ARCH),Darwin)
+# Darwin doesn't cross-compile, so just set both types of flags here.
+HOST_CMFLAGS += -fobjc-exceptions
+HOST_CMMFLAGS += -fobjc-exceptions
+OS_COMPILE_CMFLAGS += -fobjc-exceptions
+OS_COMPILE_CMMFLAGS += -fobjc-exceptions
+endif
+
+COMPILE_CFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(PROFILER_CFLAGS) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CFLAGS)
+COMPILE_CXXFLAGS = $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(XCFLAGS) $(PROFILER_CFLAGS) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(CXXFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CXXFLAGS)
+COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS)
+COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS)
+
+ifndef CROSS_COMPILE
+HOST_CFLAGS += $(RTL_FLAGS)
+endif
+
+#
+# Name of the binary code directories
+#
+# Override defaults
+
+# We need to know where to find the libraries we
+# put on the link line for binaries, and should
+# we link statically or dynamic? Assuming dynamic for now.
+
+ifneq (WINNT_,$(OS_ARCH)_$(GNU_CC))
+ifneq (,$(filter-out WINCE,$(OS_ARCH)))
+LIBS_DIR = -L$(DIST)/bin -L$(DIST)/lib
+ifdef LIBXUL_SDK
+LIBS_DIR += -L$(LIBXUL_SDK)/bin -L$(LIBXUL_SDK)/lib
+endif
+endif
+endif
+
+# Default location of include files
+IDL_DIR = $(DIST)/idl
+ifdef MODULE
+PUBLIC = $(DIST)/include/$(MODULE)
+else
+PUBLIC = $(DIST)/include
+endif
+
+XPIDL_FLAGS = -I$(srcdir) -I$(IDL_DIR)
+ifdef LIBXUL_SDK
+XPIDL_FLAGS += -I$(LIBXUL_SDK)/idl
+endif
+
+SDK_PUBLIC = $(DIST)/sdk/include
+SDK_IDL_DIR = $(DIST)/sdk/idl
+SDK_LIB_DIR = $(DIST)/sdk/lib
+SDK_BIN_DIR = $(DIST)/sdk/bin
+
+DEPENDENCIES = .md
+
+MOZ_COMPONENT_LIBS=$(XPCOM_LIBS) $(MOZ_COMPONENT_NSPR_LIBS)
+
+ifdef GC_LEAK_DETECTOR
+XPCOM_LIBS += -lboehm
+endif
+
+ifeq (xpconnect, $(findstring xpconnect, $(BUILD_MODULES)))
+DEFINES += -DXPCONNECT_STANDALONE
+endif
+
+ifeq ($(OS_ARCH),OS2)
+ELF_DYNSTR_GC = echo
+else
+ELF_DYNSTR_GC = :
+endif
+
+ifndef CROSS_COMPILE
+ifdef USE_ELF_DYNSTR_GC
+ifdef MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS
+ELF_DYNSTR_GC = $(DEPTH)/config/elf-dynstr-gc
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),Darwin)
+ifdef NEXT_ROOT
+export NEXT_ROOT
+PBBUILD = NEXT_ROOT= $(PBBUILD_BIN)
+else # NEXT_ROOT
+PBBUILD = $(PBBUILD_BIN)
+endif # NEXT_ROOT
+PBBUILD_SETTINGS = GCC_VERSION="$(GCC_VERSION)" SYMROOT=build ARCHS="$(OS_TEST)"
+ifdef MACOS_SDK_DIR
+PBBUILD_SETTINGS += SDKROOT="$(MACOS_SDK_DIR)"
+endif # MACOS_SDK_DIR
+ifdef MACOSX_DEPLOYMENT_TARGET
+export MACOSX_DEPLOYMENT_TARGET
+PBBUILD_SETTINGS += MACOSX_DEPLOYMENT_TARGET="$(MACOSX_DEPLOYMENT_TARGET)"
+endif # MACOSX_DEPLOYMENT_TARGET
+ifdef MOZ_OPTIMIZE
+ifeq (2,$(MOZ_OPTIMIZE))
+# Only override project defaults if the config specified explicit settings
+PBBUILD_SETTINGS += GCC_MODEL_TUNING= OPTIMIZATION_CFLAGS="$(MOZ_OPTIMIZE_FLAGS)"
+endif # MOZ_OPTIMIZE=2
+endif # MOZ_OPTIMIZE
+ifeq (1,$(HAS_XCODE_2_1))
+# Xcode 2.1 puts its build products in a directory corresponding to the
+# selected build style/configuration.
+XCODE_PRODUCT_DIR = build/$(BUILDSTYLE)
+else
+XCODE_PRODUCT_DIR = build
+endif # HAS_XCODE_2_1=1
+endif # OS_ARCH=Darwin
+
+
+ifdef MOZ_NATIVE_MAKEDEPEND
+MKDEPEND_DIR =
+MKDEPEND = $(CYGWIN_WRAPPER) $(MOZ_NATIVE_MAKEDEPEND)
+else
+MKDEPEND_DIR = $(CONFIG_TOOLS)/mkdepend
+MKDEPEND = $(CYGWIN_WRAPPER) $(MKDEPEND_DIR)/mkdepend$(BIN_SUFFIX)
+endif
+
+# Set link flags according to whether we want a console.
+ifdef MOZ_WINCONSOLE
+ifeq ($(MOZ_WINCONSOLE),1)
+ifeq ($(OS_ARCH),OS2)
+BIN_FLAGS += -Zlinker -PM:VIO
+endif
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+WIN32_EXE_LDFLAGS += -mconsole
+else
+WIN32_EXE_LDFLAGS += -SUBSYSTEM:CONSOLE
+endif
+endif
+else # MOZ_WINCONSOLE
+ifeq ($(OS_ARCH),OS2)
+BIN_FLAGS += -Zlinker -PM:PM
+endif
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+WIN32_EXE_LDFLAGS += -mwindows
+else
+WIN32_EXE_LDFLAGS += -SUBSYSTEM:WINDOWS
+endif
+endif
+endif
+endif
+
+# Flags needed to link against the component library
+ifdef MOZ_COMPONENTLIB
+MOZ_COMPONENTLIB_EXTRA_DSO_LIBS = mozcomps xpcom_compat
+
+# Tell the linker where NSS is, if we're building crypto
+ifeq ($(OS_ARCH),Darwin)
+ifeq (,$(findstring crypto,$(MOZ_META_COMPONENTS)))
+MOZ_COMPONENTLIB_EXTRA_LIBS = $(foreach library, $(patsubst -l%, $(LIB_PREFIX)%$(DLL_SUFFIX), $(filter -l%, $(NSS_LIBS))), -dylib_file @executable_path/$(library):$(DIST)/bin/$(library))
+endif
+endif
+endif
+
+# If we're building a component on MSVC, we don't want to generate an
+# import lib, because that import lib will collide with the name of a
+# static version of the same library.
+ifeq ($(GNU_LD)$(OS_ARCH),WINNT)
+ifdef IS_COMPONENT
+LDFLAGS += -IMPLIB:fake.lib
+DELETE_AFTER_LINK = fake.lib fake.exp
+endif
+endif
+
+#
+# Include any personal overrides the user might think are needed.
+#
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
+-include $(MY_CONFIG)
+
+######################################################################
+# Now test variables that might have been set or overridden by $(MY_CONFIG).
+
+DEFINES += -DOSTYPE=\"$(OS_CONFIG)\"
+DEFINES += -DOSARCH=$(OS_ARCH)
+
+# For profiling
+ifdef ENABLE_EAZEL_PROFILER
+ifndef INTERNAL_TOOLS
+ifneq ($(LIBRARY_NAME), xpt)
+ifneq (, $(findstring $(shell $(topsrcdir)/build/unix/print-depth-path.sh | awk -F/ '{ print $$2; }'), $(MOZ_PROFILE_MODULES)))
+PROFILER_CFLAGS = $(EAZEL_PROFILER_CFLAGS) -DENABLE_EAZEL_PROFILER
+PROFILER_LIBS = $(EAZEL_PROFILER_LIBS)
+endif
+endif
+endif
+endif
+
+######################################################################
+
+GARBAGE += $(DEPENDENCIES) $(MKDEPENDENCIES) $(MKDEPENDENCIES).bak core $(wildcard core.[0-9]*) $(wildcard *.err) $(wildcard *.pure) $(wildcard *_pure_*.o) Templates.DB
+
+ifeq ($(OS_ARCH),Darwin)
+ifndef NSDISTMODE
+NSDISTMODE=absolute_symlink
+endif
+PWD := $(shell pwd)
+endif
+
+ifdef NSINSTALL_BIN
+NSINSTALL = $(CYGWIN_WRAPPER) $(NSINSTALL_BIN)
+else
+ifeq (WINNT,$(CROSS_COMPILE)$(OS_ARCH))
+NSINSTALL = $(CYGWIN_WRAPPER) $(MOZ_TOOLS_DIR)/bin/nsinstall
+else
+ifeq (OS2,$(CROSS_COMPILE)$(OS_ARCH))
+NSINSTALL = $(MOZ_TOOLS_DIR)/nsinstall
+else
+NSINSTALL = $(CONFIG_TOOLS)/nsinstall
+endif # OS2
+endif # WINNT
+endif # NSINSTALL_BIN
+
+
+ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2, $(OS_ARCH)))
+INSTALL = $(NSINSTALL)
+else
+ifeq ($(NSDISTMODE),copy)
+# copy files, but preserve source mtime
+INSTALL = $(NSINSTALL) -t
+else
+ifeq ($(NSDISTMODE),absolute_symlink)
+# install using absolute symbolic links
+ifeq ($(OS_ARCH),Darwin)
+INSTALL = $(NSINSTALL) -L $(PWD)
+else
+INSTALL = $(NSINSTALL) -L `$(NFSPWD)`
+endif # Darwin
+else
+# install using relative symbolic links
+INSTALL = $(NSINSTALL) -R
+endif # absolute_symlink
+endif # copy
+endif # WINNT/OS2
+
+ifeq (,$(filter-out WINCE,$(OS_ARCH)))
+NSINSTALL = $(CYGWIN_WRAPPER) nsinstall
+INSTALL = $(CYGWIN_WRAPPER) nsinstall
+endif
+
+# Use nsinstall in copy mode to install files on the system
+SYSINSTALL = $(NSINSTALL) -t
+
+ifeq ($(OS_ARCH),WINNT)
+ifneq (,$(CYGDRIVE_MOUNT))
+export CYGDRIVE_MOUNT
+endif
+endif
+
+#
+# Localization build automation
+#
+
+# Because you might wish to "make locales AB_CD=ab-CD", we don't hardcode
+# MOZ_UI_LOCALE directly, but use an intermediate variable that can be
+# overridden by the command line. (Besides, AB_CD is prettier).
+AB_CD = $(MOZ_UI_LOCALE)
+
+ifndef L10NBASEDIR
+L10NBASEDIR = $(error L10NBASEDIR not defined by configure)
+endif
+
+EXPAND_LOCALE_SRCDIR = $(if $(filter en-US,$(AB_CD)),$(topsrcdir)/$(1)/en-US,$(L10NBASEDIR)/$(AB_CD)/$(subst /locales,,$(1)))
+
+ifdef relativesrcdir
+LOCALE_SRCDIR = $(call EXPAND_LOCALE_SRCDIR,$(relativesrcdir))
+endif
+
+ifdef LOCALE_SRCDIR
+# if LOCALE_MERGEDIR is set, use mergedir first, then the localization,
+# and finally en-US
+ifdef LOCALE_MERGEDIR
+MAKE_JARS_FLAGS += -c $(LOCALE_MERGEDIR)/$(subst /locales,,$(relativesrcdir))
+endif
+MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
+ifdef LOCALE_MERGEDIR
+MAKE_JARS_FLAGS += -c $(topsrcdir)/$(relativesrcdir)/en-US
+endif
+endif
+
+ifeq (,$(filter WINCE WINNT OS2,$(OS_ARCH)))
+RUN_TEST_PROGRAM = $(DIST)/bin/run-mozilla.sh
+endif
+
+#
+# Java macros
+#
+
+# Make sure any compiled classes work with at least JVM 1.4
+JAVAC_FLAGS += -source 1.4
+
+ifdef MOZ_DEBUG
+JAVAC_FLAGS += -g
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl
new file mode 100644
index 0000000..c327ccf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/fastcwd.pl
@@ -0,0 +1,66 @@
+#!perl5
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+sub fastcwd {
+ local($odev, $oino, $cdev, $cino, $tdev, $tino);
+ local(@path, $path);
+ local(*DIR);
+
+ ($cdev, $cino) = stat('.');
+ for (;;) {
+ ($odev, $oino) = ($cdev, $cino);
+ chdir('..');
+ ($cdev, $cino) = stat('.');
+ last if $odev == $cdev && $oino == $cino;
+ opendir(DIR, '.');
+ for (;;) {
+ $_ = readdir(DIR);
+ next if $_ eq '.';
+ next if $_ eq '..';
+
+ last unless $_;
+ ($tdev, $tino) = lstat($_);
+ last unless $tdev != $odev || $tino != $oino;
+ }
+ closedir(DIR);
+ unshift(@path, $_);
+ }
+ chdir($path = '/' . join('/', @path));
+ $path;
+}
+1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h b/tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h
new file mode 100644
index 0000000..58140c1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/gcc_hidden.h
@@ -0,0 +1,2 @@
+/* Begin all files as hidden visibility */
+#pragma GCC visibility push(hidden)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk
new file mode 100644
index 0000000..fc796eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/insure.mk
@@ -0,0 +1,53 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+INCLUDED_INSURE_MK = 1
+
+INSURE_MATCH_SCRIPT=$(topsrcdir)/build/autoconf/match-dir.sh
+
+INSURE_EXCLUDE=$(shell $(INSURE_MATCH_SCRIPT) $(MOZ_INSURE_EXCLUDE_DIRS))
+
+INSURE_INCLUDE=$(shell $(INSURE_MATCH_SCRIPT) $(MOZ_INSURE_DIRS))
+
+ifeq ($(INSURE_EXCLUDE),0)
+
+ifeq ($(INSURE_INCLUDE),1)
+CC := $(MOZ_INSURE)
+CXX := $(MOZ_INSURE)
+endif # INSURE_INCLUDE == 1
+
+endif # INSURE_EXCLUDE == 0
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl
new file mode 100644
index 0000000..31c9af4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/make-system-wrappers.pl
@@ -0,0 +1,59 @@
+#!/usr/bin/perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# IBM Corporation.
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Brian Ryner <bryner@brianryner.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+$output_dir = shift;
+
+while (<STDIN>) {
+ chomp;
+ if (-e "$output_dir/$_") {
+ next;
+ }
+
+ if (/(.*)\/[^\/*]/) {
+ mkdir "$output_dir/$1";
+ }
+
+ open OUT, ">$output_dir/$_";
+ print OUT "#pragma GCC system_header\n"; # suppress include_next warning
+ print OUT "#pragma GCC visibility push(default)\n";
+ print OUT "#include_next \<$_\>\n";
+ print OUT "#pragma GCC visibility pop\n";
+ close OUT;
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl
new file mode 100644
index 0000000..e3cee2a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.pl
@@ -0,0 +1,112 @@
+#!/usr/bin/perl -w
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Netscape Communications Corporation
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+use Getopt::Long;
+
+use strict;
+use vars qw(
+ $OBJDIR
+ $SRCDIR
+ $TOPSRCDIR
+ $SCRIPTDIR
+ @TEMPLATE_FILE
+ $MILESTONE_FILE
+ $MILESTONE
+ $MILESTONE_NUM
+ @MILESTONE_PARTS
+ $MINI_VERSION
+ $MICRO_VERSION
+ $opt_debug
+ $opt_template
+ $opt_help
+ );
+
+$SCRIPTDIR = $0;
+$SCRIPTDIR =~ s/[^\/]*$//;
+push(@INC,$SCRIPTDIR);
+
+require "Moz/Milestone.pm";
+
+&GetOptions('topsrcdir=s' => \$TOPSRCDIR, 'srcdir=s' => \$SRCDIR, 'objdir=s' => \$OBJDIR, 'debug', 'help', 'template');
+
+if (defined($opt_help)) {
+ &usage();
+ exit;
+}
+
+if (defined($opt_template)) {
+ @TEMPLATE_FILE = @ARGV;
+ if ($opt_debug) {
+ print("TEMPLATE_FILE = --@TEMPLATE_FILE--\n");
+ }
+}
+
+if (!defined($SRCDIR)) { $SRCDIR = '.'; }
+if (!defined($OBJDIR)) { $OBJDIR = '.'; }
+
+$MILESTONE_FILE = "$TOPSRCDIR/config/milestone.txt";
+@MILESTONE_PARTS = (0, 0, 0, 0);
+
+#
+# Grab milestone (top line of $MILESTONE_FILE that starts with a digit)
+#
+my $milestone = Moz::Milestone::getOfficialMilestone($MILESTONE_FILE);
+
+if (defined(@TEMPLATE_FILE)) {
+ my $TFILE;
+
+ foreach $TFILE (@TEMPLATE_FILE) {
+ my $BUILT_FILE = "$OBJDIR/$TFILE";
+ $TFILE = "$SRCDIR/$TFILE.tmpl";
+
+ if (-e $TFILE) {
+
+ Moz::Milestone::build_file($TFILE,$BUILT_FILE);
+
+ } else {
+ warn("$0: No such file $TFILE!\n");
+ }
+ }
+} else {
+ print "$milestone\n";
+}
+
+sub usage() {
+ print <<END
+`milestone.pl [--topsrcdir TOPSRCDIR] [--objdir OBJDIR] [--srcdir SRCDIR] --template [file list]` # will build file list from .tmpl files
+END
+ ;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt
new file mode 100644
index 0000000..f3b9fdf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/milestone.txt
@@ -0,0 +1,13 @@
+# Holds the current milestone.
+# Should be in the format of
+#
+# x.x.x
+# x.x.x.x
+# x.x.x+
+#
+# Referenced by milestone.pl.
+# Hopefully I'll be able to automate replacement of *all*
+# hardcoded milestones in the tree from these two files.
+#--------------------------------------------------------
+
+1.9.1b2
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in
new file mode 100644
index 0000000..2e0fc2a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/Makefile.in
@@ -0,0 +1,84 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+# undefine (as best we can, thanks gmake!) so we don't need build_number
+MOZILLA_OFFICIAL =
+BUILD_OFFICIAL =
+MODULE = mkdepend
+HOST_PROGRAM = mkdepend$(BIN_SUFFIX)
+ifdef GNU_CC
+MODULE_OPTIMIZE_FLAGS = -O3
+else
+ifeq ($(OS_ARCH),SunOS)
+MODULE_OPTIMIZE_FLAGS = -fast
+endif
+endif
+
+ifeq ($(OS_ARCH),WINNT)
+ifndef GNU_CC
+MODULE_OPTIMIZE_FLAGS = -Ox
+endif
+endif
+
+HOST_CSRCS = \
+ cppsetup.c \
+ ifparser.c \
+ include.c \
+ main.c \
+ parse.c \
+ pr.c \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+HOST_CFLAGS += -DINCLUDEDIR=\"/usr/include\" -DOBJSUFFIX=\".$(OBJ_SUFFIX)\"
+
+ifdef GNU_CC
+_GCCDIR = $(shell $(CC) -print-file-name=include)
+HOST_CFLAGS += -DPREINCDIR=\"$(_GCCDIR)\"
+endif
+
+export:: $(HOST_PROGRAM)
+
+$(HOST_OBJS): def.h ifparser.h imakemdep.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c
new file mode 100644
index 0000000..49a746a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/cppsetup.c
@@ -0,0 +1,233 @@
+/* $Xorg: cppsetup.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/cppsetup.c,v 3.11 2001/12/17 20:52:22 dawes Exp $ */
+
+#include "def.h"
+
+#ifdef CPP
+/*
+ * This file is strictly for the sake of cpy.y and yylex.c (if
+ * you indeed have the source for cpp).
+ */
+#define IB 1
+#define SB 2
+#define NB 4
+#define CB 8
+#define QB 16
+#define WB 32
+#define SALT '#'
+#if defined(pdp11) || defined(vax) || defined(ns16000) || defined(mc68000) || defined(ibm032)
+#define COFF 128
+#else
+#define COFF 0
+#endif
+/*
+ * These variables used by cpy.y and yylex.c
+ */
+extern char *outp, *inp, *newp, *pend;
+extern char *ptrtab;
+extern char fastab[];
+extern char slotab[];
+
+/*
+ * cppsetup
+ */
+struct filepointer *currentfile;
+struct inclist *currentinc;
+
+int
+cppsetup(char *line, struct filepointer *filep, struct inclist *inc)
+{
+ char *p, savec;
+ static boolean setupdone = FALSE;
+ boolean value;
+
+ if (!setupdone) {
+ cpp_varsetup();
+ setupdone = TRUE;
+ }
+
+ currentfile = filep;
+ currentinc = inc;
+ inp = newp = line;
+ for (p=newp; *p; p++)
+ ;
+
+ /*
+ * put a newline back on the end, and set up pend, etc.
+ */
+ *p++ = '\n';
+ savec = *p;
+ *p = '\0';
+ pend = p;
+
+ ptrtab = slotab+COFF;
+ *--inp = SALT;
+ outp=inp;
+ value = yyparse();
+ *p = savec;
+ return(value);
+}
+
+struct symtab **lookup(symbol)
+ char *symbol;
+{
+ static struct symtab *undefined;
+ struct symtab **sp;
+
+ sp = isdefined(symbol, currentinc, NULL);
+ if (sp == NULL) {
+ sp = &undefined;
+ (*sp)->s_value = NULL;
+ }
+ return (sp);
+}
+
+pperror(tag, x0,x1,x2,x3,x4)
+ int tag,x0,x1,x2,x3,x4;
+{
+ warning("\"%s\", line %d: ", currentinc->i_file, currentfile->f_line);
+ warning(x0,x1,x2,x3,x4);
+}
+
+
+yyerror(s)
+ register char *s;
+{
+ fatalerr("Fatal error: %s\n", s);
+}
+#else /* not CPP */
+
+#include "ifparser.h"
+struct _parse_data {
+ struct filepointer *filep;
+ struct inclist *inc;
+ char *filename;
+ const char *line;
+};
+
+static const char *
+my_if_errors (IfParser *ip, const char *cp, const char *expecting)
+{
+ struct _parse_data *pd = (struct _parse_data *) ip->data;
+ int lineno = pd->filep->f_line;
+ char *filename = pd->filename;
+ char prefix[300];
+ int prefixlen;
+ int i;
+
+ sprintf (prefix, "\"%s\":%d", filename, lineno);
+ prefixlen = strlen(prefix);
+ fprintf (stderr, "%s: %s", prefix, pd->line);
+ i = cp - pd->line;
+ if (i > 0 && pd->line[i-1] != '\n') {
+ putc ('\n', stderr);
+ }
+ for (i += prefixlen + 3; i > 0; i--) {
+ putc (' ', stderr);
+ }
+ fprintf (stderr, "^--- expecting %s\n", expecting);
+ return NULL;
+}
+
+
+#define MAXNAMELEN 256
+
+static struct symtab **
+lookup_variable (IfParser *ip, const char *var, int len)
+{
+ char tmpbuf[MAXNAMELEN + 1];
+ struct _parse_data *pd = (struct _parse_data *) ip->data;
+
+ if (len > MAXNAMELEN)
+ return 0;
+
+ strncpy (tmpbuf, var, len);
+ tmpbuf[len] = '\0';
+ return isdefined (tmpbuf, pd->inc, NULL);
+}
+
+
+static int
+my_eval_defined (IfParser *ip, const char *var, int len)
+{
+ if (lookup_variable (ip, var, len))
+ return 1;
+ else
+ return 0;
+}
+
+#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
+
+static long
+my_eval_variable (IfParser *ip, const char *var, int len)
+{
+ long val;
+ struct symtab **s;
+
+ s = lookup_variable (ip, var, len);
+ if (!s)
+ return 0;
+ do {
+ var = (*s)->s_value;
+ if (!isvarfirstletter(*var) || !strcmp((*s)->s_name, var))
+ break;
+ s = lookup_variable (ip, var, strlen(var));
+ } while (s);
+
+ var = ParseIfExpression(ip, var, &val);
+ if (var && *var) debug(4, ("extraneous: '%s'\n", var));
+ return val;
+}
+
+int
+cppsetup(char *filename,
+ char *line,
+ struct filepointer *filep,
+ struct inclist *inc)
+{
+ IfParser ip;
+ struct _parse_data pd;
+ long val = 0;
+
+ pd.filep = filep;
+ pd.inc = inc;
+ pd.line = line;
+ pd.filename = filename;
+ ip.funcs.handle_error = my_if_errors;
+ ip.funcs.eval_defined = my_eval_defined;
+ ip.funcs.eval_variable = my_eval_variable;
+ ip.data = (char *) &pd;
+
+ (void) ParseIfExpression (&ip, line, &val);
+ if (val)
+ return IF;
+ else
+ return IFFALSE;
+}
+#endif /* CPP */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h
new file mode 100644
index 0000000..d6e5f89
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/def.h
@@ -0,0 +1,184 @@
+/* $Xorg: def.h,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/def.h,v 3.14 2003/01/17 17:09:49 tsi Exp $ */
+
+#ifndef NO_X11
+#include <X11/Xos.h>
+#include <X11/Xfuncproto.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#if 0
+#ifndef X_NOT_POSIX
+#ifndef _POSIX_SOURCE
+#define _POSIX_SOURCE
+#endif
+#endif
+#endif
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define MAXDEFINES 512
+#define MAXFILES 1024
+#define MAXINCFILES 256 /* "-include" files */
+#define MAXDIRS 1024
+#define SYMTABINC 10 /* must be > 1 for define() to work right */
+#define TRUE 1
+#define FALSE 0
+
+/* the following must match the directives table in main.c */
+#define IF 0
+#define IFDEF 1
+#define IFNDEF 2
+#define ELSE 3
+#define ENDIF 4
+#define DEFINE 5
+#define UNDEF 6
+#define INCLUDE 7
+#define LINE 8
+#define PRAGMA 9
+#define ERROR 10
+#define IDENT 11
+#define SCCS 12
+#define ELIF 13
+#define EJECT 14
+#define WARNING 15
+#define INCLUDENEXT 16
+#define IFFALSE 17 /* pseudo value --- never matched */
+#define ELIFFALSE 18 /* pseudo value --- never matched */
+#define INCLUDEDOT 19 /* pseudo value --- never matched */
+#define IFGUESSFALSE 20 /* pseudo value --- never matched */
+#define ELIFGUESSFALSE 21 /* pseudo value --- never matched */
+#define INCLUDENEXTDOT 22 /* pseudo value --- never matched */
+
+#ifdef DEBUG
+extern int _debugmask;
+/*
+ * debug levels are:
+ *
+ * 0 show ifn*(def)*,endif
+ * 1 trace defined/!defined
+ * 2 show #include
+ * 3 show #include SYMBOL
+ * 4-6 unused
+ */
+#define debug(level,arg) { if (_debugmask & (1 << level)) warning arg; }
+#else
+#define debug(level,arg) /**/
+#endif /* DEBUG */
+
+typedef unsigned char boolean;
+
+struct symtab {
+ char *s_name;
+ char *s_value;
+};
+
+/* possible i_flag */
+#define DEFCHECKED (1<<0) /* whether defines have been checked */
+#define NOTIFIED (1<<1) /* whether we have revealed includes */
+#define MARKED (1<<2) /* whether it's in the makefile */
+#define SEARCHED (1<<3) /* whether we have read this */
+#define FINISHED (1<<4) /* whether we are done reading this */
+#define INCLUDED_SYM (1<<5) /* whether #include SYMBOL was found
+ Can't use i_list if TRUE */
+struct inclist {
+ char *i_incstring; /* string from #include line */
+ char *i_file; /* path name of the include file */
+ struct inclist **i_list; /* list of files it itself includes */
+ int i_listlen; /* length of i_list */
+ struct symtab **i_defs; /* symbol table for this file and its
+ children when merged */
+ int i_ndefs; /* current # defines */
+ boolean *i_merged; /* whether we have merged child
+ defines */
+ unsigned char i_flags;
+};
+
+struct filepointer {
+ char *f_name;
+ char *f_p;
+ char *f_base;
+ char *f_end;
+ long f_len;
+ long f_line;
+ long cmdinc_count;
+ char **cmdinc_list;
+ long cmdinc_line;
+};
+
+#include <stdlib.h>
+#if defined(macII) && !defined(__STDC__) /* stdlib.h fails to define these */
+char *malloc(), *realloc();
+#endif /* macII */
+
+char *copy(char *str);
+int match(char *str, char **list);
+char *base_name(char *file);
+char *getnextline(struct filepointer *fp);
+struct symtab **slookup(char *symbol, struct inclist *file);
+struct symtab **isdefined(char *symbol, struct inclist *file,
+ struct inclist **srcfile);
+struct symtab **fdefined(char *symbol, struct inclist *file,
+ struct inclist **srcfile);
+struct filepointer *getfile(char *file);
+void included_by(struct inclist *ip,
+ struct inclist *newfile);
+struct inclist *newinclude(char *newfile, char *incstring);
+void inc_clean (void);
+struct inclist *inc_path(char *file, char *include, int type);
+
+void freefile(struct filepointer *fp);
+
+void define2(char *name, char *val, struct inclist *file);
+void define(char *def, struct inclist *file);
+void undefine(char *symbol, struct inclist *file);
+int find_includes(struct filepointer *filep,
+ struct inclist *file,
+ struct inclist *file_red,
+ int recursion, boolean failOK);
+
+void recursive_pr_include(struct inclist *head,
+ char *file, char *base);
+void add_include(struct filepointer *filep,
+ struct inclist *file,
+ struct inclist *file_red,
+ char *include, int type,
+ boolean failOK);
+
+int cppsetup(char *filename,
+ char *line,
+ struct filepointer *filep,
+ struct inclist *inc);
+
+
+extern void fatalerr(char *, ...);
+extern void warning(char *, ...);
+extern void warning1(char *, ...);
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c
new file mode 100644
index 0000000..d8d9e76
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.c
@@ -0,0 +1,549 @@
+/*
+ * $Xorg: ifparser.c,v 1.3 2000/08/17 19:41:50 cpqbld Exp $
+ *
+ * Copyright 1992 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Network Computing Devices may not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Network Computing Devices makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided ``as is'' without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Jim Fulton
+ * Network Computing Devices, Inc.
+ *
+ * Simple if statement processor
+ *
+ * This module can be used to evaluate string representations of C language
+ * if constructs. It accepts the following grammar:
+ *
+ * EXPRESSION := VALUE
+ * | VALUE BINOP EXPRESSION
+ * | VALUE '?' EXPRESSION ':' EXPRESSION
+ *
+ * VALUE := '(' EXPRESSION ')'
+ * | '!' VALUE
+ * | '-' VALUE
+ * | '+' VALUE
+ * | '~' VALUE
+ * | 'defined' '(' variable ')'
+ * | 'defined' variable
+ * | # variable '(' variable-list ')'
+ * | variable
+ * | number
+ *
+ * BINOP := '*' | '/' | '%'
+ * | '+' | '-'
+ * | '<<' | '>>'
+ * | '<' | '>' | '<=' | '>='
+ * | '==' | '!='
+ * | '&' | '^' | '|'
+ * | '&&' | '||'
+ *
+ * The normal C order of precedence is supported.
+ *
+ *
+ * External Entry Points:
+ *
+ * ParseIfExpression parse a string for #if
+ */
+/* $XFree86: xc/config/makedepend/ifparser.c,v 3.11 2002/09/23 01:48:08 tsi Exp $ */
+
+#include "ifparser.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/****************************************************************************
+ Internal Macros and Utilities for Parser
+ ****************************************************************************/
+
+#define DO(val) if (!(val)) return NULL
+#define CALLFUNC(ggg,fff) (*((ggg)->funcs.fff))
+#define SKIPSPACE(ccc) while (isspace(*ccc)) ccc++
+#define isvarfirstletter(ccc) (isalpha(ccc) || (ccc) == '_')
+
+
+static const char *
+parse_variable (IfParser *g, const char *cp, const char **varp)
+{
+ SKIPSPACE (cp);
+
+ if (!isvarfirstletter (*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "variable name");
+
+ *varp = cp;
+ /* EMPTY */
+ for (cp++; isalnum(*cp) || *cp == '_'; cp++) ;
+ return cp;
+}
+
+
+static const char *
+parse_number (IfParser *g, const char *cp, long *valp)
+{
+ long base = 10;
+ SKIPSPACE (cp);
+
+ if (!isdigit(*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "number");
+
+ *valp = 0;
+
+ if (*cp == '0') {
+ cp++;
+ if ((*cp == 'x') || (*cp == 'X')) {
+ base = 16;
+ cp++;
+ } else {
+ base = 8;
+ }
+ }
+
+ /* Ignore overflows and assume ASCII, what source is usually written in */
+ while (1) {
+ int increment = -1;
+ if (base == 8) {
+ if ((*cp >= '0') && (*cp <= '7'))
+ increment = *cp++ - '0';
+ } else if (base == 16) {
+ if ((*cp >= '0') && (*cp <= '9'))
+ increment = *cp++ - '0';
+ else if ((*cp >= 'A') && (*cp <= 'F'))
+ increment = *cp++ - ('A' - 10);
+ else if ((*cp >= 'a') && (*cp <= 'f'))
+ increment = *cp++ - ('a' - 10);
+ } else { /* Decimal */
+ if ((*cp >= '0') && (*cp <= '9'))
+ increment = *cp++ - '0';
+ }
+ if (increment < 0)
+ break;
+ *valp = (*valp * base) + increment;
+ }
+
+ /* Skip trailing qualifiers */
+ while (*cp == 'U' || *cp == 'u' || *cp == 'L' || *cp == 'l') cp++;
+ return cp;
+}
+
+static const char *
+parse_character (IfParser *g, const char *cp, long *valp)
+{
+ char val;
+
+ SKIPSPACE (cp);
+ if (*cp == '\\')
+ switch (cp[1]) {
+ case 'n': val = '\n'; break;
+ case 't': val = '\t'; break;
+ case 'v': val = '\v'; break;
+ case 'b': val = '\b'; break;
+ case 'r': val = '\r'; break;
+ case 'f': val = '\f'; break;
+ case 'a': val = '\a'; break;
+ case '\\': val = '\\'; break;
+ case '?': val = '\?'; break;
+ case '\'': val = '\''; break;
+ case '\"': val = '\"'; break;
+ case 'x': val = (char) strtol (cp + 2, NULL, 16); break;
+ default: val = (char) strtol (cp + 1, NULL, 8); break;
+ }
+ else
+ val = *cp;
+ while (*cp != '\'') cp++;
+ *valp = (long) val;
+ return cp;
+}
+
+static const char *
+parse_value (IfParser *g, const char *cp, long *valp)
+{
+ const char *var, *varend;
+
+ *valp = 0;
+
+ SKIPSPACE (cp);
+ if (!*cp)
+ return cp;
+
+ switch (*cp) {
+ case '(':
+ DO (cp = ParseIfExpression (g, cp + 1, valp));
+ SKIPSPACE (cp);
+ if (*cp != ')')
+ return CALLFUNC(g, handle_error) (g, cp, ")");
+
+ return cp + 1; /* skip the right paren */
+
+ case '!':
+ DO (cp = parse_value (g, cp + 1, valp));
+ *valp = !(*valp);
+ return cp;
+
+ case '-':
+ DO (cp = parse_value (g, cp + 1, valp));
+ *valp = -(*valp);
+ return cp;
+
+ case '+':
+ DO (cp = parse_value (g, cp + 1, valp));
+ return cp;
+
+ case '~':
+ DO (cp = parse_value (g, cp + 1, valp));
+ *valp = ~(*valp);
+ return cp;
+
+ case '#':
+ DO (cp = parse_variable (g, cp + 1, &var));
+ SKIPSPACE (cp);
+ if (*cp != '(')
+ return CALLFUNC(g, handle_error) (g, cp, "(");
+ do {
+ DO (cp = parse_variable (g, cp + 1, &var));
+ SKIPSPACE (cp);
+ } while (*cp && *cp != ')');
+ if (*cp != ')')
+ return CALLFUNC(g, handle_error) (g, cp, ")");
+ *valp = 1; /* XXX */
+ return cp + 1;
+
+ case '\'':
+ DO (cp = parse_character (g, cp + 1, valp));
+ if (*cp != '\'')
+ return CALLFUNC(g, handle_error) (g, cp, "'");
+ return cp + 1;
+
+ case 'd':
+ if (strncmp (cp, "defined", 7) == 0 && !isalnum(cp[7])) {
+ int paren = 0;
+ int len;
+
+ cp += 7;
+ SKIPSPACE (cp);
+ if (*cp == '(') {
+ paren = 1;
+ cp++;
+ }
+ DO (cp = parse_variable (g, cp, &var));
+ len = cp - var;
+ SKIPSPACE (cp);
+ if (paren && *cp != ')')
+ return CALLFUNC(g, handle_error) (g, cp, ")");
+ *valp = (*(g->funcs.eval_defined)) (g, var, len);
+ return cp + paren; /* skip the right paren */
+ }
+ /* fall out */
+ }
+
+ if (isdigit(*cp)) {
+ DO (cp = parse_number (g, cp, valp));
+ } else if (!isvarfirstletter(*cp))
+ return CALLFUNC(g, handle_error) (g, cp, "variable or number");
+ else {
+ DO (cp = parse_variable (g, cp, &var));
+ varend = cp;
+ SKIPSPACE(cp);
+ if (*cp != '(') {
+ *valp = (*(g->funcs.eval_variable)) (g, var, varend - var);
+ } else {
+ do {
+ long dummy;
+ DO (cp = ParseIfExpression (g, cp + 1, &dummy));
+ SKIPSPACE(cp);
+ if (*cp == ')')
+ break;
+ if (*cp != ',')
+ return CALLFUNC(g, handle_error) (g, cp, ",");
+ } while (1);
+
+ *valp = 1; /* XXX */
+ cp++;
+ }
+ }
+
+ return cp;
+}
+
+
+
+static const char *
+parse_product (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_value (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '*':
+ DO (cp = parse_product (g, cp + 1, &rightval));
+ *valp = (*valp * rightval);
+ break;
+
+ case '/':
+ DO (cp = parse_product (g, cp + 1, &rightval));
+ *valp = (*valp / rightval);
+ break;
+
+ case '%':
+ DO (cp = parse_product (g, cp + 1, &rightval));
+ *valp = (*valp % rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_sum (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_product (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '+':
+ DO (cp = parse_sum (g, cp + 1, &rightval));
+ *valp = (*valp + rightval);
+ break;
+
+ case '-':
+ DO (cp = parse_sum (g, cp + 1, &rightval));
+ *valp = (*valp - rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_shift (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_sum (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '<':
+ if (cp[1] == '<') {
+ DO (cp = parse_shift (g, cp + 2, &rightval));
+ *valp = (*valp << rightval);
+ }
+ break;
+
+ case '>':
+ if (cp[1] == '>') {
+ DO (cp = parse_shift (g, cp + 2, &rightval));
+ *valp = (*valp >> rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_inequality (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_shift (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '<':
+ if (cp[1] == '=') {
+ DO (cp = parse_inequality (g, cp + 2, &rightval));
+ *valp = (*valp <= rightval);
+ } else {
+ DO (cp = parse_inequality (g, cp + 1, &rightval));
+ *valp = (*valp < rightval);
+ }
+ break;
+
+ case '>':
+ if (cp[1] == '=') {
+ DO (cp = parse_inequality (g, cp + 2, &rightval));
+ *valp = (*valp >= rightval);
+ } else {
+ DO (cp = parse_inequality (g, cp + 1, &rightval));
+ *valp = (*valp > rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_equality (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_inequality (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '=':
+ if (cp[1] == '=')
+ cp++;
+ DO (cp = parse_equality (g, cp + 1, &rightval));
+ *valp = (*valp == rightval);
+ break;
+
+ case '!':
+ if (cp[1] != '=')
+ break;
+ DO (cp = parse_equality (g, cp + 2, &rightval));
+ *valp = (*valp != rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_band (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_equality (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '&':
+ if (cp[1] != '&') {
+ DO (cp = parse_band (g, cp + 1, &rightval));
+ *valp = (*valp & rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_bxor (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_band (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '^':
+ DO (cp = parse_bxor (g, cp + 1, &rightval));
+ *valp = (*valp ^ rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_bor (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_bxor (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '|':
+ if (cp[1] != '|') {
+ DO (cp = parse_bor (g, cp + 1, &rightval));
+ *valp = (*valp | rightval);
+ }
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_land (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_bor (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '&':
+ if (cp[1] != '&')
+ return CALLFUNC(g, handle_error) (g, cp, "&&");
+ DO (cp = parse_land (g, cp + 2, &rightval));
+ *valp = (*valp && rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_lor (IfParser *g, const char *cp, long *valp)
+{
+ long rightval;
+
+ DO (cp = parse_land (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '|':
+ if (cp[1] != '|')
+ return CALLFUNC(g, handle_error) (g, cp, "||");
+ DO (cp = parse_lor (g, cp + 2, &rightval));
+ *valp = (*valp || rightval);
+ break;
+ }
+ return cp;
+}
+
+
+static const char *
+parse_cond(IfParser *g, const char *cp, long *valp)
+{
+ long trueval, falseval;
+
+ DO (cp = parse_lor (g, cp, valp));
+ SKIPSPACE (cp);
+
+ switch (*cp) {
+ case '?':
+ DO (cp = parse_cond (g, cp + 1, &trueval));
+ SKIPSPACE (cp);
+ if (*cp != ':')
+ return CALLFUNC(g, handle_error) (g, cp, ":");
+ DO (cp = parse_cond (g, cp + 1, &falseval));
+ *valp = (*valp ? trueval : falseval);
+ break;
+ }
+ return cp;
+}
+
+
+/****************************************************************************
+ External Entry Points
+ ****************************************************************************/
+
+const char *
+ParseIfExpression (IfParser *g, const char *cp, long *valp)
+{
+ return parse_cond (g, cp, valp);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h
new file mode 100644
index 0000000..89d2a2f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/ifparser.h
@@ -0,0 +1,83 @@
+/*
+ * $Xorg: ifparser.h,v 1.3 2000/08/17 19:41:51 cpqbld Exp $
+ *
+ * Copyright 1992 Network Computing Devices, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Network Computing Devices may not be
+ * used in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Network Computing Devices makes
+ * no representations about the suitability of this software for any purpose.
+ * It is provided ``as is'' without express or implied warranty.
+ *
+ * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Jim Fulton
+ * Network Computing Devices, Inc.
+ *
+ * Simple if statement processor
+ *
+ * This module can be used to evaluate string representations of C language
+ * if constructs. It accepts the following grammar:
+ *
+ * EXPRESSION := VALUE
+ * | VALUE BINOP EXPRESSION
+ * | VALUE '?' EXPRESSION ':' EXPRESSION
+ *
+ * VALUE := '(' EXPRESSION ')'
+ * | '!' VALUE
+ * | '-' VALUE
+ * | '~' VALUE
+ * | 'defined' '(' variable ')'
+ * | variable
+ * | number
+ *
+ * BINOP := '*' | '/' | '%'
+ * | '+' | '-'
+ * | '<<' | '>>'
+ * | '<' | '>' | '<=' | '>='
+ * | '==' | '!='
+ * | '&' | '^' | '|'
+ * | '&&' | '||'
+ *
+ * The normal C order of precedence is supported.
+ *
+ *
+ * External Entry Points:
+ *
+ * ParseIfExpression parse a string for #if
+ */
+
+/* $XFree86: xc/config/makedepend/ifparser.h,v 3.5 2001/07/25 15:04:40 dawes Exp $ */
+
+#include <stdio.h>
+
+typedef int Bool;
+#define False 0
+#define True 1
+
+typedef struct _if_parser {
+ struct { /* functions */
+ const char *(*handle_error) (struct _if_parser *, const char *,
+ const char *);
+ long (*eval_variable) (struct _if_parser *, const char *, int);
+ int (*eval_defined) (struct _if_parser *, const char *, int);
+ } funcs;
+ char *data;
+} IfParser;
+
+const char *ParseIfExpression (
+ IfParser *,
+ const char *,
+ long *
+);
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h
new file mode 100644
index 0000000..5c58351
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/imakemdep.h
@@ -0,0 +1,733 @@
+
+/* $XConsortium: imakemdep.h,v 1.83 95/04/07 19:47:46 kaleb Exp $ */
+/* $XFree86: xc/config/imake/imakemdep.h,v 3.12 1995/07/08 10:22:17 dawes Exp $ */
+/*
+
+Copyright (c) 1993, 1994 X Consortium
+
+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
+X CONSORTIUM 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.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+
+/*
+ * This file contains machine-dependent constants for the imake utility.
+ * When porting imake, read each of the steps below and add in any necessary
+ * definitions. In general you should *not* edit ccimake.c or imake.c!
+ */
+
+#ifdef CCIMAKE
+/*
+ * Step 1: imake_ccflags
+ * Define any special flags that will be needed to get imake.c to compile.
+ * These will be passed to the compile along with the contents of the
+ * make variable BOOTSTRAPCFLAGS.
+ */
+#ifdef hpux
+#ifdef hp9000s800
+#define imake_ccflags "-DSYSV"
+#else
+#define imake_ccflags "-Wc,-Nd4000,-Ns3000 -DSYSV"
+#endif
+#endif
+
+#if defined(macII) || defined(_AUX_SOURCE)
+#define imake_ccflags "-DmacII -DSYSV"
+#endif
+
+#ifdef stellar
+#define imake_ccflags "-DSYSV"
+#endif
+
+#if defined(USL) || defined(Oki) || defined(NCR)
+#define imake_ccflags "-Xc -DSVR4"
+#endif
+
+#ifdef sony
+#if defined(SYSTYPE_SYSV) || defined(_SYSTYPE_SYSV)
+#define imake_ccflags "-DSVR4"
+#else
+#include <sys/param.h>
+#if NEWSOS < 41
+#define imake_ccflags "-Dbsd43 -DNOSTDHDRS"
+#else
+#if NEWSOS < 42
+#define imake_ccflags "-Dbsd43"
+#endif
+#endif
+#endif
+#endif
+
+#ifdef _CRAY
+#define imake_ccflags "-DSYSV -DUSG"
+#endif
+
+#if defined(_IBMR2) || defined(aix)
+#define imake_ccflags "-Daix -DSYSV"
+#endif
+
+#ifdef Mips
+# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43)
+# define imake_ccflags "-DBSD43"
+# else
+# define imake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef is68k
+#define imake_ccflags "-Dluna -Duniosb"
+#endif
+
+#ifdef SYSV386
+# ifdef SVR4
+# define imake_ccflags "-Xc -DSVR4"
+# else
+# define imake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef SVR4
+# ifdef i386
+# define imake_ccflags "-Xc -DSVR4"
+# endif
+#endif
+
+#ifdef SYSV
+# ifdef i386
+# define imake_ccflags "-DSYSV"
+# endif
+#endif
+
+#ifdef __convex__
+#define imake_ccflags "-fn -tm c1"
+#endif
+
+#ifdef apollo
+#define imake_ccflags "-DX_NOT_POSIX"
+#endif
+
+#ifdef WIN32
+#define imake_ccflags "-nologo -batch -D__STDC__"
+#endif
+
+#ifdef __uxp__
+#define imake_ccflags "-DSVR4 -DANSICPP"
+#endif
+
+#ifdef __sxg__
+#define imake_ccflags "-DSYSV -DUSG -DNOSTDHDRS"
+#endif
+
+#ifdef sequent
+#define imake_ccflags "-DX_NOT_STDC_ENV -DX_NOT_POSIX"
+#endif
+
+#ifdef _SEQUENT_
+#define imake_ccflags "-DSYSV -DUSG"
+#endif
+
+#if defined(SX) || defined(PC_UX)
+#define imake_ccflags "-DSYSV"
+#endif
+
+#ifdef nec_ews_svr2
+#define imake_ccflags "-DUSG"
+#endif
+
+#if defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(_nec_up) || defined(_nec_ft)
+#define imake_ccflags "-DSVR4"
+#endif
+
+#ifdef MACH
+#define imake_ccflags "-DNOSTDHDRS"
+#endif
+
+/* this is for OS/2 under EMX. This won't work with DOS */
+#if defined(__EMX__)
+#define imake_ccflags "-DBSD43"
+#endif
+
+#else /* not CCIMAKE */
+#ifndef MAKEDEPEND
+/*
+ * Step 2: dup2
+ * If your OS doesn't have a dup2() system call to duplicate one file
+ * descriptor onto another, define such a mechanism here (if you don't
+ * already fall under the existing category(ies).
+ */
+#if defined(SYSV) && !defined(_CRAY) && !defined(Mips) && !defined(_SEQUENT_)
+#define dup2(fd1,fd2) ((fd1 == fd2) ? fd1 : (close(fd2), \
+ fcntl(fd1, F_DUPFD, fd2)))
+#endif
+
+
+/*
+ * Step 3: FIXUP_CPP_WHITESPACE
+ * If your cpp collapses tabs macro expansions into a single space and
+ * replaces escaped newlines with a space, define this symbol. This will
+ * cause imake to attempt to patch up the generated Makefile by looking
+ * for lines that have colons in them (this is why the rules file escapes
+ * all colons). One way to tell if you need this is to see whether or not
+ * your Makefiles have no tabs in them and lots of @@ strings.
+ */
+#if defined(sun) || defined(SYSV) || defined(SVR4) || defined(hcx) || defined(WIN32) || (defined(AMOEBA) && defined(CROSS_COMPILE))
+#define FIXUP_CPP_WHITESPACE
+#endif
+#ifdef WIN32
+#define REMOVE_CPP_LEADSPACE
+#define INLINE_SYNTAX
+#define MAGIC_MAKE_VARS
+#endif
+#ifdef __minix_vmd
+#define FIXUP_CPP_WHITESPACE
+#endif
+
+/*
+ * Step 4: USE_CC_E, DEFAULT_CC, DEFAULT_CPP
+ * If you want to use cc -E instead of cpp, define USE_CC_E.
+ * If use cc -E but want a different compiler, define DEFAULT_CC.
+ * If the cpp you need is not in /lib/cpp, define DEFAULT_CPP.
+ */
+#ifdef hpux
+#define USE_CC_E
+#endif
+#ifdef WIN32
+#define USE_CC_E
+#define DEFAULT_CC "cl"
+#endif
+#ifdef apollo
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#if defined(_IBMR2) && !defined(DEFAULT_CPP)
+#define DEFAULT_CPP "/usr/lpp/X11/Xamples/util/cpp/cpp"
+#endif
+#if defined(sun) && defined(SVR4)
+#define DEFAULT_CPP "/usr/ccs/lib/cpp"
+#endif
+#ifdef __bsdi__
+#define DEFAULT_CPP "/usr/bin/cpp"
+#endif
+#ifdef __uxp__
+#define DEFAULT_CPP "/usr/ccs/lib/cpp"
+#endif
+#ifdef __sxg__
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#ifdef _CRAY
+#define DEFAULT_CPP "/lib/pcpp"
+#endif
+#if defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#define DEFAULT_CPP "/usr/libexec/cpp"
+#endif
+#ifdef MACH
+#define USE_CC_E
+#endif
+#ifdef __minix_vmd
+#define DEFAULT_CPP "/usr/lib/cpp"
+#endif
+#if defined(__EMX__)
+/* expects cpp in PATH */
+#define DEFAULT_CPP "cpp"
+#endif
+
+/*
+ * Step 5: cpp_argv
+ * The following table contains the flags that should be passed
+ * whenever a Makefile is being generated. If your preprocessor
+ * doesn't predefine any unique symbols, choose one and add it to the
+ * end of this table. Then, do the following:
+ *
+ * a. Use this symbol in Imake.tmpl when setting MacroFile.
+ * b. Put this symbol in the definition of BootstrapCFlags in your
+ * <platform>.cf file.
+ * c. When doing a make World, always add "BOOTSTRAPCFLAGS=-Dsymbol"
+ * to the end of the command line.
+ *
+ * Note that you may define more than one symbol (useful for platforms
+ * that support multiple operating systems).
+ */
+
+#define ARGUMENTS 50 /* number of arguments in various arrays */
+char *cpp_argv[ARGUMENTS] = {
+ "cc", /* replaced by the actual program to exec */
+ "-I.", /* add current directory to include path */
+#ifdef unix
+ "-Uunix", /* remove unix symbol so that filename unix.c okay */
+#endif
+#if defined(__386BSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(MACH)
+# ifdef __i386__
+ "-D__i386__",
+# endif
+# ifdef __x86_64__
+ "-D__x86_64__",
+# endif
+# ifdef __GNUC__
+ "-traditional",
+# endif
+#endif
+#ifdef M4330
+ "-DM4330", /* Tektronix */
+#endif
+#ifdef M4310
+ "-DM4310", /* Tektronix */
+#endif
+#if defined(macII) || defined(_AUX_SOURCE)
+ "-DmacII", /* Apple A/UX */
+#endif
+#ifdef USL
+ "-DUSL", /* USL */
+#endif
+#ifdef sony
+ "-Dsony", /* Sony */
+#if !defined(SYSTYPE_SYSV) && !defined(_SYSTYPE_SYSV) && NEWSOS < 42
+ "-Dbsd43",
+#endif
+#endif
+#ifdef _IBMR2
+ "-D_IBMR2", /* IBM RS-6000 (we ensured that aix is defined above */
+#ifndef aix
+#define aix /* allow BOOTSTRAPCFLAGS="-D_IBMR2" */
+#endif
+#endif /* _IBMR2 */
+#ifdef aix
+ "-Daix", /* AIX instead of AOS */
+#ifndef ibm
+#define ibm /* allow BOOTSTRAPCFLAGS="-Daix" */
+#endif
+#endif /* aix */
+#ifdef ibm
+ "-Dibm", /* IBM PS/2 and RT under both AOS and AIX */
+#endif
+#ifdef luna
+ "-Dluna", /* OMRON luna 68K and 88K */
+#ifdef luna1
+ "-Dluna1",
+#endif
+#ifdef luna88k /* need not on UniOS-Mach Vers. 1.13 */
+ "-traditional", /* for some older version */
+#endif /* instead of "-DXCOMM=\\#" */
+#ifdef uniosb
+ "-Duniosb",
+#endif
+#ifdef uniosu
+ "-Duniosu",
+#endif
+#endif /* luna */
+#ifdef _CRAY /* Cray */
+ "-Ucray",
+#endif
+#ifdef Mips
+ "-DMips", /* Define and use Mips for Mips Co. OS/mach. */
+# if defined(SYSTYPE_BSD) || defined(BSD) || defined(BSD43)
+ "-DBSD43", /* Mips RISCOS supports two environments */
+# else
+ "-DSYSV", /* System V environment is the default */
+# endif
+#endif /* Mips */
+#ifdef MOTOROLA
+ "-DMOTOROLA", /* Motorola Delta Systems */
+# ifdef SYSV
+ "-DSYSV",
+# endif
+# ifdef SVR4
+ "-DSVR4",
+# endif
+#endif /* MOTOROLA */
+#ifdef i386
+ "-Di386",
+# ifdef SVR4
+ "-DSVR4",
+# endif
+# ifdef SYSV
+ "-DSYSV",
+# ifdef ISC
+ "-DISC",
+# ifdef ISC40
+ "-DISC40", /* ISC 4.0 */
+# else
+# ifdef ISC202
+ "-DISC202", /* ISC 2.0.2 */
+# else
+# ifdef ISC30
+ "-DISC30", /* ISC 3.0 */
+# else
+ "-DISC22", /* ISC 2.2.1 */
+# endif
+# endif
+# endif
+# endif
+# ifdef SCO
+ "-DSCO",
+# ifdef SCO324
+ "-DSCO324",
+# endif
+# endif
+# endif
+# ifdef ESIX
+ "-DESIX",
+# endif
+# ifdef ATT
+ "-DATT",
+# endif
+# ifdef DELL
+ "-DDELL",
+# endif
+#endif
+#ifdef SYSV386 /* System V/386 folks, obsolete */
+ "-Di386",
+# ifdef SVR4
+ "-DSVR4",
+# endif
+# ifdef ISC
+ "-DISC",
+# ifdef ISC40
+ "-DISC40", /* ISC 4.0 */
+# else
+# ifdef ISC202
+ "-DISC202", /* ISC 2.0.2 */
+# else
+# ifdef ISC30
+ "-DISC30", /* ISC 3.0 */
+# else
+ "-DISC22", /* ISC 2.2.1 */
+# endif
+# endif
+# endif
+# endif
+# ifdef SCO
+ "-DSCO",
+# ifdef SCO324
+ "-DSCO324",
+# endif
+# endif
+# ifdef ESIX
+ "-DESIX",
+# endif
+# ifdef ATT
+ "-DATT",
+# endif
+# ifdef DELL
+ "-DDELL",
+# endif
+#endif
+#ifdef __osf__
+ "-D__osf__",
+# ifdef __mips__
+ "-D__mips__",
+# endif
+# ifdef __alpha
+ "-D__alpha",
+# endif
+# ifdef __i386__
+ "-D__i386__",
+# endif
+# ifdef __GNUC__
+ "-traditional",
+# endif
+#endif
+#ifdef Oki
+ "-DOki",
+#endif
+#ifdef sun
+#ifdef SVR4
+ "-DSVR4",
+#endif
+#endif
+#ifdef WIN32
+ "-DWIN32",
+ "-nologo",
+ "-batch",
+ "-D__STDC__",
+#endif
+#ifdef NCR
+ "-DNCR", /* NCR */
+#endif
+#ifdef linux
+ "-traditional",
+ "-Dlinux",
+#endif
+#ifdef __uxp__
+ "-D__uxp__",
+#endif
+#ifdef __sxg__
+ "-D__sxg__",
+#endif
+#ifdef nec_ews_svr2
+ "-Dnec_ews_svr2",
+#endif
+#ifdef AMOEBA
+ "-DAMOEBA",
+# ifdef CROSS_COMPILE
+ "-DCROSS_COMPILE",
+# ifdef CROSS_i80386
+ "-Di80386",
+# endif
+# ifdef CROSS_sparc
+ "-Dsparc",
+# endif
+# ifdef CROSS_mc68000
+ "-Dmc68000",
+# endif
+# else
+# ifdef i80386
+ "-Di80386",
+# endif
+# ifdef sparc
+ "-Dsparc",
+# endif
+# ifdef mc68000
+ "-Dmc68000",
+# endif
+# endif
+#endif
+#ifdef __minix_vmd
+ "-Dminix",
+#endif
+
+#if defined(__EMX__)
+ "-traditional",
+ "-Demxos2",
+#endif
+
+};
+#else /* else MAKEDEPEND */
+/*
+ * Step 6: predefs
+ * If your compiler and/or preprocessor define any specific symbols, add
+ * them to the the following table. The definition of struct symtab is
+ * in util/makedepend/def.h.
+ */
+struct symtab predefs[] = {
+#ifdef apollo
+ {"apollo", "1"},
+#endif
+#ifdef ibm032
+ {"ibm032", "1"},
+#endif
+#ifdef ibm
+ {"ibm", "1"},
+#endif
+#ifdef aix
+ {"aix", "1"},
+#endif
+#ifdef sun
+ {"sun", "1"},
+#endif
+#ifdef sun2
+ {"sun2", "1"},
+#endif
+#ifdef sun3
+ {"sun3", "1"},
+#endif
+#ifdef sun4
+ {"sun4", "1"},
+#endif
+#ifdef sparc
+ {"sparc", "1"},
+#endif
+#ifdef __sparc__
+ {"__sparc__", "1"},
+#endif
+#ifdef hpux
+ {"hpux", "1"},
+#endif
+#ifdef __hpux
+ {"__hpux", "1"},
+#endif
+#ifdef __hp9000s800
+ {"__hp9000s800", "1"},
+#endif
+#ifdef __hp9000s700
+ {"__hp9000s700", "1"},
+#endif
+#ifdef vax
+ {"vax", "1"},
+#endif
+#ifdef VMS
+ {"VMS", "1"},
+#endif
+#ifdef cray
+ {"cray", "1"},
+#endif
+#ifdef CRAY
+ {"CRAY", "1"},
+#endif
+#ifdef _CRAY
+ {"_CRAY", "1"},
+#endif
+#ifdef att
+ {"att", "1"},
+#endif
+#ifdef mips
+ {"mips", "1"},
+#endif
+#ifdef __mips__
+ {"__mips__", "1"},
+#endif
+#ifdef ultrix
+ {"ultrix", "1"},
+#endif
+#ifdef stellar
+ {"stellar", "1"},
+#endif
+#ifdef mc68000
+ {"mc68000", "1"},
+#endif
+#ifdef mc68020
+ {"mc68020", "1"},
+#endif
+#ifdef __GNUC__
+ {"__GNUC__", "1"},
+#endif
+#if __STDC__
+ {"__STDC__", "1"},
+#endif
+#ifdef __HIGHC__
+ {"__HIGHC__", "1"},
+#endif
+#ifdef CMU
+ {"CMU", "1"},
+#endif
+#ifdef luna
+ {"luna", "1"},
+#ifdef luna1
+ {"luna1", "1"},
+#endif
+#ifdef luna2
+ {"luna2", "1"},
+#endif
+#ifdef luna88k
+ {"luna88k", "1"},
+#endif
+#ifdef uniosb
+ {"uniosb", "1"},
+#endif
+#ifdef uniosu
+ {"uniosu", "1"},
+#endif
+#endif
+#ifdef ieeep754
+ {"ieeep754", "1"},
+#endif
+#ifdef is68k
+ {"is68k", "1"},
+#endif
+#ifdef m68k
+ {"m68k", "1"},
+#endif
+#ifdef m88k
+ {"m88k", "1"},
+#endif
+#ifdef __m88k__
+ {"__m88k__", "1"},
+#endif
+#ifdef bsd43
+ {"bsd43", "1"},
+#endif
+#ifdef hcx
+ {"hcx", "1"},
+#endif
+#ifdef sony
+ {"sony", "1"},
+#ifdef SYSTYPE_SYSV
+ {"SYSTYPE_SYSV", "1"},
+#endif
+#ifdef _SYSTYPE_SYSV
+ {"_SYSTYPE_SYSV", "1"},
+#endif
+#endif
+#ifdef __OSF__
+ {"__OSF__", "1"},
+#endif
+#ifdef __osf__
+ {"__osf__", "1"},
+#endif
+#ifdef __alpha
+ {"__alpha", "1"},
+#endif
+#ifdef __DECC
+ {"__DECC", "1"},
+#endif
+#ifdef __decc
+ {"__decc", "1"},
+#endif
+#ifdef __uxp__
+ {"__uxp__", "1"},
+#endif
+#ifdef __sxg__
+ {"__sxg__", "1"},
+#endif
+#ifdef _SEQUENT_
+ {"_SEQUENT_", "1"},
+ {"__STDC__", "1"},
+#endif
+#ifdef __bsdi__
+ {"__bsdi__", "1"},
+#endif
+#ifdef nec_ews_svr2
+ {"nec_ews_svr2", "1"},
+#endif
+#ifdef nec_ews_svr4
+ {"nec_ews_svr4", "1"},
+#endif
+#ifdef _nec_ews_svr4
+ {"_nec_ews_svr4", "1"},
+#endif
+#ifdef _nec_up
+ {"_nec_up", "1"},
+#endif
+#ifdef SX
+ {"SX", "1"},
+#endif
+#ifdef nec
+ {"nec", "1"},
+#endif
+#ifdef _nec_ft
+ {"_nec_ft", "1"},
+#endif
+#ifdef PC_UX
+ {"PC_UX", "1"},
+#endif
+#ifdef sgi
+ {"sgi", "1"},
+#endif
+#ifdef __sgi
+ {"__sgi", "1"},
+#endif
+#ifdef __FreeBSD__
+ {"__FreeBSD__", "1"},
+#endif
+#ifdef __NetBSD__
+ {"__NetBSD__", "1"},
+#endif
+#ifdef __OpenBSD__
+ {"__OpenBSD__", "1"},
+#endif
+#ifdef __EMX__
+ {"__EMX__", "1"},
+#endif
+ /* add any additional symbols before this line */
+ {NULL, NULL}
+};
+
+#endif /* MAKEDEPEND */
+#endif /* CCIMAKE */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c
new file mode 100644
index 0000000..3b89f26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/include.c
@@ -0,0 +1,337 @@
+/* $Xorg: include.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/include.c,v 3.7 2001/12/14 19:53:20 dawes Exp $ */
+
+
+#include "def.h"
+
+#ifdef _MSC_VER
+#include <windows.h>
+static int
+does_file_exist(char *file)
+{
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ BOOL b = GetFileAttributesExA(file, GetFileExInfoStandard, &data);
+ if (!b)
+ return 0;
+ return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
+}
+#else
+static int
+does_file_exist(char *file)
+{
+ struct stat sb;
+ return stat(file, &sb) == 0 && !S_ISDIR(sb.st_mode);
+}
+#endif
+
+extern struct inclist inclist[ MAXFILES ],
+ *inclistp, *inclistnext;
+extern char *includedirs[ ],
+ **includedirsnext;
+extern char *notdotdot[ ];
+extern boolean show_where_not;
+extern boolean warn_multiple;
+
+static boolean
+isdot(char *p)
+{
+ if(p && *p++ == '.' && *p++ == '\0')
+ return(TRUE);
+ return(FALSE);
+}
+
+static boolean
+isdotdot(char *p)
+{
+ if(p && *p++ == '.' && *p++ == '.' && *p++ == '\0')
+ return(TRUE);
+ return(FALSE);
+}
+
+static boolean
+issymbolic(char *dir, char *component)
+{
+#ifdef S_IFLNK
+ struct stat st;
+ char buf[ BUFSIZ ], **pp;
+
+ sprintf(buf, "%s%s%s", dir, *dir ? "/" : "", component);
+ for (pp=notdotdot; *pp; pp++)
+ if (strcmp(*pp, buf) == 0)
+ return (TRUE);
+ if (lstat(buf, &st) == 0
+ && (st.st_mode & S_IFMT) == S_IFLNK) {
+ *pp++ = copy(buf);
+ if (pp >= &notdotdot[ MAXDIRS ])
+ fatalerr("out of .. dirs, increase MAXDIRS\n");
+ return(TRUE);
+ }
+#endif
+ return(FALSE);
+}
+
+/*
+ * Occasionally, pathnames are created that look like .../x/../y
+ * Any of the 'x/..' sequences within the name can be eliminated.
+ * (but only if 'x' is not a symbolic link!!)
+ */
+static void
+remove_dotdot(char *path)
+{
+ register char *end, *from, *to, **cp;
+ char *components[ MAXFILES ],
+ newpath[ BUFSIZ ];
+ boolean component_copied;
+
+ /*
+ * slice path up into components.
+ */
+ to = newpath;
+ if (*path == '/')
+ *to++ = '/';
+ *to = '\0';
+ cp = components;
+ for (from=end=path; *end; end++)
+ if (*end == '/') {
+ while (*end == '/')
+ *end++ = '\0';
+ if (*from)
+ *cp++ = from;
+ from = end;
+ }
+ *cp++ = from;
+ *cp = NULL;
+
+ /*
+ * Recursively remove all 'x/..' component pairs.
+ */
+ cp = components;
+ while(*cp) {
+ if (!isdot(*cp) && !isdotdot(*cp) && isdotdot(*(cp+1))
+ && !issymbolic(newpath, *cp))
+ {
+ char **fp = cp + 2;
+ char **tp = cp;
+
+ do
+ *tp++ = *fp; /* move all the pointers down */
+ while (*fp++);
+ if (cp != components)
+ cp--; /* go back and check for nested ".." */
+ } else {
+ cp++;
+ }
+ }
+ /*
+ * Concatenate the remaining path elements.
+ */
+ cp = components;
+ component_copied = FALSE;
+ while(*cp) {
+ if (component_copied)
+ *to++ = '/';
+ component_copied = TRUE;
+ for (from = *cp; *from; )
+ *to++ = *from++;
+ *to = '\0';
+ cp++;
+ }
+ *to++ = '\0';
+
+ /*
+ * copy the reconstituted path back to our pointer.
+ */
+ strcpy(path, newpath);
+}
+
+/*
+ * Add an include file to the list of those included by 'file'.
+ */
+struct inclist *
+newinclude(char *newfile, char *incstring)
+{
+ register struct inclist *ip;
+
+ /*
+ * First, put this file on the global list of include files.
+ */
+ ip = inclistp++;
+ if (inclistp == inclist + MAXFILES - 1)
+ fatalerr("out of space: increase MAXFILES\n");
+ ip->i_file = copy(newfile);
+
+ if (incstring == NULL)
+ ip->i_incstring = ip->i_file;
+ else
+ ip->i_incstring = copy(incstring);
+
+ inclistnext = inclistp;
+ return(ip);
+}
+
+void
+included_by(struct inclist *ip, struct inclist *newfile)
+{
+ register int i;
+
+ if (ip == NULL)
+ return;
+ /*
+ * Put this include file (newfile) on the list of files included
+ * by 'file'. If 'file' is NULL, then it is not an include
+ * file itself (i.e. was probably mentioned on the command line).
+ * If it is already on the list, don't stick it on again.
+ */
+ if (ip->i_list == NULL) {
+ ip->i_list = (struct inclist **)
+ malloc(sizeof(struct inclist *) * ++ip->i_listlen);
+ ip->i_merged = (boolean *)
+ malloc(sizeof(boolean) * ip->i_listlen);
+ } else {
+ for (i=0; i<ip->i_listlen; i++)
+ if (ip->i_list[ i ] == newfile) {
+ i = strlen(newfile->i_file);
+ if (!(ip->i_flags & INCLUDED_SYM) &&
+ !(i > 2 &&
+ newfile->i_file[i-1] == 'c' &&
+ newfile->i_file[i-2] == '.'))
+ {
+ /* only bitch if ip has */
+ /* no #include SYMBOL lines */
+ /* and is not a .c file */
+ if (warn_multiple)
+ {
+ warning("%s includes %s more than once!\n",
+ ip->i_file, newfile->i_file);
+ warning1("Already have\n");
+ for (i=0; i<ip->i_listlen; i++)
+ warning1("\t%s\n", ip->i_list[i]->i_file);
+ }
+ }
+ return;
+ }
+ ip->i_list = (struct inclist **) realloc(ip->i_list,
+ sizeof(struct inclist *) * ++ip->i_listlen);
+ ip->i_merged = (boolean *)
+ realloc(ip->i_merged, sizeof(boolean) * ip->i_listlen);
+ }
+ ip->i_list[ ip->i_listlen-1 ] = newfile;
+ ip->i_merged[ ip->i_listlen-1 ] = FALSE;
+}
+
+void
+inc_clean (void)
+{
+ register struct inclist *ip;
+
+ for (ip = inclist; ip < inclistp; ip++) {
+ ip->i_flags &= ~MARKED;
+ }
+}
+
+struct inclist *
+inc_path(char *file, char *include, int type)
+{
+ static char path[ BUFSIZ ];
+ register char **pp, *p;
+ register struct inclist *ip;
+
+ /*
+ * Check all previously found include files for a path that
+ * has already been expanded.
+ */
+ if ((type == INCLUDE) || (type == INCLUDEDOT))
+ inclistnext = inclist;
+ ip = inclistnext;
+
+ for (; ip->i_file; ip++) {
+ if ((strcmp(ip->i_incstring, include) == 0) &&
+ !(ip->i_flags & INCLUDED_SYM)) {
+ inclistnext = ip + 1;
+ return ip;
+ }
+ }
+
+ if (inclistnext == inclist) {
+ /*
+ * If the path was surrounded by "" or is an absolute path,
+ * then check the exact path provided.
+ */
+ if ((type == INCLUDEDOT) ||
+ (type == INCLUDENEXTDOT) ||
+ (*include == '/')) {
+ if (does_file_exist(include))
+ return newinclude(include, include);
+ if (show_where_not)
+ warning1("\tnot in %s\n", include);
+ }
+
+ /*
+ * If the path was surrounded by "" see if this include file is
+ * in the directory of the file being parsed.
+ */
+ if ((type == INCLUDEDOT) || (type == INCLUDENEXTDOT)) {
+ for (p=file+strlen(file); p>file; p--)
+ if (*p == '/')
+ break;
+ if (p == file) {
+ strcpy(path, include);
+ } else {
+ strncpy(path, file, (p-file) + 1);
+ path[ (p-file) + 1 ] = '\0';
+ strcpy(path + (p-file) + 1, include);
+ }
+ remove_dotdot(path);
+ if (does_file_exist(path))
+ return newinclude(path, include);
+ if (show_where_not)
+ warning1("\tnot in %s\n", path);
+ }
+ }
+
+ /*
+ * Check the include directories specified. Standard include dirs
+ * should be at the end.
+ */
+ if ((type == INCLUDE) || (type == INCLUDEDOT))
+ includedirsnext = includedirs;
+ pp = includedirsnext;
+
+ for (; *pp; pp++) {
+ sprintf(path, "%s/%s", *pp, include);
+ remove_dotdot(path);
+ if (does_file_exist(path)) {
+ includedirsnext = pp + 1;
+ return newinclude(path, include);
+ }
+ if (show_where_not)
+ warning1("\tnot in %s\n", path);
+ }
+
+ return NULL;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c
new file mode 100644
index 0000000..a86866f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/main.c
@@ -0,0 +1,860 @@
+/* $Xorg: main.c,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+THE OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/main.c,v 3.32 2003/03/26 20:43:48 tsi Exp $ */
+
+#include "def.h"
+#ifdef hpux
+#define sigvec sigvector
+#endif /* hpux */
+
+#ifdef X_POSIX_C_SOURCE
+#define _POSIX_C_SOURCE X_POSIX_C_SOURCE
+#include <signal.h>
+#undef _POSIX_C_SOURCE
+#else
+#if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE)
+#include <signal.h>
+#else
+#define _POSIX_SOURCE
+#include <signal.h>
+#undef _POSIX_SOURCE
+#endif
+#endif
+
+#include <stdarg.h>
+
+#ifdef MINIX
+#define USE_CHMOD 1
+#endif
+
+#ifdef DEBUG
+int _debugmask;
+#endif
+
+/* #define DEBUG_DUMP */
+#ifdef DEBUG_DUMP
+#define DBG_PRINT(file, fmt, args) fprintf(file, fmt, args)
+#else
+#define DBG_PRINT(file, fmt, args) /* empty */
+#endif
+
+#define DASH_INC_PRE "#include \""
+#define DASH_INC_POST "\""
+
+char *ProgramName;
+
+char *directives[] = {
+ "if",
+ "ifdef",
+ "ifndef",
+ "else",
+ "endif",
+ "define",
+ "undef",
+ "include",
+ "line",
+ "pragma",
+ "error",
+ "ident",
+ "sccs",
+ "elif",
+ "eject",
+ "warning",
+ "include_next",
+ NULL
+};
+
+#define MAKEDEPEND
+#include "imakemdep.h" /* from config sources */
+#undef MAKEDEPEND
+
+struct inclist inclist[ MAXFILES ],
+ *inclistp = inclist,
+ *inclistnext = inclist,
+ maininclist;
+
+static char *filelist[ MAXFILES ];
+char *includedirs[ MAXDIRS + 1 ],
+ **includedirsnext = includedirs;
+char *notdotdot[ MAXDIRS ];
+static int cmdinc_count = 0;
+static char *cmdinc_list[ 2 * MAXINCFILES ];
+char *objprefix = "";
+char *objsuffix = OBJSUFFIX;
+static char *startat = "# DO NOT DELETE";
+int width = 78;
+static boolean append = FALSE;
+boolean printed = FALSE;
+boolean verbose = FALSE;
+boolean show_where_not = FALSE;
+/* Warn on multiple includes of same file */
+boolean warn_multiple = FALSE;
+
+static void setfile_cmdinc(struct filepointer *filep, long count, char **list);
+static void redirect(char *line, char *makefile);
+
+static
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+catch (int sig)
+{
+ fflush (stdout);
+ fatalerr ("got signal %d\n", sig);
+}
+
+#if defined(USG) || (defined(i386) && defined(SYSV)) || defined(WIN32) || defined(__UNIXOS2__) || defined(Lynx_22) || defined(__CYGWIN__)
+#define USGISH
+#endif
+
+#ifndef USGISH
+#ifdef X_NOT_POSIX
+#define sigaction sigvec
+#define sa_handler sv_handler
+#define sa_mask sv_mask
+#define sa_flags sv_flags
+#endif
+struct sigaction sig_act;
+#endif /* USGISH */
+
+int
+main(int argc, char *argv[])
+{
+ char **fp = filelist;
+ char **incp = includedirs;
+ char *p;
+ struct inclist *ip;
+ char *makefile = NULL;
+ struct filepointer *filecontent;
+ struct symtab *psymp = predefs;
+ char *endmarker = NULL;
+ char *defincdir = NULL;
+ char **undeflist = NULL;
+ int numundefs = 0, i;
+ register char offset;
+
+ ProgramName = argv[0];
+
+ while (psymp->s_name)
+ {
+ define2(psymp->s_name, psymp->s_value, &maininclist);
+ psymp++;
+ }
+ if (argc == 2 && argv[1][0] == '@') {
+ struct stat ast;
+ int afd;
+ char *args;
+ char **nargv;
+ int nargc;
+ char quotechar = '\0';
+
+ nargc = 1;
+ if ((afd = open(argv[1]+1, O_RDONLY)) < 0)
+ fatalerr("cannot open \"%s\"\n", argv[1]+1);
+ fstat(afd, &ast);
+ args = (char *)malloc(ast.st_size + 1);
+ if ((ast.st_size = read(afd, args, ast.st_size)) < 0)
+ fatalerr("failed to read %s\n", argv[1]+1);
+ args[ast.st_size] = '\0';
+ close(afd);
+ for (p = args; *p; p++) {
+ if (quotechar) {
+ if (quotechar == '\\' ||
+ (*p == quotechar && p[-1] != '\\'))
+ quotechar = '\0';
+ continue;
+ }
+ switch (*p) {
+ case '\\':
+ case '"':
+ case '\'':
+ quotechar = *p;
+ break;
+ case ' ':
+ case '\n':
+ *p = '\0';
+ if (p > args && p[-1])
+ nargc++;
+ break;
+ }
+ }
+ if (p[-1])
+ nargc++;
+ nargv = (char **)malloc(nargc * sizeof(char *));
+ nargv[0] = argv[0];
+ argc = 1;
+ for (p = args; argc < nargc; p += strlen(p) + 1)
+ if (*p) nargv[argc++] = p;
+ argv = nargv;
+ }
+ for(argc--, argv++; argc; argc--, argv++) {
+ /* if looking for endmarker then check before parsing */
+ if (endmarker && strcmp (endmarker, *argv) == 0) {
+ endmarker = NULL;
+ continue;
+ }
+ if (**argv != '-') {
+ /* treat +thing as an option for C++ */
+ if (endmarker && **argv == '+')
+ continue;
+ *fp++ = argv[0];
+ continue;
+ }
+ switch(argv[0][1]) {
+ case '-':
+ endmarker = &argv[0][2];
+ if (endmarker[0] == '\0') endmarker = "--";
+ break;
+ case 'D':
+ offset = 2;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ offset = 0;
+ }
+ /* offset +1 here since first def letter
+ * cannot be `=`
+ */
+ for (p = argv[0] + offset + 1; *p; p++)
+ if (*p == '=') {
+ *p = ' ';
+ break;
+ }
+ define(argv[0] + offset, &maininclist);
+ break;
+ case 'I':
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = argv[0]+2;
+ if (**(incp-1) == '\0') {
+ *(incp-1) = *(++argv);
+ argc--;
+ }
+ break;
+ case 'U':
+ /* Undef's override all -D's so save them up */
+ numundefs++;
+ if (numundefs == 1)
+ undeflist = malloc(sizeof(char *));
+ else
+ undeflist = realloc(undeflist,
+ numundefs * sizeof(char *));
+ offset = 2;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ offset = 0;
+ }
+ undeflist[numundefs - 1] = argv[0] + offset;
+ break;
+ case 'Y':
+ defincdir = argv[0]+2;
+ break;
+ /* do not use if endmarker processing */
+ case 'a':
+ if (endmarker) break;
+ append = TRUE;
+ break;
+ case 'w':
+ if (endmarker) break;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ width = atoi(argv[0]);
+ } else
+ width = atoi(argv[0]+2);
+ break;
+ case 'o':
+ if (endmarker) break;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ objsuffix = argv[0];
+ } else
+ objsuffix = argv[0]+2;
+ break;
+ case 'p':
+ if (endmarker) break;
+ if (argv[0][2] == '\0') {
+ argv++;
+ argc--;
+ objprefix = argv[0];
+ } else
+ objprefix = argv[0]+2;
+ break;
+ case 'v':
+ if (endmarker) break;
+ verbose = TRUE;
+#ifdef DEBUG
+ if (argv[0][2])
+ _debugmask = atoi(argv[0]+2);
+#endif
+ break;
+ case 's':
+ if (endmarker) break;
+ startat = argv[0]+2;
+ if (*startat == '\0') {
+ startat = *(++argv);
+ argc--;
+ }
+ if (*startat != '#')
+ fatalerr("-s flag's value should start %s\n",
+ "with '#'.");
+ break;
+ case 'f':
+ if (endmarker) break;
+ makefile = argv[0]+2;
+ if (*makefile == '\0') {
+ makefile = *(++argv);
+ argc--;
+ }
+ break;
+
+ case 'm':
+ warn_multiple = TRUE;
+ break;
+
+ /* Ignore -O, -g so we can just pass ${CFLAGS} to
+ makedepend
+ */
+ case 'O':
+ case 'g':
+ break;
+ case 'i':
+ if (strcmp(&argv[0][1],"include") == 0) {
+ char *buf;
+ if (argc<2)
+ fatalerr("option -include is a "
+ "missing its parameter\n");
+ if (cmdinc_count >= MAXINCFILES)
+ fatalerr("Too many -include flags.\n");
+ argc--;
+ argv++;
+ buf = malloc(strlen(DASH_INC_PRE) +
+ strlen(argv[0]) +
+ strlen(DASH_INC_POST) + 1);
+ if(!buf)
+ fatalerr("out of memory at "
+ "-include string\n");
+ cmdinc_list[2 * cmdinc_count + 0] = argv[0];
+ cmdinc_list[2 * cmdinc_count + 1] = buf;
+ cmdinc_count++;
+ break;
+ }
+ /* intentional fall through */
+ default:
+ if (endmarker) break;
+ /* fatalerr("unknown opt = %s\n", argv[0]); */
+ warning("ignoring option %s\n", argv[0]);
+ }
+ }
+ /* Now do the undefs from the command line */
+ for (i = 0; i < numundefs; i++)
+ undefine(undeflist[i], &maininclist);
+ if (numundefs > 0)
+ free(undeflist);
+
+ if (!defincdir) {
+#ifdef PREINCDIR
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = PREINCDIR;
+#endif
+#ifdef __UNIXOS2__
+ {
+ char *emxinc = getenv("C_INCLUDE_PATH");
+ /* can have more than one component */
+ if (emxinc) {
+ char *beg, *end;
+ beg= (char*)strdup(emxinc);
+ for (;;) {
+ end = (char*)strchr(beg,';');
+ if (end) *end = 0;
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many include dirs\n");
+ *incp++ = beg;
+ if (!end) break;
+ beg = end+1;
+ }
+ }
+ }
+#else /* !__UNIXOS2__, does not use INCLUDEDIR at all */
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = INCLUDEDIR;
+#endif
+
+#ifdef EXTRAINCDIR
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = EXTRAINCDIR;
+#endif
+
+#ifdef POSTINCDIR
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = POSTINCDIR;
+#endif
+ } else if (*defincdir) {
+ if (incp >= includedirs + MAXDIRS)
+ fatalerr("Too many -I flags.\n");
+ *incp++ = defincdir;
+ }
+
+ redirect(startat, makefile);
+
+ /*
+ * catch signals.
+ */
+#ifdef USGISH
+/* should really reset SIGINT to SIG_IGN if it was. */
+#ifdef SIGHUP
+ signal (SIGHUP, catch);
+#endif
+ signal (SIGINT, catch);
+#ifdef SIGQUIT
+ signal (SIGQUIT, catch);
+#endif
+ signal (SIGILL, catch);
+#ifdef SIGBUS
+ signal (SIGBUS, catch);
+#endif
+ signal (SIGSEGV, catch);
+#ifdef SIGSYS
+ signal (SIGSYS, catch);
+#endif
+#else
+ sig_act.sa_handler = catch;
+#if defined(_POSIX_SOURCE) || !defined(X_NOT_POSIX)
+ sigemptyset(&sig_act.sa_mask);
+ sigaddset(&sig_act.sa_mask, SIGINT);
+ sigaddset(&sig_act.sa_mask, SIGQUIT);
+#ifdef SIGBUS
+ sigaddset(&sig_act.sa_mask, SIGBUS);
+#endif
+ sigaddset(&sig_act.sa_mask, SIGILL);
+ sigaddset(&sig_act.sa_mask, SIGSEGV);
+ sigaddset(&sig_act.sa_mask, SIGHUP);
+ sigaddset(&sig_act.sa_mask, SIGPIPE);
+#ifdef SIGSYS
+ sigaddset(&sig_act.sa_mask, SIGSYS);
+#endif
+#else
+ sig_act.sa_mask = ((1<<(SIGINT -1))
+ |(1<<(SIGQUIT-1))
+#ifdef SIGBUS
+ |(1<<(SIGBUS-1))
+#endif
+ |(1<<(SIGILL-1))
+ |(1<<(SIGSEGV-1))
+ |(1<<(SIGHUP-1))
+ |(1<<(SIGPIPE-1))
+#ifdef SIGSYS
+ |(1<<(SIGSYS-1))
+#endif
+ );
+#endif /* _POSIX_SOURCE */
+ sig_act.sa_flags = 0;
+ sigaction(SIGHUP, &sig_act, (struct sigaction *)0);
+ sigaction(SIGINT, &sig_act, (struct sigaction *)0);
+ sigaction(SIGQUIT, &sig_act, (struct sigaction *)0);
+ sigaction(SIGILL, &sig_act, (struct sigaction *)0);
+#ifdef SIGBUS
+ sigaction(SIGBUS, &sig_act, (struct sigaction *)0);
+#endif
+ sigaction(SIGSEGV, &sig_act, (struct sigaction *)0);
+#ifdef SIGSYS
+ sigaction(SIGSYS, &sig_act, (struct sigaction *)0);
+#endif
+#endif /* USGISH */
+
+ /*
+ * now peruse through the list of files.
+ */
+ for(fp=filelist; *fp; fp++) {
+ DBG_PRINT(stderr,"file: %s\n",*fp);
+ filecontent = getfile(*fp);
+ setfile_cmdinc(filecontent, cmdinc_count, cmdinc_list);
+ ip = newinclude(*fp, (char *)NULL);
+
+ find_includes(filecontent, ip, ip, 0, FALSE);
+ freefile(filecontent);
+ recursive_pr_include(ip, ip->i_file, base_name(*fp));
+ inc_clean();
+ }
+ if (printed)
+ printf("\n");
+ return 0;
+}
+
+#ifdef __UNIXOS2__
+/*
+ * eliminate \r chars from file
+ */
+static int
+elim_cr(char *buf, int sz)
+{
+ int i,wp;
+ for (i= wp = 0; i<sz; i++) {
+ if (buf[i] != '\r')
+ buf[wp++] = buf[i];
+ }
+ return wp;
+}
+#endif
+
+struct filepointer *
+getfile(char *file)
+{
+ int fd;
+ struct filepointer *content;
+ struct stat st;
+
+ content = (struct filepointer *)malloc(sizeof(struct filepointer));
+ content->f_name = file;
+ if ((fd = open(file, O_RDONLY)) < 0) {
+ warning("cannot open \"%s\"\n", file);
+ content->f_p = content->f_base = content->f_end = (char *)malloc(1);
+ *content->f_p = '\0';
+ return(content);
+ }
+ fstat(fd, &st);
+ content->f_base = (char *)malloc(st.st_size+1);
+ if (content->f_base == NULL)
+ fatalerr("cannot allocate mem\n");
+ if ((st.st_size = read(fd, content->f_base, st.st_size)) < 0)
+ fatalerr("failed to read %s\n", file);
+#ifdef __UNIXOS2__
+ st.st_size = elim_cr(content->f_base,st.st_size);
+#endif
+ close(fd);
+ content->f_len = st.st_size+1;
+ content->f_p = content->f_base;
+ content->f_end = content->f_base + st.st_size;
+ *content->f_end = '\0';
+ content->f_line = 0;
+ content->cmdinc_count = 0;
+ content->cmdinc_list = NULL;
+ content->cmdinc_line = 0;
+ return(content);
+}
+
+void
+setfile_cmdinc(struct filepointer* filep, long count, char** list)
+{
+ filep->cmdinc_count = count;
+ filep->cmdinc_list = list;
+ filep->cmdinc_line = 0;
+}
+
+void
+freefile(struct filepointer *fp)
+{
+ free(fp->f_base);
+ free(fp);
+}
+
+char *copy(char *str)
+{
+ char *p = (char *)malloc(strlen(str) + 1);
+
+ strcpy(p, str);
+ return(p);
+}
+
+int
+match(char *str, char **list)
+{
+ int i;
+
+ for (i=0; *list; i++, list++)
+ if (strcmp(str, *list) == 0)
+ return(i);
+ return(-1);
+}
+
+/*
+ * Get the next line. We only return lines beginning with '#' since that
+ * is all this program is ever interested in.
+ */
+char *getnextline(struct filepointer *filep)
+{
+ char *p, /* walking pointer */
+ *eof, /* end of file pointer */
+ *bol; /* beginning of line pointer */
+ int lineno; /* line number */
+ boolean whitespace = FALSE;
+
+ /*
+ * Fake the "-include" line files in form of #include to the
+ * start of each file.
+ */
+ if (filep->cmdinc_line < filep->cmdinc_count) {
+ char *inc = filep->cmdinc_list[2 * filep->cmdinc_line + 0];
+ char *buf = filep->cmdinc_list[2 * filep->cmdinc_line + 1];
+ filep->cmdinc_line++;
+ sprintf(buf,"%s%s%s",DASH_INC_PRE,inc,DASH_INC_POST);
+ DBG_PRINT(stderr,"%s\n",buf);
+ return(buf);
+ }
+
+ p = filep->f_p;
+ eof = filep->f_end;
+ if (p >= eof)
+ return((char *)NULL);
+ lineno = filep->f_line;
+
+ for (bol = p--; ++p < eof; ) {
+ if ((bol == p) && ((*p == ' ') || (*p == '\t')))
+ {
+ /* Consume leading white-spaces for this line */
+ while (((p+1) < eof) && ((*p == ' ') || (*p == '\t')))
+ {
+ p++;
+ bol++;
+ }
+ whitespace = TRUE;
+ }
+
+ if (*p == '/' && (p+1) < eof && *(p+1) == '*') {
+ /* Consume C comments */
+ *(p++) = ' ';
+ *(p++) = ' ';
+ while (p < eof && *p) {
+ if (*p == '*' && (p+1) < eof && *(p+1) == '/') {
+ *(p++) = ' ';
+ *(p++) = ' ';
+ break;
+ }
+ if (*p == '\n')
+ lineno++;
+ *(p++) = ' ';
+ }
+ --p;
+ }
+ else if (*p == '/' && (p+1) < eof && *(p+1) == '/') {
+ /* Consume C++ comments */
+ *(p++) = ' ';
+ *(p++) = ' ';
+ while (p < eof && *p) {
+ if (*p == '\\' && (p+1) < eof &&
+ *(p+1) == '\n') {
+ *(p++) = ' ';
+ lineno++;
+ }
+ else if (*p == '?' && (p+3) < eof &&
+ *(p+1) == '?' &&
+ *(p+2) == '/' &&
+ *(p+3) == '\n') {
+ *(p++) = ' ';
+ *(p++) = ' ';
+ *(p++) = ' ';
+ lineno++;
+ }
+ else if (*p == '\n')
+ break; /* to process end of line */
+ *(p++) = ' ';
+ }
+ --p;
+ }
+ else if (*p == '\\' && (p+1) < eof && *(p+1) == '\n') {
+ /* Consume backslash line terminations */
+ *(p++) = ' ';
+ *p = ' ';
+ lineno++;
+ }
+ else if (*p == '?' && (p+3) < eof &&
+ *(p+1) == '?' && *(p+2) == '/' && *(p+3) == '\n') {
+ /* Consume trigraph'ed backslash line terminations */
+ *(p++) = ' ';
+ *(p++) = ' ';
+ *(p++) = ' ';
+ *p = ' ';
+ lineno++;
+ }
+ else if (*p == '\n') {
+ lineno++;
+ if (*bol == '#') {
+ char *cp;
+
+ *(p++) = '\0';
+ /* punt lines with just # (yacc generated) */
+ for (cp = bol+1;
+ *cp && (*cp == ' ' || *cp == '\t'); cp++);
+ if (*cp) goto done;
+ --p;
+ }
+ bol = p+1;
+ whitespace = FALSE;
+ }
+ }
+ if (*bol != '#')
+ bol = NULL;
+done:
+ if (bol && whitespace) {
+ warning("%s: non-portable whitespace encountered at line %d\n",
+ filep->f_name, lineno);
+ }
+ filep->f_p = p;
+ filep->f_line = lineno;
+#ifdef DEBUG_DUMP
+ if (bol)
+ DBG_PRINT(stderr,"%s\n",bol);
+#endif
+ return(bol);
+}
+
+/*
+ * Strip the file name down to what we want to see in the Makefile.
+ * It will have objprefix and objsuffix around it.
+ */
+char *base_name(char *file)
+{
+ char *p;
+
+ file = copy(file);
+ for(p=file+strlen(file); p>file && *p != '.'; p--) ;
+
+ if (*p == '.')
+ *p = '\0';
+ return(file);
+}
+
+#if defined(USG) && !defined(CRAY) && !defined(SVR4) && !defined(__UNIXOS2__) && !defined(clipper) && !defined(__clipper__)
+int rename (char *from, char *to)
+{
+ (void) unlink (to);
+ if (link (from, to) == 0) {
+ unlink (from);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+#endif /* USGISH */
+
+void
+redirect(char *line, char *makefile)
+{
+ struct stat st;
+ FILE *fdin, *fdout;
+ char backup[ BUFSIZ ],
+ buf[ BUFSIZ ];
+ boolean found = FALSE;
+ int len;
+
+ /*
+ * if makefile is "-" then let it pour onto stdout.
+ */
+ if (makefile && *makefile == '-' && *(makefile+1) == '\0') {
+ puts(line);
+ return;
+ }
+
+ /*
+ * use a default makefile is not specified.
+ */
+ if (!makefile) {
+ if (stat("Makefile", &st) == 0)
+ makefile = "Makefile";
+ else if (stat("makefile", &st) == 0)
+ makefile = "makefile";
+ else
+ fatalerr("[mM]akefile is not present\n");
+ }
+ else
+ stat(makefile, &st);
+ if ((fdin = fopen(makefile, "r")) == NULL)
+ fatalerr("cannot open \"%s\"\n", makefile);
+ sprintf(backup, "%s.bak", makefile);
+ unlink(backup);
+#if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
+ fclose(fdin);
+#endif
+ if (rename(makefile, backup) < 0)
+ fatalerr("cannot rename %s to %s\n", makefile, backup);
+#if defined(WIN32) || defined(__UNIXOS2__) || defined(__CYGWIN__)
+ if ((fdin = fopen(backup, "r")) == NULL)
+ fatalerr("cannot open \"%s\"\n", backup);
+#endif
+ if ((fdout = freopen(makefile, "w", stdout)) == NULL)
+ fatalerr("cannot open \"%s\"\n", backup);
+ len = strlen(line);
+ while (!found && fgets(buf, BUFSIZ, fdin)) {
+ if (*buf == '#' && strncmp(line, buf, len) == 0)
+ found = TRUE;
+ fputs(buf, fdout);
+ }
+ if (!found) {
+ if (verbose)
+ warning("Adding new delimiting line \"%s\" and dependencies...\n",
+ line);
+ puts(line); /* same as fputs(fdout); but with newline */
+ } else if (append) {
+ while (fgets(buf, BUFSIZ, fdin)) {
+ fputs(buf, fdout);
+ }
+ }
+ fflush(fdout);
+#if defined(USGISH) || defined(_SEQUENT_) || defined(USE_CHMOD)
+ chmod(makefile, st.st_mode);
+#else
+ fchmod(fileno(fdout), st.st_mode);
+#endif /* USGISH */
+}
+
+void
+fatalerr(char *msg, ...)
+{
+ va_list args;
+ fprintf(stderr, "%s: error: ", ProgramName);
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+ exit (1);
+}
+
+void
+warning(char *msg, ...)
+{
+ va_list args;
+ fprintf(stderr, "%s: warning: ", ProgramName);
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+}
+
+void
+warning1(char *msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ va_end(args);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man
new file mode 100644
index 0000000..595c87e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/mkdepend.man
@@ -0,0 +1,382 @@
+.\" $Xorg: mkdepend.man,v 1.5 2001/02/09 02:03:16 xorgcvs Exp $
+.\" Copyright (c) 1993, 1994, 1998 The Open Group
+.\"
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\"
+.\" 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 OPEN GROUP 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.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall not
+.\" be used in advertising or otherwise to promote the sale, use or other
+.\" dealing in this Software without prior written authorization from The
+.\" Open Group.
+.\"
+.\" $XFree86: xc/config/makedepend/mkdepend.man,v 1.7 2002/12/14 02:39:45 dawes Exp $
+.\"
+.TH MAKEDEPEND 1 __xorgversion__
+.UC 4
+.SH NAME
+makedepend \- create dependencies in makefiles
+.SH SYNOPSIS
+.B makedepend
+[
+.BI \-D name\fB=\fPdef
+] [
+.BI \-D name
+] [
+.BI \-I includedir
+] [
+.BI \-Y includedir
+] [
+.B \-a
+] [
+.BI \-f makefile
+] [
+.BI \-include \ file
+] [
+.BI \-o objsuffix
+] [
+.BI \-p objprefix
+] [
+.BI \-s string
+] [
+.BI \-w width
+] [
+.B \-v
+] [
+.B \-m
+] [
+\-\^\-
+.I otheroptions
+\-\^\-
+]
+.I sourcefile
+\&.\|.\|.
+.br
+.SH DESCRIPTION
+The
+.B makedepend
+program reads each
+.I sourcefile
+in sequence and parses it like a C-preprocessor,
+processing all
+.I #include,
+.I #define,
+.I #undef,
+.I #ifdef,
+.I #ifndef,
+.I #endif,
+.I #if,
+.I #elif
+and
+.I #else
+directives so that it can correctly tell which
+.I #include,
+directives would be used in a compilation.
+Any
+.I #include,
+directives can reference files having other
+.I #include
+directives, and parsing will occur in these files as well.
+.PP
+Every file that a
+.I sourcefile
+includes,
+directly or indirectly,
+is what
+.B makedepend
+calls a \fIdependency.\fP
+These dependencies are then written to a
+.I makefile
+in such a way that
+.B make(1)
+will know which object files must be recompiled when a dependency has changed.
+.PP
+By default,
+.B makedepend
+places its output in the file named
+.I makefile
+if it exists, otherwise
+.I Makefile.
+An alternate makefile may be specified with the
+.B \-f
+option.
+It first searches the makefile for
+the line
+.sp
+\& # DO NOT DELETE THIS LINE \-\^\- make depend depends on it.
+.sp
+or one provided with the
+.B \-s
+option,
+as a delimiter for the dependency output.
+If it finds it, it will delete everything
+following this to the end of the makefile
+and put the output after this line.
+If it doesn't find it, the program
+will append the string to the end of the makefile
+and place the output following that.
+For each
+.I sourcefile
+appearing on the command line,
+.B makedepend
+puts lines in the makefile of the form
+.sp
+ sourcefile.o:\0dfile .\|.\|.
+.sp
+Where \fIsourcefile.o\fP is the name from the command
+line with its suffix replaced with ``.o'',
+and \fIdfile\fP is a dependency discovered in a
+.I #include
+directive while parsing
+.I sourcefile
+or one of the files it included.
+.SH EXAMPLE
+Normally,
+.B makedepend
+will be used in a makefile target so that typing ``make depend'' will
+bring the dependencies up to date for the makefile.
+For example,
+.nf
+ SRCS\0=\0file1.c\0file2.c\0.\|.\|.
+ CFLAGS\0=\0\-O\0\-DHACK\0\-I\^.\^.\^/foobar\0\-xyz
+ depend:
+ makedepend\0\-\^\-\0$(CFLAGS)\0\-\^\-\0$(SRCS)
+.fi
+.SH OPTIONS
+The program
+will ignore any option that it does not understand so that you may use
+the same arguments that you would for
+.B cc(1).
+.TP 5
+.B \-D\fIname\fP=\fIdef\fP \fRor\fP \-D\fIname\fP
+Define.
+This places a definition for
+.I name
+in
+.B makedepend's
+symbol table.
+Without
+.I =def\|
+the symbol becomes defined as ``1''.
+.TP 5
+.B \-I\fIincludedir\fP
+Include directory.
+This option tells
+.B makedepend
+to prepend
+.I includedir
+to its list of directories to search when it encounters
+a
+.I #include
+directive.
+By default,
+.B makedepend
+only searches the standard include directories (usually /usr/include
+and possibly a compiler-dependent directory).
+.TP 5
+.B \-Y\fIincludedir\fP
+Replace all of the standard include directories with the single specified
+include directory; you can omit the
+.I includedir
+to simply prevent searching the standard include directories.
+.TP 5
+.B \-a
+Append the dependencies to the end of the file instead of replacing them.
+.TP 5
+.B \-f\fImakefile\fP
+Filename.
+This allows you to specify an alternate makefile in which
+.B makedepend
+can place its output.
+Specifying ``\-'' as the file name (i.e., \fB\-f\-\fP) sends the
+output to standard output instead of modifying an existing file.
+.TP 5
+.B \-include \fIfile\fP
+Process file as input, and include all the resulting output
+before processing the regular input file. This has the same
+affect as if the specified file is an include statement that
+appears before the very first line of the regular input file.
+.TP 5
+.B \-o\fIobjsuffix\fP
+Object file suffix.
+Some systems may have object files whose suffix is something other
+than ``.o''.
+This option allows you to specify another suffix, such as
+``.b'' with
+.I \-o.b
+or ``:obj''
+with
+.I \-o:obj
+and so forth.
+.TP 5
+.B \-p\fIobjprefix\fP
+Object file prefix.
+The prefix is prepended to the name of the object file. This is
+usually used to designate a different directory for the object file.
+The default is the empty string.
+.TP 5
+.B \-s\fIstring\fP
+Starting string delimiter.
+This option permits you to specify
+a different string for
+.B makedepend
+to look for in the makefile.
+.TP 5
+.B \-w\fIwidth\fP
+Line width.
+Normally,
+.B makedepend
+will ensure that every output line that it writes will be no wider than
+78 characters for the sake of readability.
+This option enables you to change this width.
+.TP 5
+.B \-v
+Verbose operation.
+This option causes
+.B makedepend
+to emit the list of files included by each input file.
+.TP 5
+.B \-m
+Warn about multiple inclusion.
+This option causes
+.B makedepend
+to produce a warning if any input file includes another file more than
+once. In previous versions of
+.B makedepend
+this was the default behavior; the default has been changed to better
+match the behavior of the C compiler, which does not consider multiple
+inclusion to be an error. This option is provided for backward
+compatibility, and to aid in debugging problems related to multiple
+inclusion.
+.TP 5
+.B "\-\^\- \fIoptions\fP \-\^\-"
+If
+.B makedepend
+encounters a double hyphen (\-\^\-) in the argument list,
+then any unrecognized argument following it
+will be silently ignored; a second double hyphen terminates this
+special treatment.
+In this way,
+.B makedepend
+can be made to safely ignore esoteric compiler arguments that might
+normally be found in a CFLAGS
+.B make
+macro (see the
+.B EXAMPLE
+section above).
+All options that
+.B makedepend
+recognizes and appear between the pair of double hyphens
+are processed normally.
+.SH ALGORITHM
+The approach used in this program enables it to run an order of magnitude
+faster than any other ``dependency generator'' I have ever seen.
+Central to this performance are two assumptions:
+that all files compiled by a single
+makefile will be compiled with roughly the same
+.I \-I
+and
+.I \-D
+options;
+and that most files in a single directory will include largely the
+same files.
+.PP
+Given these assumptions,
+.B makedepend
+expects to be called once for each makefile, with
+all source files that are maintained by the
+makefile appearing on the command line.
+It parses each source and include
+file exactly once, maintaining an internal symbol table
+for each.
+Thus, the first file on the command line will take an amount of time
+proportional to the amount of time that a normal C preprocessor takes.
+But on subsequent files, if it encounters an include file
+that it has already parsed, it does not parse it again.
+.PP
+For example,
+imagine you are compiling two files,
+.I file1.c
+and
+.I file2.c,
+they each include the header file
+.I header.h,
+and the file
+.I header.h
+in turn includes the files
+.I def1.h
+and
+.I def2.h.
+When you run the command
+.sp
+ makedepend\0file1.c\0file2.c
+.sp
+.B makedepend
+will parse
+.I file1.c
+and consequently,
+.I header.h
+and then
+.I def1.h
+and
+.I def2.h.
+It then decides that the dependencies for this file are
+.sp
+ file1.o:\0header.h\0def1.h\0def2.h
+.sp
+But when the program parses
+.I file2.c
+and discovers that it, too, includes
+.I header.h,
+it does not parse the file,
+but simply adds
+.I header.h,
+.I def1.h
+and
+.I def2.h
+to the list of dependencies for
+.I file2.o.
+.SH "SEE ALSO"
+cc(1), make(1)
+.SH BUGS
+.B makedepend
+parses, but does not currently evaluate, the SVR4 #predicate(token-list)
+preprocessor expression; such expressions are simply assumed to be true.
+This may cause the wrong
+.I #include
+directives to be evaluated.
+.PP
+Imagine you are parsing two files,
+say
+.I file1.c
+and
+.I file2.c,
+each includes the file
+.I def.h.
+The list of files that
+.I def.h
+includes might truly be different when
+.I def.h
+is included by
+.I file1.c
+than when it is included by
+.I file2.c.
+But once
+.B makedepend
+arrives at a list of dependencies for a file,
+it is cast in concrete.
+.SH AUTHOR
+Todd Brunhoff, Tektronix, Inc. and MIT Project Athena
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c
new file mode 100644
index 0000000..968d2c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/parse.c
@@ -0,0 +1,686 @@
+/* $Xorg: parse.c,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/parse.c,v 1.12 2002/02/26 05:09:10 tsi Exp $ */
+
+#include "def.h"
+
+extern char *directives[];
+extern struct inclist inclist[ MAXFILES ],
+ *inclistnext,
+ maininclist;
+extern char *includedirs[ ],
+ **includedirsnext;
+
+static int deftype (char *line, struct filepointer *filep,
+ struct inclist *file_red, struct inclist *file,
+ int parse_it);
+static int zero_value(char *filename, char *exp, struct filepointer *filep,
+ struct inclist *file_red);
+static int merge2defines(struct inclist *file1, struct inclist *file2);
+
+static int
+gobble(struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red)
+{
+ char *line;
+ int type;
+
+ while ((line = getnextline(filep))) {
+ switch(type = deftype(line, filep, file_red, file, FALSE)) {
+ case IF:
+ case IFFALSE:
+ case IFGUESSFALSE:
+ case IFDEF:
+ case IFNDEF:
+ type = gobble(filep, file, file_red);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ (void)gobble(filep, file, file_red);
+ break;
+ case ELSE:
+ case ENDIF:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line,
+ directives[type]));
+ return(type);
+ case DEFINE:
+ case UNDEF:
+ case INCLUDE:
+ case INCLUDEDOT:
+ case PRAGMA:
+ case ERROR:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ case WARNING:
+ case INCLUDENEXT:
+ case INCLUDENEXTDOT:
+ break;
+ case ELIF:
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ return(type);
+ case -1:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: unknown directive == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ }
+ return(-1);
+}
+
+/*
+ * Decide what type of # directive this line is.
+ */
+static int
+deftype (char *line, struct filepointer *filep,
+ struct inclist *file_red, struct inclist *file, int parse_it)
+{
+ register char *p;
+ char *directive, savechar, *q;
+ register int ret;
+
+ /*
+ * Parse the directive...
+ */
+ directive=line+1;
+ while (*directive == ' ' || *directive == '\t')
+ directive++;
+
+ p = directive;
+ while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
+ p++;
+ savechar = *p;
+ *p = '\0';
+ ret = match(directive, directives);
+ *p = savechar;
+
+ /* If we don't recognize this compiler directive or we happen to just
+ * be gobbling up text while waiting for an #endif or #elif or #else
+ * in the case of an #elif we must check the zero_value and return an
+ * ELIF or an ELIFFALSE.
+ */
+
+ if (ret == ELIF && !parse_it)
+ {
+ while (*p == ' ' || *p == '\t')
+ p++;
+ /*
+ * parse an expression.
+ */
+ debug(0,("%s, line %d: #elif %s ",
+ file->i_file, filep->f_line, p));
+ ret = zero_value(file->i_file, p, filep, file_red);
+ if (ret != IF)
+ {
+ debug(0,("false...\n"));
+ if (ret == IFFALSE)
+ return(ELIFFALSE);
+ else
+ return(ELIFGUESSFALSE);
+ }
+ else
+ {
+ debug(0,("true...\n"));
+ return(ELIF);
+ }
+ }
+
+ if (ret < 0 || ! parse_it)
+ return(ret);
+
+ /*
+ * now decide how to parse the directive, and do it.
+ */
+ while (*p == ' ' || *p == '\t')
+ p++;
+ q = p + strlen(p);
+ do {
+ q--;
+ } while (*q == ' ' || *q == '\t');
+ q[1] = '\0';
+ switch (ret) {
+ case IF:
+ /*
+ * parse an expression.
+ */
+ ret = zero_value(file->i_file, p, filep, file_red);
+ debug(0,("%s, line %d: %s #if %s\n",
+ file->i_file, filep->f_line, ret?"false":"true", p));
+ break;
+ case IFDEF:
+ case IFNDEF:
+ debug(0,("%s, line %d: #%s %s\n",
+ file->i_file, filep->f_line, directives[ret], p));
+ case UNDEF:
+ /*
+ * separate the name of a single symbol.
+ */
+ while (isalnum(*p) || *p == '_')
+ *line++ = *p++;
+ *line = '\0';
+ break;
+ case INCLUDE:
+ case INCLUDENEXT:
+ debug(2,("%s, line %d: #include%s %s\n",
+ file->i_file, filep->f_line,
+ (ret == INCLUDE) ? "" : "_next", p));
+
+ /* Support ANSI macro substitution */
+ while (1) {
+ struct symtab **sym;
+
+ if (!*p || *p == '"' || *p == '<')
+ break;
+
+ sym = isdefined(p, file_red, NULL);
+ if (!sym)
+ break;
+
+ p = (*sym)->s_value;
+ debug(3,("%s : #includes SYMBOL %s = %s\n",
+ file->i_incstring,
+ (*sym) -> s_name,
+ (*sym) -> s_value));
+ /* mark file as having included a 'soft include' */
+ file->i_flags |= INCLUDED_SYM;
+ }
+
+ /*
+ * Separate the name of the include file.
+ */
+ while (*p && *p != '"' && *p != '<')
+ p++;
+ if (! *p)
+ return(-2);
+ if (*p++ == '"') {
+ if (ret == INCLUDE)
+ ret = INCLUDEDOT;
+ else
+ ret = INCLUDENEXTDOT;
+ while (*p && *p != '"')
+ *line++ = *p++;
+ } else
+ while (*p && *p != '>')
+ *line++ = *p++;
+ *line = '\0';
+ break;
+ case DEFINE:
+ /*
+ * copy the definition back to the beginning of the line.
+ */
+ strcpy (line, p);
+ break;
+ case ELSE:
+ case ENDIF:
+ case ELIF:
+ case PRAGMA:
+ case ERROR:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ case WARNING:
+ debug(0,("%s, line %d: #%s\n",
+ file->i_file, filep->f_line, directives[ret]));
+ /*
+ * nothing to do.
+ */
+ break;
+ }
+ return(ret);
+}
+
+struct symtab **
+fdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
+{
+ struct inclist **ip;
+ struct symtab **val;
+ int i;
+ static int recurse_lvl = 0;
+
+ if (file->i_flags & DEFCHECKED)
+ return(NULL);
+ debug(2,("Looking for %s in %s\n", symbol, file->i_file));
+ file->i_flags |= DEFCHECKED;
+ if ((val = slookup(symbol, file)))
+ debug(1,("%s defined in %s as %s\n",
+ symbol, file->i_file, (*val)->s_value));
+ if (val == NULL && file->i_list)
+ {
+ for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
+ if (file->i_merged[i]==FALSE) {
+ val = fdefined(symbol, *ip, srcfile);
+ file->i_merged[i]=merge2defines(file,*ip);
+ if (val!=NULL) break;
+ }
+ }
+ else if (val != NULL && srcfile != NULL) *srcfile = file;
+ recurse_lvl--;
+ file->i_flags &= ~DEFCHECKED;
+
+ return(val);
+}
+
+struct symtab **
+isdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
+{
+ struct symtab **val;
+
+ if ((val = slookup(symbol, &maininclist))) {
+ debug(1,("%s defined on command line\n", symbol));
+ if (srcfile != NULL) *srcfile = &maininclist;
+ return(val);
+ }
+ if ((val = fdefined(symbol, file, srcfile)))
+ return(val);
+ debug(1,("%s not defined in %s\n", symbol, file->i_file));
+ return(NULL);
+}
+
+/*
+ * Return type based on if the #if expression evaluates to 0
+ */
+static int
+zero_value(char *filename,
+ char *exp,
+ struct filepointer *filep,
+ struct inclist *file_red)
+{
+ if (cppsetup(filename, exp, filep, file_red))
+ return(IFFALSE);
+ else
+ return(IF);
+}
+
+void
+define2(char *name, char *val, struct inclist *file)
+{
+ int first, last, below;
+ register struct symtab **sp = NULL, **dest;
+ struct symtab *stab;
+
+ /* Make space if it's needed */
+ if (file->i_defs == NULL)
+ {
+ file->i_defs = (struct symtab **)
+ malloc(sizeof (struct symtab*) * SYMTABINC);
+ file->i_ndefs = 0;
+ }
+ else if (!(file->i_ndefs % SYMTABINC))
+ file->i_defs = (struct symtab **)
+ realloc(file->i_defs,
+ sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
+
+ if (file->i_defs == NULL)
+ fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+ below = first = 0;
+ last = file->i_ndefs - 1;
+ while (last >= first)
+ {
+ /* Fast inline binary search */
+ register char *s1;
+ register char *s2;
+ register int middle = (first + last) / 2;
+
+ /* Fast inline strchr() */
+ s1 = name;
+ s2 = file->i_defs[middle]->s_name;
+ while (*s1++ == *s2++)
+ if (s2[-1] == '\0') break;
+
+ /* If exact match, set sp and break */
+ if (*--s1 == *--s2)
+ {
+ sp = file->i_defs + middle;
+ break;
+ }
+
+ /* If name > i_defs[middle] ... */
+ if (*s1 > *s2)
+ {
+ below = first;
+ first = middle + 1;
+ }
+ /* else ... */
+ else
+ {
+ below = last = middle - 1;
+ }
+ }
+
+ /* Search is done. If we found an exact match to the symbol name,
+ just replace its s_value */
+ if (sp != NULL)
+ {
+ debug(1,("redefining %s from %s to %s in file %s\n",
+ name, (*sp)->s_value, val, file->i_file));
+ free((*sp)->s_value);
+ (*sp)->s_value = copy(val);
+ return;
+ }
+
+ sp = file->i_defs + file->i_ndefs++;
+ dest = file->i_defs + below + 1;
+ while (sp > dest)
+ {
+ *sp = sp[-1];
+ sp--;
+ }
+ stab = (struct symtab *) malloc(sizeof (struct symtab));
+ if (stab == NULL)
+ fatalerr("malloc()/realloc() failure in insert_defn()\n");
+
+ debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
+ stab->s_name = copy(name);
+ stab->s_value = copy(val);
+ *sp = stab;
+}
+
+void
+define(char *def, struct inclist *file)
+{
+ char *val;
+
+ /* Separate symbol name and its value */
+ val = def;
+ while (isalnum(*val) || *val == '_')
+ val++;
+ if (*val)
+ *val++ = '\0';
+ while (*val == ' ' || *val == '\t')
+ val++;
+
+ if (!*val)
+ val = "1";
+ define2(def, val, file);
+}
+
+struct symtab **
+slookup(char *symbol, struct inclist *file)
+{
+ register int first = 0;
+ register int last = file->i_ndefs - 1;
+
+ if (file) while (last >= first)
+ {
+ /* Fast inline binary search */
+ register char *s1;
+ register char *s2;
+ register int middle = (first + last) / 2;
+
+ /* Fast inline strchr() */
+ s1 = symbol;
+ s2 = file->i_defs[middle]->s_name;
+ while (*s1++ == *s2++)
+ if (s2[-1] == '\0') break;
+
+ /* If exact match, we're done */
+ if (*--s1 == *--s2)
+ {
+ return file->i_defs + middle;
+ }
+
+ /* If symbol > i_defs[middle] ... */
+ if (*s1 > *s2)
+ {
+ first = middle + 1;
+ }
+ /* else ... */
+ else
+ {
+ last = middle - 1;
+ }
+ }
+ return(NULL);
+}
+
+static int
+merge2defines(struct inclist *file1, struct inclist *file2)
+{
+ int i;
+
+ if ((file1==NULL) || (file2==NULL) ||
+ !(file2->i_flags & FINISHED))
+ return 0;
+
+ for (i=0; i < file2->i_listlen; i++)
+ if (file2->i_merged[i]==FALSE)
+ return 0;
+
+ {
+ int first1 = 0;
+ int last1 = file1->i_ndefs - 1;
+
+ int first2 = 0;
+ int last2 = file2->i_ndefs - 1;
+
+ int first=0;
+ struct symtab** i_defs = NULL;
+ int deflen=file1->i_ndefs+file2->i_ndefs;
+
+ debug(2,("merging %s into %s\n",
+ file2->i_file, file1->i_file));
+
+ if (deflen>0)
+ {
+ /* make sure deflen % SYMTABINC == 0 is still true */
+ deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
+ i_defs=(struct symtab**)
+ malloc(deflen*sizeof(struct symtab*));
+ if (i_defs==NULL) return 0;
+ }
+
+ while ((last1 >= first1) && (last2 >= first2))
+ {
+ char *s1=file1->i_defs[first1]->s_name;
+ char *s2=file2->i_defs[first2]->s_name;
+
+ if (strcmp(s1,s2) < 0)
+ i_defs[first++]=file1->i_defs[first1++];
+ else if (strcmp(s1,s2) > 0)
+ i_defs[first++]=file2->i_defs[first2++];
+ else /* equal */
+ {
+ i_defs[first++]=file2->i_defs[first2++];
+ first1++;
+ }
+ }
+ while (last1 >= first1)
+ {
+ i_defs[first++]=file1->i_defs[first1++];
+ }
+ while (last2 >= first2)
+ {
+ i_defs[first++]=file2->i_defs[first2++];
+ }
+
+ if (file1->i_defs) free(file1->i_defs);
+ file1->i_defs=i_defs;
+ file1->i_ndefs=first;
+
+ return 1;
+ }
+}
+
+void
+undefine(char *symbol, struct inclist *file)
+{
+ register struct symtab **ptr;
+ struct inclist *srcfile;
+ while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
+ {
+ srcfile->i_ndefs--;
+ for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
+ *ptr = ptr[1];
+ }
+}
+
+int
+find_includes(struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red, int recursion, boolean failOK)
+{
+ struct inclist *inclistp;
+ char **includedirsp;
+ register char *line;
+ register int type;
+ boolean recfailOK;
+
+ while ((line = getnextline(filep))) {
+ switch(type = deftype(line, filep, file_red, file, TRUE)) {
+ case IF:
+ doif:
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ while ((type == ELIF) || (type == ELIFFALSE) ||
+ (type == ELIFGUESSFALSE))
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ gobble(filep, file, file_red);
+ break;
+ case IFFALSE:
+ case IFGUESSFALSE:
+ doiffalse:
+ if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
+ recfailOK = TRUE;
+ else
+ recfailOK = failOK;
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ find_includes(filep, file,
+ file_red, recursion+1, recfailOK);
+ else
+ if (type == ELIF)
+ goto doif;
+ else
+ if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
+ goto doiffalse;
+ break;
+ case IFDEF:
+ case IFNDEF:
+ if ((type == IFDEF && isdefined(line, file_red, NULL))
+ || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
+ debug(1,(type == IFNDEF ?
+ "line %d: %s !def'd in %s via %s%s\n" : "",
+ filep->f_line, line,
+ file->i_file, file_red->i_file, ": doit"));
+ type = find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ gobble(filep, file, file_red);
+ }
+ else {
+ debug(1,(type == IFDEF ?
+ "line %d: %s !def'd in %s via %s%s\n" : "",
+ filep->f_line, line,
+ file->i_file, file_red->i_file, ": gobble"));
+ type = gobble(filep, file, file_red);
+ if (type == ELSE)
+ find_includes(filep, file,
+ file_red, recursion+1, failOK);
+ else if (type == ELIF)
+ goto doif;
+ else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
+ goto doiffalse;
+ }
+ break;
+ case ELSE:
+ case ELIFFALSE:
+ case ELIFGUESSFALSE:
+ case ELIF:
+ if (!recursion)
+ gobble(filep, file, file_red);
+ case ENDIF:
+ if (recursion)
+ return(type);
+ case DEFINE:
+ define(line, file);
+ break;
+ case UNDEF:
+ if (!*line) {
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: incomplete undef == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ undefine(line, file_red);
+ break;
+ case INCLUDE:
+ case INCLUDEDOT:
+ case INCLUDENEXT:
+ case INCLUDENEXTDOT:
+ inclistp = inclistnext;
+ includedirsp = includedirsnext;
+ debug(2,("%s, reading %s, includes %s\n",
+ file_red->i_file, file->i_file, line));
+ add_include(filep, file, file_red, line, type, failOK);
+ inclistnext = inclistp;
+ includedirsnext = includedirsp;
+ break;
+ case ERROR:
+ case WARNING:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: %s\n",
+ filep->f_line, line);
+ break;
+
+ case PRAGMA:
+ case IDENT:
+ case SCCS:
+ case EJECT:
+ break;
+ case -1:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: unknown directive == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ case -2:
+ warning("%s", file_red->i_file);
+ if (file_red != file)
+ warning1(" (reading %s)", file->i_file);
+ warning1(", line %d: incomplete include == \"%s\"\n",
+ filep->f_line, line);
+ break;
+ }
+ }
+ file->i_flags |= FINISHED;
+ debug(2,("finished with %s\n", file->i_file));
+ return(-1);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c
new file mode 100644
index 0000000..e864793
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/mkdepend/pr.c
@@ -0,0 +1,124 @@
+/* $Xorg: pr.c,v 1.4 2001/02/09 02:03:16 xorgcvs Exp $ */
+/*
+
+Copyright (c) 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/* $XFree86: xc/config/makedepend/pr.c,v 1.5 2001/12/14 19:53:21 dawes Exp $ */
+
+#include "def.h"
+
+extern struct inclist inclist[ MAXFILES ],
+ *inclistp;
+extern char *objprefix;
+extern char *objsuffix;
+extern int width;
+extern boolean printed;
+extern boolean verbose;
+extern boolean show_where_not;
+
+void
+add_include(struct filepointer *filep, struct inclist *file,
+ struct inclist *file_red, char *include, int type,
+ boolean failOK)
+{
+ register struct inclist *newfile;
+ register struct filepointer *content;
+
+ /*
+ * First decide what the pathname of this include file really is.
+ */
+ newfile = inc_path(file->i_file, include, type);
+ if (newfile == NULL) {
+ if (failOK)
+ return;
+ if (file != file_red)
+ warning("%s (reading %s, line %d): ",
+ file_red->i_file, file->i_file, filep->f_line);
+ else
+ warning("%s, line %d: ", file->i_file, filep->f_line);
+ warning1("cannot find include file \"%s\"\n", include);
+ show_where_not = TRUE;
+ newfile = inc_path(file->i_file, include, type);
+ show_where_not = FALSE;
+ }
+
+ if (newfile) {
+ included_by(file, newfile);
+ if (!(newfile->i_flags & SEARCHED)) {
+ newfile->i_flags |= SEARCHED;
+ content = getfile(newfile->i_file);
+ find_includes(content, newfile, file_red, 0, failOK);
+ freefile(content);
+ }
+ }
+}
+
+static void
+pr(struct inclist *ip, char *file, char *base)
+{
+ static char *lastfile;
+ static int current_len;
+ register int len, i;
+ char buf[ BUFSIZ ];
+
+ printed = TRUE;
+ len = strlen(ip->i_file)+1;
+ if (current_len + len > width || file != lastfile) {
+ lastfile = file;
+ sprintf(buf, "\n%s%s%s: %s", objprefix, base, objsuffix,
+ ip->i_file);
+ len = current_len = strlen(buf);
+ }
+ else {
+ buf[0] = ' ';
+ strcpy(buf+1, ip->i_file);
+ current_len += len;
+ }
+ fwrite(buf, len, 1, stdout);
+
+ /*
+ * If verbose is set, then print out what this file includes.
+ */
+ if (! verbose || ip->i_list == NULL || ip->i_flags & NOTIFIED)
+ return;
+ ip->i_flags |= NOTIFIED;
+ lastfile = NULL;
+ printf("\n# %s includes:", ip->i_file);
+ for (i=0; i<ip->i_listlen; i++)
+ printf("\n#\t%s", ip->i_list[ i ]->i_incstring);
+}
+
+void
+recursive_pr_include(struct inclist *head, char *file, char *base)
+{
+ int i;
+
+ if (head->i_flags & MARKED)
+ return;
+ head->i_flags |= MARKED;
+ if (head->i_file != file)
+ pr(head, file, base);
+ for (i=0; i<head->i_listlen; i++)
+ recursive_pr_include(head->i_list[ i ], file, base);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl
new file mode 100644
index 0000000..2f0e4fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/nfspwd.pl
@@ -0,0 +1,50 @@
+#! perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+require "fastcwd.pl";
+
+$_ = &fastcwd;
+if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) {
+ print("$_\n");
+} elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o)
+ && readlink("/u/$user") eq "/usr/people/$user") {
+ print("/u/$user/$rest\n");
+} else {
+ chop($host = `hostname`);
+ print("/h/$host$_\n");
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c
new file mode 100644
index 0000000..b6ca0e3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.c
@@ -0,0 +1,481 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+** Netscape portable install command.
+**
+** Brendan Eich, 7/20/95
+*/
+#include <stdio.h> /* OSF/1 requires this before grp.h, so put it first */
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <utime.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "pathsub.h"
+
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#ifdef SUNOS4
+#include "sunos4.h"
+#endif
+
+#ifdef NEXTSTEP
+#include <bsd/libc.h>
+#endif
+
+#ifdef __QNX__
+#include <unix.h>
+#endif
+
+#ifdef NEED_S_ISLNK
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK)
+#endif
+#endif
+
+#ifndef _DIRECTORY_SEPARATOR
+#define _DIRECTORY_SEPARATOR "/"
+#endif /* _DIRECTORY_SEPARATOR */
+
+#ifdef NEED_FCHMOD_PROTO
+extern int fchmod(int fildes, mode_t mode);
+#endif
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+ "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
+ " %*s [-DdltR] file [file ...] directory\n",
+ program, (int) strlen(program), "");
+ exit(2);
+}
+
+static int
+mkdirs(char *path, mode_t mode)
+{
+ char *cp;
+ struct stat sb;
+ int res;
+ int l;
+
+ /* strip trailing "/." */
+ l = strlen(path);
+ if(l > 1 && path[l - 1] == '.' && path[l - 2] == '/')
+ path[l - 2] = 0;
+
+ while (*path == '/' && path[1] == '/')
+ path++;
+ for (cp = strrchr(path, '/'); cp && cp != path && *(cp - 1) == '/'; cp--);
+ if (cp && cp != path) {
+ *cp = '\0';
+ if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(path, mode) < 0) {
+ return -1;
+ }
+ *cp = '/';
+ }
+
+ res = mkdir(path, mode);
+ if ((res != 0) && (errno == EEXIST))
+ return 0;
+ else
+ return res;
+}
+
+static uid_t
+touid(char *owner)
+{
+ struct passwd *pw;
+ uid_t uid;
+ char *cp;
+
+ pw = getpwnam(owner);
+ if (pw)
+ return pw->pw_uid;
+ uid = strtol(owner, &cp, 0);
+ if (uid == 0 && cp == owner)
+ fail("cannot find uid for %s", owner);
+ return uid;
+}
+
+static gid_t
+togid(char *group)
+{
+ struct group *gr;
+ gid_t gid;
+ char *cp;
+
+ gr = getgrnam(group);
+ if (gr)
+ return gr->gr_gid;
+ gid = strtol(group, &cp, 0);
+ if (gid == 0 && cp == group)
+ fail("cannot find gid for %s", group);
+ return gid;
+}
+
+static void
+copyfile( char *name, char *toname, mode_t mode, char *group, char *owner,
+ int dotimes, uid_t uid, gid_t gid )
+{
+ int fromfd, tofd = -1, cc, wc, exists;
+ char buf[BUFSIZ], *bp;
+ struct stat sb, tosb;
+ struct utimbuf utb;
+
+ exists = (lstat(toname, &tosb) == 0);
+
+ fromfd = open(name, O_RDONLY);
+ if (fromfd < 0 || fstat(fromfd, &sb) < 0)
+ fail("cannot access %s", name);
+ if (exists) {
+ if (S_ISREG(tosb.st_mode)) {
+ /* See if we can open it. This is more reliable than 'access'. */
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ }
+ if (tofd < 0) {
+ (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ }
+ }
+ if (tofd < 0) {
+ tofd = open(toname, O_CREAT | O_WRONLY, 0666);
+ if (tofd < 0)
+ fail("cannot create %s", toname);
+ }
+
+ bp = buf;
+ while ((cc = read(fromfd, bp, sizeof buf)) > 0)
+ {
+ while ((wc = write(tofd, bp, (unsigned int)cc)) > 0)
+ {
+ if ((cc -= wc) == 0)
+ break;
+ bp += wc;
+ }
+ if (wc < 0)
+ fail("cannot write to %s", toname);
+ }
+ if (cc < 0)
+ fail("cannot read from %s", name);
+
+ if (ftruncate(tofd, sb.st_size) < 0)
+ fail("cannot truncate %s", toname);
+#if !defined(VMS)
+ if (dotimes)
+ {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0)
+ fail("cannot set times of %s", toname);
+ }
+#ifdef HAVE_FCHMOD
+ if (fchmod(tofd, mode) < 0)
+#else
+ if (chmod(toname, mode) < 0)
+#endif
+ fail("cannot change mode of %s", toname);
+#endif
+ if ((owner || group) && fchown(tofd, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+
+ /* Must check for delayed (NFS) write errors on close. */
+ if (close(tofd) < 0)
+ fail("cannot write to %s", toname);
+ close(fromfd);
+#if defined(VMS)
+ if (chmod(toname, (mode & (S_IREAD | S_IWRITE))) < 0)
+ fail("cannot change mode of %s", toname);
+ if (dotimes)
+ {
+ utb.actime = sb.st_atime;
+ utb.modtime = sb.st_mtime;
+ if (utime(toname, &utb) < 0)
+ fail("cannot set times of %s", toname);
+ }
+#endif
+}
+
+static void
+copydir( char *from, char *to, mode_t mode, char *group, char *owner,
+ int dotimes, uid_t uid, gid_t gid)
+{
+ int i;
+ DIR *dir;
+ struct dirent *ep;
+ struct stat sb;
+ char *base, *destdir, *direntry, *destentry;
+
+ base = xbasename(from);
+
+ /* create destination directory */
+ destdir = xmalloc((unsigned int)(strlen(to) + 1 + strlen(base) + 1));
+ sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
+ if (mkdirs(destdir, mode) != 0) {
+ fail("cannot make directory %s\n", destdir);
+ return;
+ }
+
+ dir = opendir(from);
+
+ direntry = xmalloc((unsigned int)PATH_MAX);
+ destentry = xmalloc((unsigned int)PATH_MAX);
+
+ while ((ep = readdir(dir)))
+ {
+ if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
+ continue;
+
+ sprintf(direntry, "%s/%s", from, ep->d_name);
+ sprintf(destentry, "%s%s%s", destdir, _DIRECTORY_SEPARATOR, ep->d_name);
+
+ if (stat(direntry, &sb) == 0 && S_ISDIR(sb.st_mode))
+ copydir( direntry, destdir, mode, group, owner, dotimes, uid, gid );
+ else
+ copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
+ }
+
+ free(direntry);
+ free(destentry);
+ closedir(dir);
+}
+
+int
+main(int argc, char **argv)
+{
+ int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
+ mode_t mode = 0755;
+ char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
+ uid_t uid;
+ gid_t gid;
+ struct stat sb, tosb, fromsb;
+ struct utimbuf utb;
+
+ program = argv[0];
+ cwd = linkname = linkprefix = owner = group = 0;
+ onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
+
+ while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
+ switch (opt) {
+ case 'C':
+ cwd = optarg;
+ break;
+ case 'D':
+ onlydir = 1;
+ break;
+ case 'd':
+ dodir = 1;
+ break;
+ case 'l':
+ dolink = 1;
+ break;
+ case 'L':
+ linkprefix = optarg;
+ lplen = strlen(linkprefix);
+ dolink = 1;
+ break;
+ case 'R':
+ dolink = dorelsymlink = 1;
+ break;
+ case 'm':
+ mode = strtoul(optarg, &cp, 8);
+ if (mode == 0 && cp == optarg)
+ usage();
+ break;
+ case 'o':
+ owner = optarg;
+ break;
+ case 'g':
+ group = optarg;
+ break;
+ case 't':
+ dotimes = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc < 2 - onlydir)
+ usage();
+
+ todir = argv[argc-1];
+ if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
+ mkdirs(todir, 0777) < 0) {
+ fail("cannot make directory %s", todir);
+ }
+ if (onlydir)
+ return 0;
+
+ if (!cwd) {
+#ifndef NEEDS_GETCWD
+#ifndef GETCWD_CANT_MALLOC
+ cwd = getcwd(0, PATH_MAX);
+#else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getcwd(cwd, PATH_MAX);
+#endif
+#else
+ cwd = malloc(PATH_MAX + 1);
+ cwd = getwd(cwd);
+#endif
+ }
+
+ xchdir(todir);
+#ifndef NEEDS_GETCWD
+#ifndef GETCWD_CANT_MALLOC
+ todir = getcwd(0, PATH_MAX);
+#else
+ todir = malloc(PATH_MAX + 1);
+ todir = getcwd(todir, PATH_MAX);
+#endif
+#else
+ todir = malloc(PATH_MAX + 1);
+ todir = getwd(todir);
+#endif
+ tdlen = strlen(todir);
+ xchdir(cwd);
+ tdlen = strlen(todir);
+
+ uid = owner ? touid(owner) : (uid_t)(-1);
+ gid = group ? togid(group) : (gid_t)(-1);
+
+ while (--argc > 0) {
+ name = *argv++;
+ len = strlen(name);
+ base = xbasename(name);
+ bnlen = strlen(base);
+ toname = xmalloc((unsigned int)(tdlen + 1 + bnlen + 1));
+ sprintf(toname, "%s%s%s", todir, _DIRECTORY_SEPARATOR, base);
+ exists = (lstat(toname, &tosb) == 0);
+
+ if (dodir) {
+ /* -d means create a directory, always */
+ if (exists && !S_ISDIR(tosb.st_mode)) {
+ (void) unlink(toname);
+ exists = 0;
+ }
+ if (!exists && mkdir(toname, mode) < 0)
+ fail("cannot make directory %s", toname);
+ if ((owner || group) && chown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+ } else if (dolink) {
+ if (access(name, R_OK) != 0) {
+ fail("cannot access %s", name);
+ }
+ if (*name == '/') {
+ /* source is absolute pathname, link to it directly */
+ linkname = 0;
+ } else {
+ if (linkprefix) {
+ /* -L implies -l and prefixes names with a $cwd arg. */
+ len += lplen + 1;
+ linkname = xmalloc((unsigned int)(len + 1));
+ sprintf(linkname, "%s/%s", linkprefix, name);
+ } else if (dorelsymlink) {
+ /* Symlink the relative path from todir to source name. */
+ linkname = xmalloc(PATH_MAX);
+
+ if (*todir == '/') {
+ /* todir is absolute: skip over common prefix. */
+ lplen = relatepaths(todir, cwd, linkname);
+ strcpy(linkname + lplen, name);
+ } else {
+ /* todir is named by a relative path: reverse it. */
+ reversepath(todir, name, len, linkname);
+ xchdir(cwd);
+ }
+
+ len = strlen(linkname);
+ }
+ name = linkname;
+ }
+
+ /* Check for a pre-existing symlink with identical content. */
+ if ((exists && (!S_ISLNK(tosb.st_mode) ||
+ readlink(toname, buf, sizeof buf) != len ||
+ strncmp(buf, name, (unsigned int)len) != 0)) ||
+ ((stat(name, &fromsb) == 0) &&
+ (fromsb.st_mtime > tosb.st_mtime))) {
+ (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
+ exists = 0;
+ }
+ if (!exists && symlink(name, toname) < 0)
+ fail("cannot make symbolic link %s", toname);
+#ifdef HAVE_LCHOWN
+ if ((owner || group) && lchown(toname, uid, gid) < 0)
+ fail("cannot change owner of %s", toname);
+#endif
+
+ if (linkname) {
+ free(linkname);
+ linkname = 0;
+ }
+ } else {
+ /* Copy from name to toname, which might be the same file. */
+ if( stat(name, &sb) == 0 && S_IFDIR & sb.st_mode )
+ {
+ /* then is directory: must explicitly create destination dir */
+ /* and manually copy files over */
+ copydir( name, todir, mode, group, owner, dotimes, uid, gid );
+ }
+ else
+ {
+ copyfile(name, toname, mode, group, owner, dotimes, uid, gid);
+ }
+ }
+
+ free(toname);
+ }
+
+ free(cwd);
+ free(todir);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py
new file mode 100644
index 0000000..fd4e253
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/nsinstall.py
@@ -0,0 +1,139 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla.
+#
+# The Initial Developer of the Original Code is
+# the Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Axel Hecht <axel@pike.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+# This is a partial python port of nsinstall.
+# It's intended to be used when there's no natively compile nsinstall
+# available, and doesn't intend to be fully equivalent.
+# Its major use is for l10n repackaging on systems that don't have
+# a full build environment set up.
+# The basic limitation is, it doesn't even try to link and ignores
+# all related options.
+
+from optparse import OptionParser
+import os
+import os.path
+import sys
+import shutil
+
+usage = "usage: %prog [options] arg1 [arg2 ...] target-directory"
+p = OptionParser(usage=usage)
+
+p.add_option('-D', action="store_true",
+ help="Create a single directory only")
+p.add_option('-t', action="store_true",
+ help="Preserve time stamp")
+p.add_option('-m', action="store",
+ help="Set mode", metavar="mode")
+p.add_option('-d', action="store_true",
+ help="Create directories in target")
+p.add_option('-R', action="store_true",
+ help="Use relative symbolic links (ignored)")
+p.add_option('-l', action="store_true",
+ help="Create link (ignored)")
+p.add_option('-L', action="store", metavar="linkprefix",
+ help="Link prefix (ignored)")
+
+# The remaining arguments are not used in our tree, thus they're not
+# implented.
+def BadArg(option, opt, value, parser):
+ parser.error('option not supported: %s' % opt)
+
+p.add_option('-C', action="callback", metavar="CWD",
+ callback=BadArg,
+ help="NOT SUPPORTED")
+p.add_option('-o', action="callback", callback=BadArg,
+ help="Set owner (NOT SUPPORTED)", metavar="owner")
+p.add_option('-g', action="callback", callback=BadArg,
+ help="Set group (NOT SUPPORTED)", metavar="group")
+
+(options, args) = p.parse_args()
+
+if options.m:
+ # mode is specified
+ try:
+ options.m = int(options.m, 8)
+ except:
+ sys.stderr.write('nsinstall: ' + options.m + ' is not a valid mode\n')
+ sys.exit(1)
+
+# just create one directory?
+if options.D:
+ if len(args) != 1:
+ sys.exit(1)
+ if os.path.exists(args[0]):
+ if not os.path.isdir(args[0]):
+ sys.stderr.write('nsinstall: ' + args[0] + ' is not a directory\n')
+ sys.exit(1)
+ if options.m:
+ os.chmod(args[0], options.m)
+ sys.exit()
+ if options.m:
+ os.makedirs(args[0], options.m)
+ else:
+ os.makedirs(args[0])
+ sys.exit()
+
+# nsinstall arg1 [...] directory
+if len(args) < 2:
+ p.error('not enough arguments')
+
+# set up handler
+if options.d:
+ # we're supposed to create directories
+ def handleTarget(srcpath, targetpath):
+ # target directory was already created, just use mkdir
+ os.mkdir(dest)
+else:
+ # we're supposed to copy files
+ def handleTarget(srcpath, targetpath):
+ if options.t:
+ shutil.copy2(srcpath, targetpath)
+ else:
+ shutil.copy(srcpath, targetpath)
+
+# the last argument is the target directory
+target = args.pop()
+# ensure target directory
+if not os.path.isdir(target):
+ os.makedirs(target)
+
+for f in args:
+ dest = os.path.join(target,
+ os.path.basename(os.path.normpath(f)))
+ handleTarget(f, dest)
+ if options.m:
+ os.chmod(dest, options.m)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c
new file mode 100644
index 0000000..8384e5f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.c
@@ -0,0 +1,247 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <assert.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "pathsub.h"
+
+#ifdef USE_REENTRANT_LIBC
+#include <libc_r.h>
+#endif
+
+#ifdef SUNOS4
+#include "sunos4.h"
+#endif
+
+#ifndef D_INO
+#define D_INO d_ino
+#endif
+
+char *program;
+
+void
+fail(char *format, ...)
+{
+ int error;
+ va_list ap;
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_INIT_R();
+#endif
+
+ error = errno;
+ fprintf(stderr, "%s: ", program);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if (error) {
+
+#ifdef USE_REENTRANT_LIBC
+ R_STRERROR_R(errno);
+ fprintf(stderr, ": %s", r_strerror_r);
+#else
+ fprintf(stderr, ": %s", strerror(errno));
+#endif
+ }
+
+ putc('\n', stderr);
+ exit(1);
+}
+
+char *
+getcomponent(char *path, char *name)
+{
+ if (*path == '\0')
+ return 0;
+ if (*path == '/') {
+ *name++ = '/';
+ } else {
+ do {
+ *name++ = *path++;
+ } while (*path != '/' && *path != '\0');
+ }
+ *name = '\0';
+ while (*path == '/')
+ path++;
+ return path;
+}
+
+#ifdef LAME_READDIR
+#include <sys/param.h>
+/*
+** The static buffer in Unixware's readdir is too small.
+*/
+struct dirent *readdir(DIR *d)
+{
+ static struct dirent *buf = NULL;
+
+ if(buf == NULL)
+ buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN);
+ return(readdir_r(d, buf));
+}
+#endif
+
+char *
+ino2name(ino_t ino, char *dir)
+{
+ DIR *dp;
+ struct dirent *ep;
+ char *name;
+
+ dp = opendir("..");
+ if (!dp)
+ fail("cannot read parent directory");
+ for (;;) {
+ if (!(ep = readdir(dp)))
+ fail("cannot find current directory");
+ if (ep->D_INO == ino)
+ break;
+ }
+ name = xstrdup(ep->d_name);
+ closedir(dp);
+ return name;
+}
+
+void *
+xmalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p)
+ fail("cannot allocate %u bytes", size);
+ return p;
+}
+
+char *
+xstrdup(char *s)
+{
+ return strcpy(xmalloc(strlen(s) + 1), s);
+}
+
+char *
+xbasename(char *path)
+{
+ char *cp;
+
+ while ((cp = strrchr(path, '/')) && cp[1] == '\0')
+ *cp = '\0';
+ if (!cp) return path;
+ return cp + 1;
+}
+
+void
+xchdir(char *dir)
+{
+ if (chdir(dir) < 0)
+ fail("cannot change directory to %s", dir);
+}
+
+int
+relatepaths(char *from, char *to, char *outpath)
+{
+ char *cp, *cp2;
+ int len;
+ char buf[NAME_MAX];
+
+ assert(*from == '/' && *to == '/');
+ for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
+ if (*cp == '\0')
+ break;
+ while (cp[-1] != '/')
+ cp--, cp2--;
+ if (cp - 1 == to) {
+ /* closest common ancestor is /, so use full pathname */
+ len = strlen(strcpy(outpath, to));
+ if (outpath[len] != '/') {
+ outpath[len++] = '/';
+ outpath[len] = '\0';
+ }
+ } else {
+ len = 0;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ strcpy(outpath + len, "../");
+ len += 3;
+ }
+ while ((cp = getcomponent(cp, buf)) != 0) {
+ sprintf(outpath + len, "%s/", buf);
+ len += strlen(outpath + len);
+ }
+ }
+ return len;
+}
+
+void
+reversepath(char *inpath, char *name, int len, char *outpath)
+{
+ char *cp, *cp2;
+ char buf[NAME_MAX];
+ struct stat sb;
+
+ cp = strcpy(outpath + PATH_MAX - (len + 1), name);
+ cp2 = inpath;
+ while ((cp2 = getcomponent(cp2, buf)) != 0) {
+ if (strcmp(buf, ".") == 0)
+ continue;
+ if (strcmp(buf, "..") == 0) {
+ if (stat(".", &sb) < 0)
+ fail("cannot stat current directory");
+ name = ino2name(sb.st_ino, "..");
+ len = strlen(name);
+ cp -= len + 1;
+ strcpy(cp, name);
+ cp[len] = '/';
+ free(name);
+ xchdir("..");
+ } else {
+ cp -= 3;
+ strncpy(cp, "../", 3);
+ xchdir(buf);
+ }
+ }
+ strcpy(outpath, cp);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h
new file mode 100644
index 0000000..ab1a7fe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/pathsub.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef pathsub_h___
+#define pathsub_h___
+/*
+** Pathname subroutines.
+**
+** Brendan Eich, 8/29/95
+*/
+#include <limits.h>
+#include <sys/types.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+/*
+ * Just prevent stupidity
+ */
+#undef NAME_MAX
+#define NAME_MAX 256
+
+extern char *program;
+
+extern void fail(char *format, ...);
+extern char *getcomponent(char *path, char *name);
+extern char *ino2name(ino_t ino, char *dir);
+extern void *xmalloc(size_t size);
+extern char *xstrdup(char *s);
+extern char *xbasename(char *path);
+extern void xchdir(char *dir);
+
+/* Relate absolute pathnames from and to returning the result in outpath. */
+extern int relatepaths(char *from, char *to, char *outpath);
+
+/* XXX changes current working directory -- caveat emptor */
+extern void reversepath(char *inpath, char *name, int len, char *outpath);
+
+#endif /* pathsub_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl
new file mode 100644
index 0000000..3da6654
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/preprocessor.pl
@@ -0,0 +1,671 @@
+#!/usr/bin/perl -w
+# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
+#
+# Preprocessor
+# Version 1.1
+#
+# Copyright (c) 2002, 2003, 2004 by Ian Hickson
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# Thanks to bryner and bsmedberg for suggestions.
+# Thanks to jon rekai for a patch to not require File::Spec 0.8.
+
+use strict;
+
+# takes as arguments the files to process
+# defaults to stdin
+# output to stdout
+
+my $stack = new stack;
+my $marker = '#';
+
+# command line arguments
+my @includes;
+while ($_ = $ARGV[0], defined($_) && /^-./) {
+ shift;
+ last if /^--$/os;
+ if (/^-D(.*)$/os) {
+ for ($1) {
+ if (/^([\w\.]+)=(.*)$/os) {
+ $stack->define($1, $2);
+ } elsif (/^([\w\.]+)$/os) {
+ $stack->define($1, 1);
+ } else {
+ die "$0: invalid argument to -D: $_\n";
+ }
+ }
+ } elsif (/^-F(.*)$/os) {
+ for ($1) {
+ if (/^(\w+)$/os) {
+ $stack->filter($1, 1);
+ } else {
+ die "$0: invalid argument to -F: $_\n";
+ }
+ }
+ } elsif (/^-I(.*)$/os) {
+ push(@includes, $1);
+ } elsif (/^-E$/os) {
+ foreach (keys %ENV) {
+ # define all variables that have valid names
+ $stack->define($_, $ENV{$_}) unless m/\W/;
+ }
+ } elsif (/^-d$/os) {
+ $stack->{'dependencies'} = 1;
+ } elsif (/^--line-endings=crlf$/os) {
+ $stack->{'lineEndings'} = "\x0D\x0A";
+ } elsif (/^--line-endings=cr$/os) {
+ $stack->{'lineEndings'} = "\x0D";
+ } elsif (/^--line-endings=lf$/os) {
+ $stack->{'lineEndings'} = "\x0A";
+ } elsif (/^--line-endings=(.+)$/os) {
+ die "$0: unrecognised line ending: $1\n";
+ } elsif (/^--marker=(.)$/os) {
+ $marker = $1;
+ } else {
+ die "$0: invalid argument: $_\n";
+ }
+}
+unshift(@ARGV, '-') unless @ARGV;
+unshift(@ARGV, @includes);
+
+# do the work
+foreach (@ARGV) { include($stack, $_); }
+exit(0);
+
+########################################################################
+
+package main;
+use File::Spec;
+use File::Spec::Unix; # on all platforms, because the #include syntax is unix-based
+
+# Note: Ideally we would use File::Spec 0.8. When this becomes
+# possible, add "0.8" to the first "use" line above, then replace
+# occurrences of "::_0_8::" with "->" below. And remove the code for
+# File::Spec 0.8 much lower down the file.
+
+sub include {
+ my($stack, $filename) = @_;
+ my $directory = $stack->{'variables'}->{'DIRECTORY'};
+ if ($filename ne '-') {
+ $filename = File::Spec::_0_8::rel2abs($filename, $directory);
+ # splitpath expects forward-slash paths on windows, so we have to
+ # change the slashes if using Activestate Perl.
+ $filename =~ s?\\?/?g if "$^O" eq "MSWin32";
+ my($volume, $path) = File::Spec::_0_8::splitpath($filename);
+ $directory = File::Spec::_0_8::catpath($volume, $path, '');
+ }
+ local $stack->{'variables'}->{'DIRECTORY'} = $directory;
+ local $stack->{'variables'}->{'FILE'} = $filename;
+ local $stack->{'variables'}->{'LINE'} = 0;
+ local *FILE;
+ open(FILE, $filename) or die "Couldn't open $filename: $!\n";
+ my $lineout = 0;
+ while (<FILE>) {
+ # on cygwin, line endings are screwed up, so normalise them.
+ s/[\x0D\x0A]+$/\n/os if ($^O eq 'msys' || $^O eq 'cygwin' || "$^O" eq "MSWin32");
+ $stack->newline;
+ if (/^\Q$marker\E([a-z]+)\n?$/os) { # argumentless processing instruction
+ process($stack, $1);
+ } elsif (/^\Q$marker\E([a-z]+)\s(.*?)\n?$/os) { # processing instruction with arguments
+ process($stack, $1, $2);
+ } elsif (/^\Q$marker\E/os) { # comment
+ # ignore it
+ } elsif ($stack->enabled) {
+ next if $stack->{'dependencies'};
+
+ # set the current line number in JavaScript if necessary
+ my $linein = $stack->{'variables'}->{'LINE'};
+ if (++$lineout != $linein) {
+ if ($filename =~ /\.js(|\.in)$/o) {
+ $stack->print("//\@line $linein \"$filename\"\n")
+ }
+ $lineout = $linein;
+ }
+
+ # print it, including any newlines
+ $stack->print(filtered($stack, $_));
+ }
+ }
+ close(FILE);
+}
+
+sub process {
+ my($stack, $instruction, @arguments) = @_;
+ my $method = 'preprocessor'->can($instruction);
+ if (not defined($method)) {
+ fatal($stack, 'unknown instruction', $instruction);
+ }
+ eval { &$method($stack, @arguments) };
+ if ($@) {
+ fatal($stack, "error evaluating $instruction:", $@);
+ }
+}
+
+sub filtered {
+ my($stack, $text) = @_;
+ foreach my $filter (sort keys %{$stack->{'filters'}}) {
+ next unless $stack->{'filters'}->{$filter};
+ my $method = 'filter'->can($filter);
+ if (not defined($method)) {
+ fatal($stack, 'unknown filter', $filter);
+ }
+ $text = eval { &$method($stack, $text) };
+ if ($@) {
+ fatal($stack, "error using $filter:", $@);
+ }
+ }
+ return $text;
+}
+
+sub fatal {
+ my $stack = shift;
+ my $filename = $stack->{'variables'}->{'FILE'};
+ local $" = ' ';
+ print STDERR "$0:$filename:$.: @_\n";
+ exit(1);
+}
+
+
+########################################################################
+
+package stack;
+
+# condition evaluated just prior to this context was false
+use constant COND_FALSE => 0;
+
+# condition evaluated just prior to this context was true
+use constant COND_TRUE => 1;
+
+# some prior condition at this level already evaluated to true (or a
+# parent condition evaluated to false or must be ignored), so we're
+# ignoring all remaining conditions at current level (and nested
+# conditions, too)
+use constant COND_COMPLETED => 2;
+
+sub new {
+ return bless {
+ 'variables' => {
+ # %ENV,
+ 'LINE' => 0, # the line number in the source file
+ 'DIRECTORY' => '', # current directory
+ 'FILE' => '', # source filename
+ '1' => 1, # for convenience (the constant '1' is thus true)
+ },
+ 'filters' => {
+ # filters
+ },
+ 'values' => [], # the value of the last condition evaluated at the nth level
+ 'lastConditionState' => [], # whether the condition in the nth-level context was true, false, or not applicable
+ 'conditionState' => COND_TRUE,
+ 'dependencies' => 0, # whether we are showing dependencies
+ 'lineEndings' => "\n", # default to platform conventions
+ };
+}
+
+sub newline {
+ my $self = shift;
+ $self->{'variables'}->{'LINE'}++;
+}
+
+sub define {
+ my $self = shift;
+ my($variable, $value) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ $self->{'variables'}->{$variable} = $value;
+}
+
+sub defined {
+ my $self = shift;
+ my($variable) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ return defined($self->{'variables'}->{$variable});
+}
+
+sub undefine {
+ my $self = shift;
+ my($variable) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ delete($self->{'variables'}->{$variable});
+}
+
+sub get {
+ my $self = shift;
+ my($variable, $required) = @_;
+ die "not a valid variable name: '$variable'\n" if $variable =~ m/[^\w\.]/;
+ my $value = $self->{'variables'}->{$variable};
+ if (defined($value)) {
+ return $value;
+ } else {
+ die "variable '$variable' is not defined\n" if $required;
+ return '';
+ }
+}
+
+sub replace {
+ my $self = shift;
+ my ($value) = @_;
+
+ ${$self->{'values'}}[-1] = $value;
+ $self->{'conditionState'} = $self->{'conditionState'} != COND_FALSE
+ ? COND_COMPLETED
+ : $value ? COND_TRUE : COND_FALSE;
+}
+
+sub push {
+ my $self = shift;
+ my($value) = @_;
+
+ push(@{$self->{'values'}}, $value);
+ my $lastCondition = $self->{'conditionState'};
+ push(@{$self->{'lastConditionState'}}, $lastCondition);
+ $self->{'conditionState'} = $lastCondition != COND_TRUE
+ ? COND_COMPLETED
+ : $value ? COND_TRUE : COND_FALSE;
+}
+
+sub pop {
+ my $self = shift;
+ $self->{'conditionState'} = pop(@{$self->{'lastConditionState'}});
+ return pop(@{$self->{'values'}});
+}
+
+sub enabled {
+ my $self = shift;
+ return $self->{'conditionState'} == COND_TRUE;
+}
+
+sub disabled {
+ my $self = shift;
+ return $self->{'conditionState'} != COND_TRUE;
+}
+
+sub filter {
+ my $self = shift;
+ my($filter, $value) = @_;
+ die "not a valid filter name: '$filter'\n" if $filter =~ m/\W/;
+ $self->{'filters'}->{$filter} = $value;
+}
+
+sub expand {
+ my $self = shift;
+ my($line) = @_;
+ $line =~ s/__(\w+)__/$self->get($1)/gose;
+ return $line;
+}
+
+sub print {
+ my $self = shift;
+ return if $self->{'dependencies'};
+ foreach my $line (@_) {
+ if (chomp $line) {
+ CORE::print("$line$self->{'lineEndings'}");
+ } else {
+ CORE::print($line);
+ }
+ }
+}
+
+sub visit {
+ my $self = shift;
+ my($filename) = @_;
+ my $directory = $stack->{'variables'}->{'DIRECTORY'};
+ $filename = File::Spec::_0_8::abs2rel(File::Spec::_0_8::rel2abs($filename, $directory));
+ CORE::print("$filename\n");
+}
+
+########################################################################
+
+package preprocessor;
+
+sub define {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $argument = shift;
+ for ($argument) {
+ /^(\w+)\s(.*)$/os && do {
+ return $stack->define($1, $2);
+ };
+ /^(\w+)$/os && do {
+ return $stack->define($1, 1);
+ };
+ die "invalid argument: '$_'\n";
+ }
+}
+
+sub undef {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ $stack->undefine(@_);
+}
+
+sub ifdef {
+ my $stack = shift;
+ my $variable = shift;
+ my $replace = defined(shift);
+ die "argument expected\n" unless defined($variable);
+ if ($replace) {
+ $stack->replace($stack->defined($variable));
+ } else {
+ $stack->push($stack->defined($variable));
+ }
+}
+
+sub ifndef {
+ my $stack = shift;
+ my $variable = shift;
+ my $replace = defined(shift);
+ die "argument expected\n" unless defined($variable);
+ if ($replace) {
+ $stack->replace(not $stack->defined($variable));
+ } else {
+ $stack->push(not $stack->defined($variable));
+ }
+}
+
+sub if {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ my $argument = shift;
+ my $replace = defined(shift);
+ for ($argument) {
+ /^(\w+)==(.*)$/os && do {
+ # equality
+ if ($replace) {
+ return $stack->replace($stack->get($1) eq $2);
+ } else {
+ return $stack->push($stack->get($1) eq $2);
+ }
+ };
+ /^(\w+)!=(.*)$/os && do {
+ # inequality
+ if ($replace) {
+ return $stack->replace($stack->get($1) ne $2);
+ } else {
+ return $stack->push($stack->get($1) ne $2);
+ }
+ };
+ /^(\w+)$/os && do {
+ # true value
+ if ($replace) {
+ return $stack->replace($stack->get($1));
+ } else {
+ return $stack->push($stack->get($1));
+ }
+ };
+ /^!(\w+)$/os && do {
+ # false value
+ if ($replace) {
+ return $stack->replace(not $stack->get($1));
+ } else {
+ return $stack->push(not $stack->get($1));
+ }
+ };
+ die "invalid argument: '$_'\n";
+ }
+}
+
+sub else {
+ my $stack = shift;
+ die "argument unexpected\n" if @_;
+ $stack->replace(1);
+}
+
+sub elif {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ &if($stack, @_, 1);
+}
+
+sub elifdef {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ &ifdef($stack, @_, 1);
+}
+
+sub elifndef {
+ my $stack = shift;
+ die "argument expected\n" unless @_;
+ &ifndef($stack, @_, 1);
+}
+
+sub endif {
+ my $stack = shift;
+ die "argument unexpected\n" if @_;
+ $stack->pop;
+}
+
+sub error {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $line = $stack->expand(@_);
+ die "$line\n";
+}
+
+sub expand {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $line = $stack->expand(@_);
+ $stack->print("$line\n");
+}
+
+sub literal {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $line = shift;
+ $stack->print("$line\n");
+}
+
+sub include {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ my $filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath(@_));
+ if ($stack->{'dependencies'}) {
+ $stack->visit($filename);
+ } else {
+ main::include($stack, $filename);
+ }
+}
+
+sub includesubst {
+ my ($stack, $filename) = @_;
+ return if $stack->disabled;
+ die "argument expected\n" unless $filename;
+ $filename =~ s/@(\w+)@/$stack->get($1, 1)/gose;
+ $filename = File::Spec::_0_8::catpath(File::Spec::_0_8::splitpath($filename));
+ if ($stack->{'dependencies'}) {
+ $stack->visit($filename);
+ } else {
+ main::include($stack, $filename);
+ }
+}
+
+sub filter {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ foreach (split(/\s/os, shift)) {
+ $stack->filter($_, 1);
+ }
+}
+
+sub unfilter {
+ my $stack = shift;
+ return if $stack->disabled;
+ die "argument expected\n" unless @_;
+ foreach (split(/\s/os, shift)) {
+ $stack->filter($_, 0);
+ }
+}
+
+
+########################################################################
+
+package filter;
+
+sub emptyLines {
+ my($stack, $text) = @_;
+ $text = "" if $text eq "\n";
+ return $text;
+}
+
+sub spaces {
+ my($stack, $text) = @_;
+ $text =~ s/ +/ /gos; # middle spaces
+ $text =~ s/^ //gos; # start spaces
+ $text =~ s/ (\n?)$/$1/gos; # end spaces
+ return $text;
+}
+
+sub slashslash {
+ my($stack, $text) = @_;
+ $text =~ s|//.*?(\n?)$|$1|gos;
+ return $text;
+}
+
+sub substitution {
+ my($stack, $text) = @_;
+ $text =~ s/@(\w+)@/$stack->get($1, 1)/gose;
+ return $text;
+}
+
+sub attemptSubstitution {
+ my($stack, $text) = @_;
+ $text =~ s/@(\w+)@/$stack->get($1, 0)/gose;
+ return $text;
+}
+
+########################################################################
+
+########################################################################
+# This code is from File::Spec::Unix 0.8.
+# It is not considered a part of the preprocessor.pl source file
+# This code is licensed under the same license as File::Spec itself.
+
+package File::Spec::_0_8;
+
+use Cwd;
+
+sub rel2abs {
+ my ($path, $base) = @_;
+ if ( ! File::Spec->file_name_is_absolute( $path ) ) {
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd() ;
+ } elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
+ $base = rel2abs( $base );
+ } else {
+ $base = File::Spec->canonpath( $base );
+ }
+ $path = File::Spec->catdir( $base, $path );
+ }
+ return File::Spec->canonpath( $path );
+}
+
+sub splitdir {
+ return split m|/|, $_[1], -1; # Preserve trailing fields
+}
+
+sub splitpath {
+ my ($path, $nofile) = @_;
+
+ my ($volume,$directory,$file) = ('','','');
+
+ if ( $nofile ) {
+ $directory = $path;
+ }
+ else {
+ $path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
+ $directory = $1;
+ $file = $2;
+ }
+
+ return ($volume,$directory,$file);
+}
+
+sub catpath {
+ my ($volume,$directory,$file) = @_;
+
+ if ( $directory ne '' &&
+ $file ne '' &&
+ substr( $directory, -1 ) ne '/' &&
+ substr( $file, 0, 1 ) ne '/'
+ ) {
+ $directory .= "/$file" ;
+ }
+ else {
+ $directory .= $file ;
+ }
+
+ return $directory ;
+}
+
+sub abs2rel {
+ my($path,$base) = @_;
+
+ # Clean up $path
+ if ( ! File::Spec->file_name_is_absolute( $path ) ) {
+ $path = rel2abs( $path ) ;
+ }
+ else {
+ $path = File::Spec->canonpath( $path ) ;
+ }
+
+ # Figure out the effective $base and clean it up.
+ if ( !defined( $base ) || $base eq '' ) {
+ $base = cwd();
+ }
+ elsif ( ! File::Spec->file_name_is_absolute( $base ) ) {
+ $base = rel2abs( $base ) ;
+ }
+ else {
+ $base = File::Spec->canonpath( $base ) ;
+ }
+
+ # Now, remove all leading components that are the same
+ my @pathchunks = File::Spec::_0_8::splitdir( $path);
+ my @basechunks = File::Spec::_0_8::splitdir( $base);
+
+ while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
+ shift @pathchunks ;
+ shift @basechunks ;
+ }
+
+ $path = CORE::join( '/', @pathchunks );
+ $base = CORE::join( '/', @basechunks );
+
+ # $base now contains the directories the resulting relative path
+ # must ascend out of before it can descend to $path_directory. So,
+ # replace all names with $parentDir
+ $base =~ s|[^/]+|..|g ;
+
+ # Glue the two together, using a separator if necessary, and preventing an
+ # empty result.
+ if ( $path ne '' && $base ne '' ) {
+ $path = "$base/$path" ;
+ } else {
+ $path = "$base$path" ;
+ }
+
+ return File::Spec->canonpath( $path ) ;
+}
+
+# End code from File::Spec::Unix 0.8.
+########################################################################
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl
new file mode 100644
index 0000000..8853268
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth-nt.pl
@@ -0,0 +1,48 @@
+#! perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+require "/ns/config/fastcwd.pl";
+
+$cur = &fastcwd;
+chdir($ARGV[0]);
+$newcur = &fastcwd;
+$newcurlen = length($newcur);
+
+# Skip common separating / unless $newcur is "/"
+$cur = substr($cur, $newcurlen + ($newcurlen > 1));
+print $cur;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl
new file mode 100644
index 0000000..3ec4272
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/revdepth.pl
@@ -0,0 +1,51 @@
+#! perl
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+unshift(@INC, '/usr/lib/perl');
+unshift(@INC, '/usr/local/lib/perl');
+
+require "fastcwd.pl";
+
+$cur = &fastcwd;
+chdir($ARGV[0]);
+$newcur = &fastcwd;
+$newcurlen = length($newcur);
+
+# Skip common separating / unless $newcur is "/"
+$cur = substr($cur, $newcurlen + ($newcurlen > 1));
+print $cur;
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk
new file mode 100644
index 0000000..6168216
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/rules.mk
@@ -0,0 +1,2269 @@
+# vim:set ts=8 sw=8 sts=8 noet:
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Chase Phillips <chase@mozilla.org>
+# Benjamin Smedberg <benjamin@smedbergs.us>
+# Jeff Walden <jwalden+code@mit.edu>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+NO_DIST_INSTALL = 1
+
+ifndef topsrcdir
+topsrcdir = $(DEPTH)
+endif
+
+ifndef MOZILLA_DIR
+MOZILLA_DIR = $(topsrcdir)
+endif
+
+ifndef INCLUDED_CONFIG_MK
+include $(topsrcdir)/config/config.mk
+endif
+
+ifndef INCLUDED_VERSION_MK
+include $(topsrcdir)/config/version.mk
+endif
+
+REPORT_BUILD = @echo $(notdir $<)
+
+ifeq ($(OS_ARCH),OS2)
+EXEC =
+else
+EXEC = exec
+endif
+
+# ELOG prints out failed command when building silently (gmake -s).
+ifneq (,$(findstring -s,$(MAKEFLAGS)))
+ ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh
+else
+ ELOG :=
+endif
+
+ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
+ifndef GNU_CC
+_LIBNAME_RELATIVE_PATHS=1
+endif
+endif
+
+ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
+PWD := $(shell pwd)
+_VPATH_SRCS = $(if $(filter /%,$<),$<,$(PWD)/$<)
+else
+_VPATH_SRCS = $<
+endif
+
+# Add $(DIST)/lib to VPATH so that -lfoo dependencies are followed
+VPATH += $(DIST)/lib
+ifdef LIBXUL_SDK
+VPATH += $(LIBXUL_SDK)/lib
+endif
+
+# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
+# expands to foo.lib on platforms with import libs and -lfoo otherwise
+
+# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
+# expands to dir/foo.lib on platforms with import libs and
+# -Ldir -lfoo otherwise
+
+# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
+# expands to $(DIST)/lib/foo.lib on platforms with import libs and
+# -lfoo otherwise
+
+ifdef _LIBNAME_RELATIVE_PATHS
+EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+else
+EXPAND_LIBNAME = $(addprefix -l,$(1))
+EXPAND_LIBNAME_PATH = -L$(2) $(addprefix -l,$(1))
+EXPAND_MOZLIBNAME = $(addprefix -l,$(1))
+endif
+
+ifdef EXTRA_DSO_LIBS
+EXTRA_DSO_LIBS := $(call EXPAND_MOZLIBNAME,$(EXTRA_DSO_LIBS))
+endif
+
+#
+# Library rules
+#
+# If BUILD_STATIC_LIBS or FORCE_STATIC_LIB is set, build a static library.
+# Otherwise, build a shared library.
+#
+
+ifndef LIBRARY
+ifdef LIBRARY_NAME
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+ifdef SHORT_LIBNAME
+LIBRARY_NAME := $(SHORT_LIBNAME)
+endif
+endif
+LIBRARY := $(LIB_PREFIX)$(LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
+
+ifndef HOST_LIBRARY
+ifdef HOST_LIBRARY_NAME
+HOST_LIBRARY := $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
+endif
+endif
+
+ifdef LIBRARY
+ifneq (_1,$(FORCE_SHARED_LIB)_$(BUILD_STATIC_LIBS))
+ifdef MKSHLIB
+
+ifdef LIB_IS_C_ONLY
+MKSHLIB = $(MKCSHLIB)
+endif
+
+ifdef MAKE_FRAMEWORK
+SHARED_LIBRARY := $(LIBRARY_NAME)
+else
+SHARED_LIBRARY := $(DLL_PREFIX)$(LIBRARY_NAME)$(DLL_SUFFIX)
+endif
+
+ifeq ($(OS_ARCH),OS2)
+DEF_FILE := $(SHARED_LIBRARY:.dll=.def)
+endif
+
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+IMPORT_LIBRARY := $(LIB_PREFIX)$(LIBRARY_NAME).$(IMPORT_LIB_SUFFIX)
+endif
+
+ifdef MOZ_ENABLE_LIBXUL
+EMBED_MANIFEST_AT=2
+endif
+
+endif # MKSHLIB
+endif # FORCE_SHARED_LIB && !BUILD_STATIC_LIBS
+endif # LIBRARY
+
+ifeq (,$(BUILD_STATIC_LIBS)$(FORCE_STATIC_LIB))
+LIBRARY := $(NULL)
+endif
+
+ifeq (_1,$(FORCE_SHARED_LIB)_$(BUILD_STATIC_LIBS))
+SHARED_LIBRARY := $(NULL)
+DEF_FILE := $(NULL)
+IMPORT_LIBRARY := $(NULL)
+endif
+
+ifdef FORCE_STATIC_LIB
+ifndef FORCE_SHARED_LIB
+SHARED_LIBRARY := $(NULL)
+DEF_FILE := $(NULL)
+IMPORT_LIBRARY := $(NULL)
+endif
+endif
+
+ifdef FORCE_SHARED_LIB
+ifndef FORCE_STATIC_LIB
+LIBRARY := $(NULL)
+endif
+endif
+
+ifdef JAVA_LIBRARY_NAME
+JAVA_LIBRARY := $(JAVA_LIBRARY_NAME).jar
+endif
+
+ifeq (,$(filter-out WINNT WINCE,$(OS_ARCH)))
+ifndef GNU_CC
+
+#
+# All C++ files share a PDB file per directory. For parallel builds, this PDB
+# file is shared and locked by MSPDBSRV.EXE, starting with MSVC8 SP1. If
+# you're using MSVC 7.1 or MSVC8 without SP1, don't do parallel builds.
+#
+# The final PDB for libraries and programs is created by the linker and uses
+# a different name from the single PDB file created by the compiler. See
+# bug 462740.
+#
+COMPILE_PDBFILE = generated.pdb
+LINK_PDBFILE = $(basename $(@F)).pdb
+ifdef MOZ_DEBUG
+CODFILE=$(basename $(@F)).cod
+endif
+
+ifdef MOZ_MAPINFO
+ifdef LIBRARY_NAME
+MAPFILE=$(LIBRARY_NAME).map
+else
+MAPFILE=$(basename $(@F)).map
+endif # LIBRARY_NAME
+endif # MOZ_MAPINFO
+
+ifdef DEFFILE
+OS_LDFLAGS += -DEF:$(DEFFILE)
+EXTRA_DEPS += $(DEFFILE)
+endif
+
+ifdef MAPFILE
+OS_LDFLAGS += -MAP:$(MAPFILE)
+#CFLAGS += -Fm$(MAPFILE)
+#CXXFLAGS += -Fm$(MAPFILE)
+endif
+
+#ifdef CODFILE
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#CFLAGS += -Fa$(CODFILE) -FAsc
+#endif
+
+endif # !GNU_CC
+
+ifdef ENABLE_CXX_EXCEPTIONS
+ifdef GNU_CC
+CXXFLAGS += -fexceptions
+else
+ifeq (,$(filter-out 1200 1300 1310,$(_MSC_VER)))
+CXXFLAGS += -GX
+else
+CXXFLAGS += -EHsc
+endif # _MSC_VER
+endif # GNU_CC
+endif # ENABLE_CXX_EXCEPTIONS
+endif # WINNT
+
+ifeq (,$(filter-out WINNT WINCE,$(HOST_OS_ARCH)))
+HOST_PDBFILE=$(basename $(@F)).pdb
+endif
+
+ifndef TARGETS
+TARGETS = $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(HOST_PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
+endif
+
+ifndef OBJS
+_OBJS = \
+ $(JRI_STUB_CFILES) \
+ $(addsuffix .$(OBJ_SUFFIX), $(JMC_GEN)) \
+ $(CSRCS:.c=.$(OBJ_SUFFIX)) \
+ $(patsubst %.cc,%.$(OBJ_SUFFIX),$(CPPSRCS:.cpp=.$(OBJ_SUFFIX))) \
+ $(CMSRCS:.m=.$(OBJ_SUFFIX)) \
+ $(CMMSRCS:.mm=.$(OBJ_SUFFIX)) \
+ $(ASFILES:.$(ASM_SUFFIX)=.$(OBJ_SUFFIX))
+OBJS = $(strip $(_OBJS))
+endif
+
+ifndef HOST_OBJS
+_HOST_OBJS = \
+ $(addprefix host_,$(HOST_CSRCS:.c=.$(OBJ_SUFFIX))) \
+ $(addprefix host_,$(patsubst %.cc,%.$(OBJ_SUFFIX),$(HOST_CPPSRCS:.cpp=.$(OBJ_SUFFIX)))) \
+ $(addprefix host_,$(HOST_CMSRCS:.m=.$(OBJ_SUFFIX))) \
+ $(addprefix host_,$(HOST_CMMSRCS:.mm=.$(OBJ_SUFFIX)))
+HOST_OBJS = $(strip $(_HOST_OBJS))
+endif
+
+LIBOBJS := $(addprefix \", $(OBJS))
+LIBOBJS := $(addsuffix \", $(LIBOBJS))
+
+ifndef MOZ_AUTO_DEPS
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS))
+MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp))
+ifndef NO_GEN_XPT
+MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.xpt)) \
+ $(addprefix $(MDDEPDIR)/,$(SDK_XPIDLSRCS:.idl=.xpt))
+endif
+endif
+endif
+
+ALL_TRASH = \
+ $(GARBAGE) $(TARGETS) $(OBJS) $(PROGOBJS) LOGS TAGS a.out \
+ $(filter-out $(ASFILES),$(OBJS:.$(OBJ_SUFFIX)=.s)) $(OBJS:.$(OBJ_SUFFIX)=.ii) \
+ $(OBJS:.$(OBJ_SUFFIX)=.i) \
+ $(HOST_PROGOBJS) $(HOST_OBJS) $(IMPORT_LIBRARY) $(DEF_FILE)\
+ $(EXE_DEF_FILE) so_locations _gen _stubs $(wildcard *.res) $(wildcard *.RES) \
+ $(wildcard *.pdb) $(CODFILE) $(MAPFILE) $(IMPORT_LIBRARY) \
+ $(SHARED_LIBRARY:$(DLL_SUFFIX)=.exp) $(wildcard *.ilk) \
+ $(PROGRAM:$(BIN_SUFFIX)=.exp) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.exp) \
+ $(PROGRAM:$(BIN_SUFFIX)=.lib) $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.lib) \
+ $(SIMPLE_PROGRAMS:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) \
+ $(wildcard gts_tmp_*) $(LIBRARY:%.a=.%.timestamp)
+ALL_TRASH_DIRS = \
+ $(GARBAGE_DIRS) /no-such-file
+
+ifdef QTDIR
+GARBAGE += $(MOCSRCS)
+endif
+
+ifdef SIMPLE_PROGRAMS
+GARBAGE += $(SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
+endif
+
+ifdef HOST_SIMPLE_PROGRAMS
+GARBAGE += $(HOST_SIMPLE_PROGRAMS:%=%.$(OBJ_SUFFIX))
+endif
+
+#
+# the Solaris WorkShop template repository cache. it occasionally can get
+# out of sync, so targets like clobber should kill it.
+#
+ifeq ($(OS_ARCH),SunOS)
+ifeq ($(GNU_CXX),)
+GARBAGE_DIRS += SunWS_cache
+endif
+endif
+
+ifeq ($(OS_ARCH),OpenVMS)
+GARBAGE += $(wildcard *.*_defines)
+ifdef SHARED_LIBRARY
+VMS_SYMVEC_FILE = $(SHARED_LIBRARY:$(DLL_SUFFIX)=_symvec.opt)
+ifdef MOZ_DEBUG
+VMS_SYMVEC_FILE_MODULE = $(topsrcdir)/build/unix/vms/$(notdir $(SHARED_LIBRARY:$(DLL_SUFFIX)=_dbg_symvec.opt))
+else
+VMS_SYMVEC_FILE_MODULE = $(topsrcdir)/build/unix/vms/$(notdir $(SHARED_LIBRARY:$(DLL_SUFFIX)=_symvec.opt))
+endif
+VMS_SYMVEC_FILE_COMP = $(topsrcdir)/build/unix/vms/component_symvec.opt
+GARBAGE += $(VMS_SYMVEC_FILE)
+ifdef IS_COMPONENT
+DSO_LDOPTS := $(filter-out -auto_symvec,$(DSO_LDOPTS)) $(VMS_SYMVEC_FILE)
+endif
+endif
+endif
+
+XPIDL_GEN_DIR = _xpidlgen
+
+ifdef MOZ_UPDATE_XTERM
+# Its good not to have a newline at the end of the titlebar string because it
+# makes the make -s output easier to read. Echo -n does not work on all
+# platforms, but we can trick sed into doing it.
+UPDATE_TITLE = sed -e "s!Y!$@ in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$(dir)!" $(MOZILLA_DIR)/config/xterm.str;
+UPDATE_TITLE_export = sed -e "s!Y!export in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$*!" $(MOZILLA_DIR)/config/xterm.str;
+UPDATE_TITLE_libs = sed -e "s!Y!libs in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$*!" $(MOZILLA_DIR)/config/xterm.str;
+UPDATE_TITLE_tools = sed -e "s!Y!tools in $(shell $(BUILD_TOOLS)/print-depth-path.sh)/$*!" $(MOZILLA_DIR)/config/xterm.str;
+endif
+
+LOOP_OVER_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+# we only use this for the makefiles target and other stuff that doesn't matter
+LOOP_OVER_PARALLEL_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(PARALLEL_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+LOOP_OVER_STATIC_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(STATIC_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+LOOP_OVER_TOOL_DIRS = \
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(TOOL_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) $@; ) true
+
+ifdef PARALLEL_DIRS
+# create a bunch of fake targets for order-only processing
+PARALLEL_DIRS_export = $(addsuffix _export,$(PARALLEL_DIRS))
+PARALLEL_DIRS_libs = $(addsuffix _libs,$(PARALLEL_DIRS))
+PARALLEL_DIRS_tools = $(addsuffix _tools,$(PARALLEL_DIRS))
+
+.PHONY: $(PARALLEL_DIRS_export) $(PARALLEL_DIRS_libs) $(PARALLEL_DIRS_tools)
+endif
+
+#
+# Now we can differentiate between objects used to build a library, and
+# objects used to build an executable in the same directory.
+#
+ifndef PROGOBJS
+PROGOBJS = $(OBJS)
+endif
+
+ifndef HOST_PROGOBJS
+HOST_PROGOBJS = $(HOST_OBJS)
+endif
+
+# MAKE_DIRS: List of directories to build while looping over directories.
+# A Makefile that needs $(MDDEPDIR) created but doesn't set any of these
+# variables we know to check can just set NEED_MDDEPDIR explicitly.
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS)$(NEED_MDDEPDIR))
+MAKE_DIRS += $(CURDIR)/$(MDDEPDIR)
+GARBAGE_DIRS += $(MDDEPDIR)
+endif
+
+#
+# Tags: emacs (etags), vi (ctags)
+# TAG_PROGRAM := ctags -L -
+#
+TAG_PROGRAM = xargs etags -a
+
+#
+# Turn on C++ linking if we have any .cpp or .mm files
+# (moved this from config.mk so that config.mk can be included
+# before the CPPSRCS are defined)
+#
+ifneq ($(CPPSRCS)$(CMMSRCS),)
+CPP_PROG_LINK = 1
+endif
+
+#
+# Make sure to wrap static libs inside linker specific flags to turn on & off
+# inclusion of all symbols inside the static libs
+#
+ifndef NO_LD_ARCHIVE_FLAGS
+ifdef SHARED_LIBRARY_LIBS
+EXTRA_DSO_LDOPTS := $(MKSHLIB_FORCE_ALL) $(SHARED_LIBRARY_LIBS) $(MKSHLIB_UNFORCE_ALL) $(EXTRA_DSO_LDOPTS)
+endif
+endif
+
+#
+# This will strip out symbols that the component should not be
+# exporting from the .dynsym section.
+#
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += $(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
+endif # IS_COMPONENT
+
+#
+# Enforce the requirement that MODULE_NAME must be set
+# for components in static builds
+#
+ifdef IS_COMPONENT
+ifdef EXPORT_LIBRARY
+ifndef FORCE_SHARED_LIB
+ifndef MODULE_NAME
+$(error MODULE_NAME is required for components which may be used in static builds)
+endif
+endif
+endif
+endif
+
+#
+# MacOS X specific stuff
+#
+
+ifeq ($(OS_ARCH),Darwin)
+ifdef SHARED_LIBRARY
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -bundle
+else
+EXTRA_DSO_LDOPTS += -dynamiclib -install_name @executable_path/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
+endif
+endif
+endif
+
+#
+# On NetBSD a.out systems, use -Bsymbolic. This fixes what would otherwise be
+# fatal symbol name clashes between components.
+#
+ifeq ($(OS_ARCH),NetBSD)
+ifeq ($(DLL_SUFFIX),.so.1.0)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),FreeBSD)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+
+ifeq ($(OS_ARCH),NetBSD)
+ifneq (,$(filter arc cobalt hpcmips mipsco newsmips pmax sgimips,$(OS_TEST)))
+ifeq ($(MODULE),layout)
+OS_CFLAGS += -Wa,-xgot
+OS_CXXFLAGS += -Wa,-xgot
+endif
+endif
+endif
+
+ifeq ($(OS_ARCH),Linux)
+ifneq (,$(filter mips mipsel,$(OS_TEST)))
+ifeq ($(MODULE),layout)
+OS_CFLAGS += -Wa,-xgot
+OS_CXXFLAGS += -Wa,-xgot
+endif
+endif
+endif
+
+#
+# HP-UXBeOS specific section: for COMPONENTS only, add -Bsymbolic flag
+# which uses internal symbols first
+#
+ifeq ($(OS_ARCH),HP-UX)
+ifdef IS_COMPONENT
+ifeq ($(GNU_CC)$(GNU_CXX),)
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+ifneq ($(HAS_EXTRAEXPORTS),1)
+MKSHLIB += -Wl,+eNSGetModule -Wl,+eerrno
+MKCSHLIB += +eNSGetModule +eerrno
+ifneq ($(OS_TEST),ia64)
+MKSHLIB += -Wl,+e_shlInit
+MKCSHLIB += +e_shlInit
+endif # !ia64
+endif # !HAS_EXTRAEXPORTS
+endif # non-gnu compilers
+endif # IS_COMPONENT
+endif # HP-UX
+
+ifeq ($(OS_ARCH),AIX)
+ifdef IS_COMPONENT
+ifneq ($(HAS_EXTRAEXPORTS),1)
+MKSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall
+MKCSHLIB += -bE:$(MOZILLA_DIR)/build/unix/aix.exp -bnoexpall
+endif # HAS_EXTRAEXPORTS
+endif # IS_COMPONENT
+endif # AIX
+
+#
+# OSF1: add -B symbolic flag for components
+#
+ifeq ($(OS_ARCH),OSF1)
+ifdef IS_COMPONENT
+ifeq ($(GNU_CC)$(GNU_CXX),)
+EXTRA_DSO_LDOPTS += -B symbolic
+endif
+endif
+endif
+
+#
+# Linux: add -Bsymbolic flag for components
+#
+ifeq ($(OS_ARCH),Linux)
+ifdef IS_COMPONENT
+EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
+endif
+endif
+
+#
+# MINGW32
+#
+ifeq ($(OS_ARCH),WINNT)
+ifdef GNU_CC
+ifndef IS_COMPONENT
+DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY)
+endif
+endif
+endif
+
+ifeq ($(USE_TVFS),1)
+IFLAGS1 = -rb
+IFLAGS2 = -rb
+else
+IFLAGS1 = -m 644
+IFLAGS2 = -m 755
+endif
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+OUTOPTION = -Fo# eol
+else
+OUTOPTION = -o # eol
+endif # WINNT && !GNU_CC
+ifneq (,$(filter WINCE,$(OS_ARCH)))
+OUTOPTION = -Fo# eol
+endif
+
+ifeq ($(OS_TARGET), WINCE)
+OUTOPTION = -Fo# eol
+HOST_OUTOPTION = -Fo# eol
+else
+
+ifeq (,$(CROSS_COMPILE))
+HOST_OUTOPTION = $(OUTOPTION)
+else
+HOST_OUTOPTION = -o # eol
+endif
+
+endif
+################################################################################
+
+# SUBMAKEFILES: List of Makefiles for next level down.
+# This is used to update or create the Makefiles before invoking them.
+SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
+
+# The root makefile doesn't want to do a plain export/libs, because
+# of the tiers and because of libxul. Suppress the default rules in favor
+# of something else. Makefiles which use this var *must* provide a sensible
+# default rule before including rules.mk
+ifndef SUPPRESS_DEFAULT_RULES
+ifdef TIERS
+
+DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_dirs))
+STATIC_DIRS += $(foreach tier,$(TIERS),$(tier_$(tier)_staticdirs))
+
+default all alldep::
+ $(EXIT_ON_ERROR) \
+ $(foreach tier,$(TIERS),$(MAKE) tier_$(tier); ) true
+
+else
+
+default all::
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(STATIC_DIRS),$(MAKE) -C $(dir); ) true
+ $(MAKE) export
+ $(MAKE) libs
+ $(MAKE) tools
+
+# Do depend as well
+alldep::
+ $(MAKE) export
+ $(MAKE) depend
+ $(MAKE) libs
+ $(MAKE) tools
+
+endif # TIERS
+endif # SUPPRESS_DEFAULT_RULES
+
+ifeq ($(filter s,$(MAKEFLAGS)),)
+ECHO := echo
+QUIET :=
+else
+ECHO := true
+QUIET := -q
+endif
+
+MAKE_TIER_SUBMAKEFILES = +$(if $(tier_$*_dirs),$(MAKE) $(addsuffix /Makefile,$(tier_$*_dirs)))
+
+export_tier_%:
+ @$(ECHO) "$@"
+ @$(MAKE_TIER_SUBMAKEFILES)
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(tier_$*_dirs),$(MAKE) -C $(dir) export; ) true
+
+libs_tier_%:
+ @$(ECHO) "$@"
+ @$(MAKE_TIER_SUBMAKEFILES)
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(tier_$*_dirs),$(MAKE) -C $(dir) libs; ) true
+
+tools_tier_%:
+ @$(ECHO) "$@"
+ @$(MAKE_TIER_SUBMAKEFILES)
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(tier_$*_dirs),$(MAKE) -C $(dir) tools; ) true
+
+$(foreach tier,$(TIERS),tier_$(tier))::
+ @$(ECHO) "$@: $($@_staticdirs) $($@_dirs)"
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$($@_staticdirs),$(MAKE) -C $(dir); ) true
+ $(MAKE) export_$@
+ $(MAKE) libs_$@
+
+# Do everything from scratch
+everything::
+ $(MAKE) clean
+ $(MAKE) alldep
+
+# Add dummy depend target for tinderboxes
+depend::
+
+ifdef ALL_PLATFORMS
+all_platforms:: $(NFSPWD)
+ @d=`$(NFSPWD)`; \
+ if test ! -d LOGS; then rm -rf LOGS; mkdir LOGS; else true; fi; \
+ for h in $(PLATFORM_HOSTS); do \
+ echo "On $$h: $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log";\
+ rsh $$h -n "(chdir $$d; \
+ $(MAKE) $(ALL_PLATFORMS) >& LOGS/$$h.log; \
+ echo DONE) &" 2>&1 > LOGS/$$h.pid & \
+ sleep 1; \
+ done
+
+$(NFSPWD):
+ cd $(@D); $(MAKE) $(@F)
+endif
+
+# Target to only regenerate makefiles
+makefiles: $(SUBMAKEFILES)
+ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+endif
+
+ifdef PARALLEL_DIRS
+export:: $(PARALLEL_DIRS_export)
+
+$(PARALLEL_DIRS_export): %_export: %/Makefile
+ +@$(UPDATE_TITLE_export) $(MAKE) -C $* export
+endif
+
+export:: $(SUBMAKEFILES) $(MAKE_DIRS) $(if $(EXPORTS)$(XPIDLSRCS)$(SDK_HEADERS)$(SDK_XPIDLSRCS),$(PUBLIC)) $(if $(SDK_HEADERS)$(SDK_XPIDLSRCS),$(SDK_PUBLIC)) $(if $(XPIDLSRCS),$(IDL_DIR)) $(if $(SDK_XPIDLSRCS),$(SDK_IDL_DIR))
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+ifdef PARALLEL_DIRS
+tools:: $(PARALLEL_DIRS_tools)
+
+$(PARALLEL_DIRS_tools): %_tools: %/Makefile
+ +@$(UPDATE_TITLE_tools) $(MAKE) -C $* tools
+endif
+
+tools:: $(SUBMAKEFILES) $(MAKE_DIRS)
+ +$(LOOP_OVER_DIRS)
+ifdef TOOL_DIRS
+ @$(EXIT_ON_ERROR) \
+ $(foreach dir,$(TOOL_DIRS),$(UPDATE_TITLE) $(MAKE) -C $(dir) libs; ) true
+endif
+
+#
+# Rule to create list of libraries for final link
+#
+export::
+ifdef LIBRARY_NAME
+ifdef EXPORT_LIBRARY
+ifdef IS_COMPONENT
+ifdef BUILD_STATIC_LIBS
+ @$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMPS) $(LIBRARY_NAME)
+ifdef MODULE_NAME
+ @$(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_COMP_NAMES) $(MODULE_NAME)
+endif
+endif
+else
+ $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/build-list.pl $(FINAL_LINK_LIBS) $(LIBRARY_NAME)
+endif # IS_COMPONENT
+endif # EXPORT_LIBRARY
+endif # LIBRARY_NAME
+
+# Create dependencies on static (and shared EXTRA_DSO_LIBS) libraries
+LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(LIBS))
+HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX), $(HOST_LIBS))
+DSO_LDOPTS_DEPS = $(EXTRA_DSO_LIBS) $(filter %.$(LIB_SUFFIX), $(EXTRA_DSO_LDOPTS))
+
+##############################################
+ifdef PARALLEL_DIRS
+libs:: $(PARALLEL_DIRS_libs)
+
+$(PARALLEL_DIRS_libs): %_libs: %/Makefile
+ +@$(UPDATE_TITLE_libs) $(MAKE) -C $* libs
+endif
+
+libs:: $(SUBMAKEFILES) $(MAKE_DIRS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY) $(IMPORT_LIBRARY) $(HOST_PROGRAM) $(PROGRAM) $(HOST_SIMPLE_PROGRAMS) $(SIMPLE_PROGRAMS) $(JAVA_LIBRARY)
+ifndef NO_DIST_INSTALL
+ifdef LIBRARY
+ifdef EXPORT_LIBRARY # Stage libs that will be linked into a static build
+ifdef IS_COMPONENT
+ $(INSTALL) $(IFLAGS1) $(LIBRARY) $(DEPTH)/staticlib/components
+else
+ $(INSTALL) $(IFLAGS1) $(LIBRARY) $(DEPTH)/staticlib
+endif
+endif # EXPORT_LIBRARY
+ifdef DIST_INSTALL
+ifdef IS_COMPONENT
+ $(error Shipping static component libs makes no sense.)
+else
+ $(INSTALL) $(IFLAGS1) $(LIBRARY) $(DIST)/lib
+endif
+endif # DIST_INSTALL
+endif # LIBRARY
+ifdef SHARED_LIBRARY
+ifdef IS_COMPONENT
+ $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
+ $(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
+ifdef BEOS_ADDON_WORKAROUND
+ ( cd $(FINAL_TARGET)/components && $(CC) -nostart -o $(SHARED_LIBRARY).stub $(SHARED_LIBRARY) )
+endif
+else # ! IS_COMPONENT
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+ $(INSTALL) $(IFLAGS2) $(IMPORT_LIBRARY) $(DIST)/lib
+else
+ $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DIST)/lib
+endif
+ $(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)
+ifdef BEOS_ADDON_WORKAROUND
+ ( cd $(FINAL_TARGET) && $(CC) -nostart -o $(SHARED_LIBRARY).stub $(SHARED_LIBRARY) )
+endif
+endif # IS_COMPONENT
+endif # SHARED_LIBRARY
+ifdef PROGRAM
+ $(INSTALL) $(IFLAGS2) $(PROGRAM) $(FINAL_TARGET)
+endif
+ifdef SIMPLE_PROGRAMS
+ $(INSTALL) $(IFLAGS2) $(SIMPLE_PROGRAMS) $(FINAL_TARGET)
+endif
+ifdef HOST_PROGRAM
+ $(INSTALL) $(IFLAGS2) $(HOST_PROGRAM) $(DIST)/host/bin
+endif
+ifdef HOST_SIMPLE_PROGRAMS
+ $(INSTALL) $(IFLAGS2) $(HOST_SIMPLE_PROGRAMS) $(DIST)/host/bin
+endif
+ifdef HOST_LIBRARY
+ $(INSTALL) $(IFLAGS1) $(HOST_LIBRARY) $(DIST)/host/lib
+endif
+ifdef JAVA_LIBRARY
+ifdef IS_COMPONENT
+ $(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)/components
+else
+ $(INSTALL) $(IFLAGS1) $(JAVA_LIBRARY) $(FINAL_TARGET)
+endif
+endif # JAVA_LIBRARY
+endif # !NO_DIST_INSTALL
+ +$(LOOP_OVER_DIRS)
+
+##############################################
+
+ifndef NO_PROFILE_GUIDED_OPTIMIZE
+ifneq (,$(MOZ_PROFILE_GENERATE)$(MOZ_PROFILE_USE))
+ifeq ($(OS_ARCH)_$(GNU_CC)$(INTERNAL_TOOLS), WINNT_)
+# Force re-linking when building with PGO, since
+# the MSVC linker does all the work. We force re-link
+# in both stages so you can do depend builds with PGO.
+ifdef SHARED_LIBRARY
+$(SHARED_LIBRARY): FORCE
+BINARY_BASENAME = $(SHARED_LIBRARY:$(DLL_SUFFIX)=)
+endif
+ifdef PROGRAM
+$(PROGRAM): FORCE
+BINARY_BASENAME = $(PROGRAM:$(BIN_SUFFIX)=)
+endif
+
+ifdef MOZ_PROFILE_USE
+# In the second pass, we need to merge the pgc files into the pgd file.
+# The compiler would do this for us automatically if they were in the right
+# place, but they're in dist/bin.
+ifdef BINARY_BASENAME
+export::
+ $(PYTHON) $(topsrcdir)/build/win32/pgomerge.py \
+ $(BINARY_BASENAME) $(DIST)/bin
+endif
+endif # MOZ_PROFILE_USE
+endif # WINNT_
+endif # MOZ_PROFILE_GENERATE || MOZ_PROFILE_USE
+endif # NO_PROFILE_GUIDED_OPTIMIZE
+
+##############################################
+
+checkout:
+ $(MAKE) -C $(topsrcdir) -f client.mk checkout
+
+run_viewer: $(FINAL_TARGET)/viewer
+ cd $(FINAL_TARGET); \
+ MOZILLA_FIVE_HOME=`pwd` \
+ LD_LIBRARY_PATH=".:$(LIBS_PATH):$$LD_LIBRARY_PATH" \
+ viewer
+
+clean clobber realclean clobber_all:: $(SUBMAKEFILES)
+ -rm -f $(ALL_TRASH)
+ -rm -rf $(ALL_TRASH_DIRS)
+ +-$(LOOP_OVER_PARALLEL_DIRS)
+ +-$(LOOP_OVER_DIRS)
+ +-$(LOOP_OVER_STATIC_DIRS)
+ +-$(LOOP_OVER_TOOL_DIRS)
+
+distclean:: $(SUBMAKEFILES)
+ +-$(LOOP_OVER_PARALLEL_DIRS)
+ +-$(LOOP_OVER_DIRS)
+ +-$(LOOP_OVER_STATIC_DIRS)
+ +-$(LOOP_OVER_TOOL_DIRS)
+ -rm -rf $(ALL_TRASH_DIRS)
+ -rm -f $(ALL_TRASH) \
+ Makefile .HSancillary \
+ $(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
+ $(wildcard *.$(LIB_SUFFIX)) $(wildcard *$(DLL_SUFFIX)) \
+ $(wildcard *.$(IMPORT_LIB_SUFFIX))
+ifeq ($(OS_ARCH),OS2)
+ -rm -f $(PROGRAM:.exe=.map)
+endif
+
+alltags:
+ rm -f TAGS
+ find $(topsrcdir) -name dist -prune -o \( -name '*.[hc]' -o -name '*.cp' -o -name '*.cpp' -o -name '*.idl' \) -print | $(TAG_PROGRAM)
+
+#
+# PROGRAM = Foo
+# creates OBJS, links with LIBS to create Foo
+#
+$(PROGRAM): $(PROGOBJS) $(LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(LD) -NOLOGO -OUT:$@ $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+else
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(PROGOBJS) $(RESFILE) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ if test -f "$(srcdir)/$@.manifest"; then \
+ mt.exe -NOLOGO -MANIFEST "$(win_srcdir)/$@.manifest" $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ else \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ fi; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(CPP_PROG_LINK),1)
+ $(CCC) -o $@ $(CXXFLAGS) $(WRAP_MALLOC_CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(WRAP_MALLOC_LIB) $(PROFILER_LIBS) $(EXE_DEF_FILE)
+else # ! CPP_PROG_LINK
+ $(CC) -o $@ $(CFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE)
+endif # CPP_PROG_LINK
+endif # WINNT && !GNU_CC
+endif # WINCE
+
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+ifeq ($(OS_ARCH),BeOS)
+ifdef BEOS_PROGRAM_RESOURCE
+ xres -o $@ $(BEOS_PROGRAM_RESOURCE)
+ mimeset $@
+endif
+endif # BeOS
+
+$(HOST_PROGRAM): $(HOST_PROGOBJS) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(HOST_LD) -NOLOGO -OUT:$@ $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifeq (_WINNT,$(GNU_CC)_$(HOST_OS_ARCH))
+ $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $(HOST_OBJS) $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(CPP_PROG_LINK),1)
+ $(HOST_CXX) -o $@ $(HOST_CXXFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CC) -o $@ $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_PROGOBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif # CPP_PROG_LINK
+endif
+endif
+
+#
+# This is an attempt to support generation of multiple binaries
+# in one directory, it assumes everything to compile Foo is in
+# Foo.o (from either Foo.c or Foo.cpp).
+#
+# SIMPLE_PROGRAMS = Foo Bar
+# creates Foo.o Bar.o, links with LIBS to create Foo, Bar.
+#
+$(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(LIBS_DEPS) $(EXTRA_DEPS) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(LD) -nologo -entry:main -out:$@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+else
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ $(LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+ifdef MSMANIFEST_TOOL
+ @if test -f $@.manifest; then \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+ rm -f $@.manifest; \
+ fi
+endif # MSVC with manifest tool
+else
+ifeq ($(CPP_PROG_LINK),1)
+ $(CCC) $(WRAP_MALLOC_CFLAGS) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(PROFILER_LIBS) $(BIN_FLAGS)
+else
+ $(CC) $(WRAP_MALLOC_CFLAGS) $(CFLAGS) $(OUTOPTION)$@ $< $(WIN32_EXE_LDFLAGS) $(SOLARIS_JEMALLOC_LDFLAGS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS) $(WRAP_MALLOC_LIB) $(PROFILER_LIBS) $(BIN_FLAGS)
+endif # CPP_PROG_LINK
+endif # WINNT && !GNU_CC
+endif # WINCE
+
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+ifdef MOZ_POST_PROGRAM_COMMAND
+ $(MOZ_POST_PROGRAM_COMMAND) $@
+endif
+
+$(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): host_%.$(OBJ_SUFFIX) $(HOST_LIBS_DEPS) $(HOST_EXTRA_DEPS) Makefile Makefile.in
+ifeq (WINCE,$(OS_ARCH))
+ $(HOST_LD) -NOLOGO -OUT:$@ $(WIN32_EXE_LDFLAGS) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC))
+ $(HOST_LD) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX))
+ $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXXFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+else
+ $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_CFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+endif
+endif
+endif
+
+#
+# Purify target. Solaris/sparc only to start.
+# Purify does not recognize "egcs" or "c++" so we go with
+# "gcc" and "g++" for now.
+#
+pure: $(PROGRAM)
+ifeq ($(CPP_PROG_LINK),1)
+ $(PURIFY) $(CCC) -o $^.pure $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(PURIFY) $(CC) -o $^.pure $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+endif
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS2) $^.pure $(FINAL_TARGET)
+endif
+
+quantify: $(PROGRAM)
+ifeq ($(CPP_PROG_LINK),1)
+ $(QUANTIFY) $(CCC) -o $^.quantify $(CXXFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+else
+ $(QUANTIFY) $(CC) -o $^.quantify $(CFLAGS) $(PROGOBJS) $(LDFLAGS) $(LIBS_DIR) $(LIBS) $(OS_LIBS) $(EXTRA_LIBS)
+endif
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS2) $^.quantify $(FINAL_TARGET)
+endif
+
+#
+# This allows us to create static versions of the shared libraries
+# that are built using other static libraries. Confused...?
+#
+ifdef SHARED_LIBRARY_LIBS
+ifeq (,$(GNU_LD)$(filter-out OS2 WINNT WINCE, $(OS_ARCH)))
+ifneq (,$(BUILD_STATIC_LIBS)$(FORCE_STATIC_LIB))
+LOBJS += $(SHARED_LIBRARY_LIBS)
+endif
+else
+ifneq (,$(filter OSF1 BSD_OS FreeBSD NetBSD OpenBSD SunOS Darwin,$(OS_ARCH)))
+CLEANUP1 := | egrep -v '(________64ELEL_|__.SYMDEF)'
+CLEANUP2 := rm -f ________64ELEL_ __.SYMDEF
+else
+CLEANUP2 := true
+endif
+SUB_LOBJS = $(shell for lib in $(SHARED_LIBRARY_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;)
+endif
+endif
+ifdef MOZILLA_PROBE_LIBS
+PROBE_LOBJS = $(shell for lib in $(MOZILLA_PROBE_LIBS); do $(AR_LIST) $${lib} $(CLEANUP1); done;)
+endif
+ifdef DTRACE_PROBE_OBJ
+EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
+endif
+
+$(LIBRARY): $(OBJS) $(LOBJS) $(SHARED_LIBRARY_LIBS) $(EXTRA_DEPS) Makefile Makefile.in
+ rm -f $@
+ifneq (,$(GNU_LD)$(filter-out OS2 WINNT WINCE, $(OS_ARCH)))
+ifdef SHARED_LIBRARY_LIBS
+ @rm -f $(SUB_LOBJS)
+ @for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
+endif
+endif
+ $(AR) $(AR_FLAGS) $(OBJS) $(LOBJS) $(SUB_LOBJS)
+ $(RANLIB) $@
+ @rm -f foodummyfilefoo $(SUB_LOBJS)
+
+ifeq (,$(filter-out WINNT WINCE, $(OS_ARCH)))
+$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
+endif
+
+ifeq ($(OS_ARCH),OS2)
+$(DEF_FILE): $(OBJS) $(SHARED_LIBRARY_LIBS)
+ rm -f $@
+ echo LIBRARY $(LIBRARY_NAME) INITINSTANCE TERMINSTANCE > $@
+ echo PROTMODE >> $@
+ echo CODE LOADONCALL MOVEABLE DISCARDABLE >> $@
+ echo DATA PRELOAD MOVEABLE MULTIPLE NONSHARED >> $@
+ echo EXPORTS >> $@
+ifeq ($(IS_COMPONENT),1)
+ifeq ($(HAS_EXTRAEXPORTS),1)
+ifndef MOZ_OS2_USE_DECLSPEC
+ $(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
+endif
+else
+ echo _NSGetModule >> $@
+endif
+else
+ifndef MOZ_OS2_USE_DECLSPEC
+ $(FILTER) $(OBJS) $(SHARED_LIBRARY_LIBS) >> $@
+endif
+endif
+ $(ADD_TO_DEF_FILE)
+
+ifdef MOZ_OS2_USE_DECLSPEC
+$(IMPORT_LIBRARY): $(SHARED_LIBRARY)
+else
+$(IMPORT_LIBRARY): $(DEF_FILE)
+endif
+ rm -f $@
+ $(IMPLIB) $@ $^
+ $(RANLIB) $@
+endif # OS/2
+
+$(HOST_LIBRARY): $(HOST_OBJS) Makefile
+ rm -f $@
+ $(HOST_AR) $(HOST_AR_FLAGS) $(HOST_OBJS)
+ $(HOST_RANLIB) $@
+
+ifdef NO_LD_ARCHIVE_FLAGS
+SUB_SHLOBJS = $(SUB_LOBJS)
+endif
+
+ifdef HAVE_DTRACE
+ifndef XP_MACOSX
+ifdef DTRACE_PROBE_OBJ
+ifndef DTRACE_LIB_DEPENDENT
+$(DTRACE_PROBE_OBJ): $(OBJS)
+ dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(OBJS)
+endif
+endif
+endif
+endif
+
+# On Darwin (Mac OS X), dwarf2 debugging uses debug info left in .o files,
+# so instead of deleting .o files after repacking them into a dylib, we make
+# symlinks back to the originals. The symlinks are a no-op for stabs debugging,
+# so no need to conditionalize on OS version or debugging format.
+
+$(SHARED_LIBRARY): $(OBJS) $(LOBJS) $(DEF_FILE) $(RESFILE) $(SHARED_LIBRARY_LIBS) $(EXTRA_DEPS) $(DSO_LDOPTS_DEPS) Makefile Makefile.in
+ifndef INCREMENTAL_LINKER
+ rm -f $@
+endif
+ifeq ($(OS_ARCH),OpenVMS)
+ @if test ! -f $(VMS_SYMVEC_FILE); then \
+ if test -f $(VMS_SYMVEC_FILE_MODULE); then \
+ echo Creating specific component options file $(VMS_SYMVEC_FILE); \
+ cp $(VMS_SYMVEC_FILE_MODULE) $(VMS_SYMVEC_FILE); \
+ fi; \
+ fi
+ifdef IS_COMPONENT
+ @if test ! -f $(VMS_SYMVEC_FILE); then \
+ echo Creating generic component options file $(VMS_SYMVEC_FILE); \
+ cp $(VMS_SYMVEC_FILE_COMP) $(VMS_SYMVEC_FILE); \
+ fi
+endif
+endif # OpenVMS
+ifdef NO_LD_ARCHIVE_FLAGS
+ifdef SHARED_LIBRARY_LIBS
+ @rm -f $(SUB_SHLOBJS)
+ @for lib in $(SHARED_LIBRARY_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
+ifeq ($(OS_ARCH),Darwin)
+ @echo Making symlinks to the original object files in the archive libraries $(SHARED_LIBRARY_LIBS)
+ @for lib in $(SHARED_LIBRARY_LIBS); do \
+ libdir=`echo $$lib|sed -e 's,/[^/]*\.a,,'`; \
+ ofiles=`$(AR_LIST) $${lib}`; \
+ for ofile in $$ofiles; do \
+ if [ -f $$libdir/$$ofile ]; then \
+ rm -f $$ofile; \
+ ln -s $$libdir/$$ofile $$ofile; \
+ fi; \
+ done; \
+ done
+endif
+endif # SHARED_LIBRARY_LIBS
+endif # NO_LD_ARCHIVE_FLAGS
+ifdef DTRACE_LIB_DEPENDENT
+ @rm -f $(PROBE_LOBJS)
+ @for lib in $(MOZILLA_PROBE_LIBS); do $(AR_EXTRACT) $${lib}; $(CLEANUP2); done
+ifndef XP_MACOSX
+ dtrace -G -C -32 -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS)
+endif
+ @for lib in $(MOZILLA_PROBE_LIBS); do \
+ ofiles=`$(AR_LIST) $${lib}`; \
+ $(AR_DELETE) $${lib} $$ofiles; \
+ done
+ $(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(LOBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(PROBE_LOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
+ @rm -f $(PROBE_LOBJS)
+ @rm -f $(DTRACE_PROBE_OBJ)
+ @for lib in $(MOZILLA_PROBE_LIBS); do \
+ if [ -L $${lib} ]; then rm -f `readlink $${lib}`; fi; \
+ done
+ @rm -f $(MOZILLA_PROBE_LIBS)
+
+else # ! DTRACE_LIB_DEPENDENT
+ $(MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(DTRACE_PROBE_OBJ) $(LOBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(EXTRA_DSO_LDOPTS) $(OS_LIBS) $(EXTRA_LIBS) $(DEF_FILE) $(SHLIB_LDENDFILE)
+endif # DTRACE_LIB_DEPENDENT
+
+ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
+ifdef MSMANIFEST_TOOL
+ifdef EMBED_MANIFEST_AT
+ @if test -f $@.manifest; then \
+ mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+ rm -f $@.manifest; \
+ fi
+endif # EMBED_MANIFEST_AT
+endif # MSVC with manifest tool
+endif # WINNT && !GCC
+ifeq ($(OS_ARCH),Darwin)
+else # non-Darwin
+ @rm -f $(SUB_SHLOBJS)
+endif # Darwin
+ @rm -f foodummyfilefoo $(DELETE_AFTER_LINK)
+ chmod +x $@
+ifdef ENABLE_STRIP
+ $(STRIP) $@
+endif
+ifdef MOZ_POST_DSO_LIB_COMMAND
+ $(MOZ_POST_DSO_LIB_COMMAND) $@
+endif
+
+ifdef MOZ_AUTO_DEPS
+ifdef COMPILER_DEPEND
+ifeq (__SunOS,$(GNU_CC)_$(GNU_CXX)_$(OS_ARCH))
+_MDDEPFILE = $(MDDEPDIR)/$(@F).pp
+
+define MAKE_DEPS_AUTO_CC
+if test -d $(@D); then \
+ echo "Building deps for $< using Sun Studio cc"; \
+ $(CC) $(COMPILE_CFLAGS) -xM $< >$(_MDDEPFILE) ; \
+fi
+endef
+define MAKE_DEPS_AUTO_CXX
+if test -d $(@D); then \
+ echo "Building deps for $< using Sun Studio CC"; \
+ $(CXX) $(COMPILE_CXXFLAGS) -xM $< >$(_MDDEPFILE) ; \
+fi
+endef
+endif # Sun Studio on Solaris
+else # COMPILER_DEPEND
+#
+# Generate dependencies on the fly
+#
+_MDDEPFILE = $(MDDEPDIR)/$(@F).pp
+
+define MAKE_DEPS_AUTO
+if test -d $(@D); then \
+ echo "Building deps for $<"; \
+ $(MKDEPEND) -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $(_MDDEPFILE) ; \
+fi
+endef
+
+MAKE_DEPS_AUTO_CC = $(MAKE_DEPS_AUTO)
+MAKE_DEPS_AUTO_CXX = $(MAKE_DEPS_AUTO)
+
+endif # COMPILER_DEPEND
+
+endif # MOZ_AUTO_DEPS
+
+ifdef MOZ_MEMORY
+ifeq ($(OS_ARCH),SunOS)
+SOLARIS_JEMALLOC_LDFLAGS = $(call EXPAND_LIBNAME_PATH,jemalloc,$(DIST)/lib)
+endif
+endif
+
+# Rules for building native targets must come first because of the host_ prefix
+host_%.$(OBJ_SUFFIX): %.c Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.cpp Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.cc Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.m Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+host_%.$(OBJ_SUFFIX): %.mm Makefile Makefile.in
+ $(REPORT_BUILD)
+ $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
+
+%: %.c Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CC)
+ $(ELOG) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
+
+%.$(OBJ_SUFFIX): %.c Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CC)
+ $(ELOG) $(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+
+moc_%.cpp: %.h Makefile Makefile.in
+ $(MOC) $< $(OUTOPTION)$@
+
+ifdef ASFILES
+# The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
+# a '-c' flag.
+%.$(OBJ_SUFFIX): %.$(ASM_SUFFIX) Makefile Makefile.in
+ $(AS) -o $@ $(ASFLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
+endif
+
+%.$(OBJ_SUFFIX): %.S Makefile Makefile.in
+ $(AS) -o $@ $(ASFLAGS) -c $<
+
+%: %.cpp Makefile Makefile.in
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(CCC) $(OUTOPTION)$@ $(CXXFLAGS) $(_VPATH_SRCS) $(LDFLAGS)
+
+#
+# Please keep the next two rules in sync.
+#
+%.$(OBJ_SUFFIX): %.cc Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+
+%.$(OBJ_SUFFIX): %.cpp Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ifdef STRICT_CPLUSPLUS_SUFFIX
+ echo "#line 1 \"$*.cpp\"" | cat - $*.cpp > t_$*.cc
+ $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) t_$*.cc
+ rm -f t_$*.cc
+else
+ $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+endif #STRICT_CPLUSPLUS_SUFFIX
+
+$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.mm Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CXX)
+ $(ELOG) $(CCC) -o $@ -c $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS)
+
+$(OBJ_PREFIX)%.$(OBJ_SUFFIX): %.m Makefile Makefile.in
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_AUTO_CC)
+ $(ELOG) $(CC) -o $@ -c $(COMPILE_CFLAGS) $(COMPILE_CMFLAGS) $(_VPATH_SRCS)
+
+%.s: %.cpp
+ $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+
+%.s: %.cc
+ $(CCC) -S $(COMPILE_CXXFLAGS) $(_VPATH_SRCS)
+
+%.s: %.c
+ $(CC) -S $(COMPILE_CFLAGS) $(_VPATH_SRCS)
+
+%.i: %.cpp
+ $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.i: %.cc
+ $(CCC) -C -E $(COMPILE_CXXFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.i: %.c
+ $(CC) -C -E $(COMPILE_CFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.i: %.mm
+ $(CCC) -C -E $(COMPILE_CXXFLAGS) $(COMPILE_CMMFLAGS) $(_VPATH_SRCS) > $*.i
+
+%.res: %.rc
+ @echo Creating Resource file: $@
+ifeq ($(OS_ARCH),OS2)
+ $(RC) $(RCFLAGS:-D%=-d %) -i $(subst /,\,$(srcdir)) -r $< $@
+else
+ifdef GNU_CC
+ $(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
+else
+ $(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS)
+endif
+endif
+
+# need 3 separate lines for OS/2
+%: %.pl
+ rm -f $@
+ cp $< $@
+ chmod +x $@
+
+%: %.sh
+ rm -f $@; cp $< $@; chmod +x $@
+
+# Cancel these implicit rules
+#
+%: %,v
+
+%: RCS/%,v
+
+%: s.%
+
+%: SCCS/s.%
+
+###############################################################################
+# Java rules
+###############################################################################
+ifneq (,$(filter OS2 WINNT WINCE,$(OS_ARCH)))
+SEP := ;
+else
+SEP := :
+endif
+
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
+
+# Cygwin and MSYS have their own special path form, but javac expects the source
+# and class paths to be in the DOS form (i.e. e:/builds/...). This function
+# does the appropriate conversion on Windows, but is a noop on other systems.
+ifeq (,$(filter-out WINNT WINCE, $(HOST_OS_ARCH)))
+ifdef CYGWIN_WRAPPER
+normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p)))
+else
+# assume MSYS
+# We use 'pwd -W' to get DOS form of the path. However, since the given path
+# could be a file or a non-existent path, we cannot call 'pwd -W' directly
+# on the path. Instead, we extract the root path (i.e. "c:/"), call 'pwd -W'
+# on it, then merge with the rest of the path.
+root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|")
+non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|")
+normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(shell cd $(call root-path,$(1)) && pwd -W)$(call non-root-path,$(1)),$(1)))
+endif
+else
+normalizepath = $(1)
+endif
+
+_srcdir = $(call normalizepath,$(srcdir))
+ifdef JAVA_SOURCEPATH
+SP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_SOURCEPATH))))
+_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)$(SEP)$(SP)"
+else
+_JAVA_SOURCEPATH = ".$(SEP)$(_srcdir)"
+endif
+
+ifdef JAVA_CLASSPATH
+CP = $(subst $(SPACE),$(SEP),$(call normalizepath,$(strip $(JAVA_CLASSPATH))))
+_JAVA_CLASSPATH = ".$(SEP)$(CP)"
+else
+_JAVA_CLASSPATH = .
+endif
+
+_JAVA_DIR = _java
+$(_JAVA_DIR)::
+ $(NSINSTALL) -D $@
+
+$(_JAVA_DIR)/%.class: %.java Makefile Makefile.in $(_JAVA_DIR)
+ $(CYGWIN_WRAPPER) $(JAVAC) $(JAVAC_FLAGS) -classpath $(_JAVA_CLASSPATH) \
+ -sourcepath $(_JAVA_SOURCEPATH) -d $(_JAVA_DIR) $(_VPATH_SRCS)
+
+$(JAVA_LIBRARY): $(addprefix $(_JAVA_DIR)/,$(JAVA_SRCS:.java=.class)) Makefile Makefile.in
+ $(JAR) cf $@ -C $(_JAVA_DIR) .
+
+GARBAGE_DIRS += $(_JAVA_DIR)
+
+###############################################################################
+# Update Makefiles
+###############################################################################
+
+# In GNU make 3.80, makefiles must use the /cygdrive syntax, even if we're
+# processing them with AS perl. See bug 232003
+ifdef AS_PERL
+CYGWIN_TOPSRCDIR = -nowrap -p $(topsrcdir) -wrap
+endif
+
+# Note: Passing depth to make-makefile is optional.
+# It saves the script some work, though.
+Makefile: Makefile.in
+ @$(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) $(CYGWIN_TOPSRCDIR)
+
+ifdef SUBMAKEFILES
+# VPATH does not work on some machines in this case, so add $(srcdir)
+$(SUBMAKEFILES): % : $(srcdir)/%.in
+ $(PERL) $(AUTOCONF_TOOLS)/make-makefile -t $(topsrcdir) -d $(DEPTH) $(CYGWIN_TOPSRCDIR) $@
+endif
+
+ifdef AUTOUPDATE_CONFIGURE
+$(topsrcdir)/configure: $(topsrcdir)/configure.in
+ (cd $(topsrcdir) && $(AUTOCONF)) && (cd $(DEPTH) && ./config.status --recheck)
+endif
+
+###############################################################################
+# Bunch of things that extend the 'export' rule (in order):
+###############################################################################
+
+################################################################################
+# Copy each element of EXPORTS to $(PUBLIC)
+
+ifneq ($(EXPORTS)$(XPIDLSRCS)$(SDK_HEADERS)$(SDK_XPIDLSRCS),)
+$(SDK_PUBLIC) $(PUBLIC)::
+ $(NSINSTALL) -D $@
+endif
+
+ifdef MOZ_JAVAXPCOM
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+$(JAVA_DIST_DIR)::
+ $(NSINSTALL) -D $@
+endif
+endif
+
+ifneq ($(XPI_NAME),)
+$(FINAL_TARGET):
+ $(NSINSTALL) -D $@
+
+export:: $(FINAL_TARGET)
+endif
+
+ifndef NO_DIST_INSTALL
+ifneq ($(EXPORTS),)
+export:: $(EXPORTS) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+
+ifneq ($(SDK_HEADERS),)
+export:: $(SDK_HEADERS) $(SDK_PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(SDK_HEADERS) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+endif # NO_DIST_INSTALL
+
+################################################################################
+# Copy each element of PREF_JS_EXPORTS
+
+ifdef GRE_MODULE
+PREF_DIR = greprefs
+else
+ifneq (,$(XPI_NAME)$(LIBXUL_SDK))
+PREF_DIR = defaults/preferences
+else
+PREF_DIR = defaults/pref
+endif
+endif
+
+ifneq ($(PREF_JS_EXPORTS),)
+# on win32, pref files need CRLF line endings... see bug 206029
+ifeq (WINNT,$(OS_ARCH))
+PREF_PPFLAGS = --line-endings=crlf
+endif
+
+ifndef NO_DIST_INSTALL
+$(FINAL_TARGET)/$(PREF_DIR):
+ $(NSINSTALL) -D $@
+
+libs:: $(FINAL_TARGET)/$(PREF_DIR) $(PREF_JS_EXPORTS)
+ $(EXIT_ON_ERROR) \
+ for i in $(PREF_JS_EXPORTS); do \
+ dest=$(FINAL_TARGET)/$(PREF_DIR)/`basename $$i`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+ done
+endif
+endif
+
+################################################################################
+# Copy each element of AUTOCFG_JS_EXPORTS to $(FINAL_TARGET)/defaults/autoconfig
+
+ifneq ($(AUTOCFG_JS_EXPORTS),)
+$(FINAL_TARGET)/defaults/autoconfig::
+ $(NSINSTALL) -D $@
+
+ifndef NO_DIST_INSTALL
+export:: $(AUTOCFG_JS_EXPORTS) $(FINAL_TARGET)/defaults/autoconfig
+ $(INSTALL) $(IFLAGS1) $^
+endif
+
+endif
+################################################################################
+# Export the elements of $(XPIDLSRCS) & $(SDK_XPIDLSRCS),
+# generating .h and .xpt files and moving them to the appropriate places.
+
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS))
+
+ifndef XPIDL_MODULE
+XPIDL_MODULE = $(MODULE)
+endif
+
+ifeq ($(XPIDL_MODULE),) # we need $(XPIDL_MODULE) to make $(XPIDL_MODULE).xpt
+export:: FORCE
+ @echo
+ @echo "*** Error processing XPIDLSRCS:"
+ @echo "Please define MODULE or XPIDL_MODULE when defining XPIDLSRCS,"
+ @echo "so we have a module name to use when creating MODULE.xpt."
+ @echo; sleep 2; false
+endif
+
+$(SDK_IDL_DIR) $(IDL_DIR)::
+ $(NSINSTALL) -D $@
+
+# generate .h files from into $(XPIDL_GEN_DIR), then export to $(PUBLIC);
+# warn against overriding existing .h file.
+$(XPIDL_GEN_DIR)/.done:
+ @if test ! -d $(XPIDL_GEN_DIR); then echo Creating $(XPIDL_GEN_DIR)/.done; rm -rf $(XPIDL_GEN_DIR); mkdir $(XPIDL_GEN_DIR); fi
+ @touch $@
+
+# don't depend on $(XPIDL_GEN_DIR), because the modification date changes
+# with any addition to the directory, regenerating all .h files -> everything.
+
+$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+ $(REPORT_BUILD)
+ $(ELOG) $(XPIDL_COMPILE) -m header -w $(XPIDL_FLAGS) -o $(XPIDL_GEN_DIR)/$* $(_VPATH_SRCS)
+ @if test -n "$(findstring $*.h, $(EXPORTS) $(SDK_HEADERS))"; \
+ then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
+
+ifndef NO_GEN_XPT
+# generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
+# into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components.
+$(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done
+ $(REPORT_BUILD)
+ $(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$*.pp $(_VPATH_SRCS)
+
+# no need to link together if XPIDLSRCS contains only XPIDL_MODULE
+ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS)))
+$(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS) $(SDK_XPIDLSRCS)) Makefile.in Makefile $(XPIDL_LINK)
+ $(XPIDL_LINK) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.xpt,$(XPIDLSRCS) $(SDK_XPIDLSRCS))
+endif # XPIDL_MODULE.xpt != XPIDLSRCS
+
+libs:: $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS1) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt $(FINAL_TARGET)/components
+endif
+
+endif # NO_GEN_XPT
+
+GARBAGE_DIRS += $(XPIDL_GEN_DIR)
+
+endif # XPIDLSRCS || SDK_XPIDLSRCS
+
+ifneq ($(XPIDLSRCS),)
+# export .idl files to $(IDL_DIR)
+ifndef NO_DIST_INSTALL
+export:: $(XPIDLSRCS) $(IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(XPIDLSRCS)) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif # NO_DIST_INSTALL
+
+endif # XPIDLSRCS
+
+
+
+#
+# General rules for exporting idl files.
+#
+# WORK-AROUND ONLY, for mozilla/tools/module-deps/bootstrap.pl build.
+# Bug to fix idl dependency problems w/o this extra build pass is
+# http://bugzilla.mozilla.org/show_bug.cgi?id=145777
+#
+$(IDL_DIR)::
+ $(NSINSTALL) -D $@
+
+export-idl:: $(SUBMAKEFILES) $(MAKE_DIRS)
+
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+ifndef NO_DIST_INSTALL
+export-idl:: $(XPIDLSRCS) $(SDK_XPIDLSRCS) $(IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+
+
+
+ifneq ($(SDK_XPIDLSRCS),)
+# export .idl files to $(IDL_DIR) & $(SDK_IDL_DIR)
+ifndef NO_DIST_INSTALL
+export:: $(SDK_XPIDLSRCS) $(IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(SDK_XPIDLSRCS) $(SDK_IDL_DIR)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(SDK_XPIDLSRCS)) $(PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+
+export:: $(patsubst %.idl,$(XPIDL_GEN_DIR)/%.h, $(SDK_XPIDLSRCS)) $(SDK_PUBLIC)
+ $(INSTALL) $(IFLAGS1) $^
+endif
+
+endif # SDK_XPIDLSRCS
+
+
+
+ifdef MOZ_JAVAXPCOM
+ifneq ($(XPIDLSRCS)$(SDK_XPIDLSRCS),)
+
+JAVA_XPIDLSRCS = $(XPIDLSRCS) $(SDK_XPIDLSRCS)
+
+# A single IDL file can contain multiple interfaces, which result in multiple
+# Java interface files. So use hidden dependency files.
+JAVADEPFILES = $(addprefix $(JAVA_GEN_DIR)/.,$(JAVA_XPIDLSRCS:.idl=.java.pp))
+
+$(JAVA_GEN_DIR):
+ $(NSINSTALL) -D $@
+GARBAGE_DIRS += $(JAVA_GEN_DIR)
+
+# generate .java files into _javagen/[package name dirs]
+_JAVA_GEN_DIR = $(JAVA_GEN_DIR)/$(JAVA_IFACES_PKG_NAME)
+$(_JAVA_GEN_DIR):
+ $(NSINSTALL) -D $@
+
+$(JAVA_GEN_DIR)/.%.java.pp: %.idl $(XPIDL_COMPILE) $(_JAVA_GEN_DIR)
+ $(REPORT_BUILD)
+ $(ELOG) $(XPIDL_COMPILE) -m java -w -I$(srcdir) -I$(IDL_DIR) -o $(_JAVA_GEN_DIR)/$* $(_VPATH_SRCS)
+ @touch $@
+
+# "Install" generated Java interfaces. We segregate them based on the XPI_NAME.
+# If XPI_NAME is not set, install into the "default" directory.
+ifneq ($(XPI_NAME),)
+JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/$(XPI_NAME)
+else
+JAVA_INSTALL_DIR = $(JAVA_DIST_DIR)/default
+endif
+
+$(JAVA_INSTALL_DIR):
+ $(NSINSTALL) -D $@
+
+export:: $(JAVA_DIST_DIR) $(JAVADEPFILES) $(JAVA_INSTALL_DIR)
+ (cd $(JAVA_GEN_DIR) && tar $(TAR_CREATE_FLAGS) - .) | (cd $(JAVA_INSTALL_DIR) && tar -xf -)
+
+endif # XPIDLSRCS || SDK_XPIDLSRCS
+endif # MOZ_JAVAXPCOM
+
+################################################################################
+# Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
+ifdef EXTRA_COMPONENTS
+libs:: $(EXTRA_COMPONENTS)
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/components
+endif
+
+endif
+
+ifdef EXTRA_PP_COMPONENTS
+libs:: $(EXTRA_PP_COMPONENTS)
+ifndef NO_DIST_INSTALL
+ $(EXIT_ON_ERROR) \
+ $(NSINSTALL) -D $(FINAL_TARGET)/components; \
+ for i in $^; do \
+ dest=$(FINAL_TARGET)/components/`basename $$i`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+ done
+endif
+
+endif
+
+################################################################################
+# Copy each element of EXTRA_JS_MODULES to $(FINAL_TARGET)/modules
+ifdef EXTRA_JS_MODULES
+libs:: $(EXTRA_JS_MODULES)
+ifndef NO_DIST_INSTALL
+ $(INSTALL) $(IFLAGS1) $^ $(FINAL_TARGET)/modules
+endif
+
+endif
+
+ifdef EXTRA_PP_JS_MODULES
+libs:: $(EXTRA_PP_JS_MODULES)
+ifndef NO_DIST_INSTALL
+ $(EXIT_ON_ERROR) \
+ $(NSINSTALL) -D $(FINAL_TARGET)/modules; \
+ for i in $^; do \
+ dest=$(FINAL_TARGET)/modules/`basename $$i`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $$i > $$dest; \
+ done
+endif
+
+endif
+
+################################################################################
+# SDK
+
+ifneq (,$(SDK_LIBRARY))
+$(SDK_LIB_DIR)::
+ $(NSINSTALL) -D $@
+
+ifndef NO_DIST_INSTALL
+libs:: $(SDK_LIBRARY) $(SDK_LIB_DIR)
+ $(INSTALL) $(IFLAGS2) $^
+endif
+
+endif # SDK_LIBRARY
+
+ifneq (,$(SDK_BINARY))
+$(SDK_BIN_DIR)::
+ $(NSINSTALL) -D $@
+
+ifndef NO_DIST_INSTALL
+libs:: $(SDK_BINARY) $(SDK_BIN_DIR)
+ $(INSTALL) $(IFLAGS2) $^
+endif
+
+endif # SDK_BINARY
+
+################################################################################
+# CHROME PACKAGING
+
+JAR_MANIFEST := $(srcdir)/jar.mn
+
+chrome::
+ $(MAKE) realchrome
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+$(FINAL_TARGET)/chrome:
+ $(NSINSTALL) -D $@
+
+# libs realchrome:: $(CHROME_DEPS) $(FINAL_TARGET)/chrome
+# ifndef NO_DIST_INSTALL
+# @$(EXIT_ON_ERROR) \
+# if test -f $(JAR_MANIFEST); then \
+# $(PYTHON) $(MOZILLA_DIR)/config/JarMaker.py \
+# $(QUIET) -j $(FINAL_TARGET)/chrome \
+# $(MAKE_JARS_FLAGS) $(XULPPFLAGS) $(DEFINES) $(ACDEFINES) \
+# $(JAR_MANIFEST); \
+# fi
+# endif
+
+ifneq ($(DIST_FILES),)
+libs:: $(DIST_FILES)
+ @$(EXIT_ON_ERROR) \
+ for f in $(DIST_FILES); do \
+ dest=$(FINAL_TARGET)/`basename $$f`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
+ $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
+ $(srcdir)/$$f > $$dest; \
+ done
+endif
+
+ifneq ($(DIST_CHROME_FILES),)
+libs:: $(DIST_CHROME_FILES)
+ @$(EXIT_ON_ERROR) \
+ for f in $(DIST_CHROME_FILES); do \
+ dest=$(FINAL_TARGET)/chrome/`basename $$f`; \
+ $(RM) -f $$dest; \
+ $(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py \
+ $(XULAPP_DEFINES) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) \
+ $(srcdir)/$$f > $$dest; \
+ done
+endif
+
+ifneq ($(XPI_PKGNAME),)
+libs realchrome::
+ifdef STRIP_XPI
+ifndef MOZ_DEBUG
+ @echo "Stripping $(XPI_PKGNAME) package directory..."
+ @echo $(FINAL_TARGET)
+ @cd $(FINAL_TARGET) && find . ! -type d \
+ ! -name "*.js" \
+ ! -name "*.xpt" \
+ ! -name "*.gif" \
+ ! -name "*.jpg" \
+ ! -name "*.png" \
+ ! -name "*.xpm" \
+ ! -name "*.txt" \
+ ! -name "*.rdf" \
+ ! -name "*.sh" \
+ ! -name "*.properties" \
+ ! -name "*.dtd" \
+ ! -name "*.html" \
+ ! -name "*.xul" \
+ ! -name "*.css" \
+ ! -name "*.xml" \
+ ! -name "*.jar" \
+ ! -name "*.dat" \
+ ! -name "*.tbl" \
+ ! -name "*.src" \
+ ! -name "*.reg" \
+ $(PLATFORM_EXCLUDE_LIST) \
+ -exec $(STRIP) $(STRIP_FLAGS) {} >/dev/null 2>&1 \;
+endif
+endif
+ @echo "Packaging $(XPI_PKGNAME).xpi..."
+ cd $(FINAL_TARGET) && $(ZIP) -qr ../$(XPI_PKGNAME).xpi *
+endif
+
+ifdef INSTALL_EXTENSION_ID
+ifndef XPI_NAME
+$(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
+endif
+
+libs::
+ $(RM) -rf "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
+ $(NSINSTALL) -D "$(DIST)/bin/extensions/$(INSTALL_EXTENSION_ID)"
+ cd $(FINAL_TARGET) && tar $(TAR_CREATE_FLAGS) - . | (cd "../../bin/extensions/$(INSTALL_EXTENSION_ID)" && tar -xf -)
+
+endif
+
+ifneq (,$(filter flat symlink,$(MOZ_CHROME_FILE_FORMAT)))
+_JAR_REGCHROME_DISABLE_JAR=1
+else
+_JAR_REGCHROME_DISABLE_JAR=0
+endif
+
+REGCHROME = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \
+ $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \
+ $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(FINAL_TARGET)/chrome/installed-chrome.txt \
+ $(_JAR_REGCHROME_DISABLE_JAR)
+
+REGCHROME_INSTALL = $(PERL) -I$(MOZILLA_DIR)/config $(MOZILLA_DIR)/config/add-chrome.pl \
+ $(if $(filter gtk2,$(MOZ_WIDGET_TOOLKIT)),-x) \
+ $(if $(CROSS_COMPILE),-o $(OS_ARCH)) $(DESTDIR)$(mozappdir)/chrome/installed-chrome.txt \
+ $(_JAR_REGCHROME_DISABLE_JAR)
+
+
+################################################################################
+# Testing frameworks support
+################################################################################
+
+ifdef ENABLE_TESTS
+
+ifdef XPCSHELL_TESTS
+ifndef MODULE
+$(error Must define MODULE when defining XPCSHELL_TESTS.)
+endif
+
+# Test file installation
+libs::
+ @$(EXIT_ON_ERROR) \
+ for testdir in $(XPCSHELL_TESTS); do \
+ $(INSTALL) \
+ $(srcdir)/$$testdir/*.js \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir; \
+ done
+
+# Path formats on Windows are hard. We require a topsrcdir formatted so that
+# it may be passed to nsILocalFile.initWithPath (in other words, an absolute
+# path of the form X:\path\to\topsrcdir), which we store in NATIVE_TOPSRCDIR.
+# We require a forward-slashed path to topsrcdir so that it may be combined
+# with a relative forward-slashed path for loading scripts, both dynamically
+# and statically for head/test/tail JS files. Of course, on non-Windows none
+# of this matters, and things will work correctly because everything's
+# forward-slashed, everywhere, always.
+ifdef CYGWIN_WRAPPER
+NATIVE_TOPSRCDIR := `cygpath -wa $(topsrcdir)`
+FWDSLASH_TOPSRCDIR := `cygpath -ma $(topsrcdir)`
+else
+FWDSLASH_TOPSRCDIR := $(topsrcdir)
+ifeq ($(HOST_OS_ARCH),WINNT)
+NATIVE_TOPSRCDIR := $(subst /,\\,$(WIN_TOP_SRC))
+else
+NATIVE_TOPSRCDIR := $(topsrcdir)
+endif
+endif # CYGWIN_WRAPPER
+
+# Test execution
+check::
+ @$(EXIT_ON_ERROR) \
+ for testdir in $(XPCSHELL_TESTS); do \
+ $(RUN_TEST_PROGRAM) \
+ $(topsrcdir)/tools/test-harness/xpcshell-simple/test_all.sh \
+ $(DIST)/bin/xpcshell \
+ $(FWDSLASH_TOPSRCDIR) \
+ $(NATIVE_TOPSRCDIR) \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir; \
+ done
+
+# Test execution
+check-interactive::
+ @$(EXIT_ON_ERROR) \
+ $(RUN_TEST_PROGRAM) \
+ $(topsrcdir)/tools/test-harness/xpcshell-simple/test_one.sh \
+ $(DIST)/bin/xpcshell \
+ $(FWDSLASH_TOPSRCDIR) \
+ $(NATIVE_TOPSRCDIR) \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir \
+ $(SOLO_FILE) 1;
+
+# Test execution
+check-one::
+ @$(EXIT_ON_ERROR) \
+ $(RUN_TEST_PROGRAM) \
+ $(topsrcdir)/tools/test-harness/xpcshell-simple/test_one.sh \
+ $(DIST)/bin/xpcshell \
+ $(FWDSLASH_TOPSRCDIR) \
+ $(NATIVE_TOPSRCDIR) \
+ $(DEPTH)/_tests/xpcshell-simple/$(MODULE)/$$testdir \
+ $(SOLO_FILE) 0;
+
+endif # XPCSHELL_TESTS
+
+endif # ENABLE_TESTS
+
+
+#############################################################################
+# Dependency system
+#############################################################################
+ifdef COMPILER_DEPEND
+depend::
+ @echo "$(MAKE): No need to run depend target.\
+ Using compiler-based depend." 1>&2
+ifeq ($(GNU_CC)$(GNU_CXX),)
+# Non-GNU compilers
+ @echo "`echo '$(MAKE):'|sed 's/./ /g'`"\
+ '(Compiler-based depend was turned on by "--enable-md".)' 1>&2
+else
+# GNU compilers
+ @space="`echo '$(MAKE): '|sed 's/./ /g'`";\
+ echo "$$space"'Since you are using a GNU compiler,\
+ it is on by default.' 1>&2; \
+ echo "$$space"'To turn it off, pass --disable-md to configure.' 1>&2
+endif
+
+else # ! COMPILER_DEPEND
+
+ifndef MOZ_AUTO_DEPS
+
+define MAKE_DEPS_NOAUTO
+ $(MKDEPEND) -w1024 -o'.$(OBJ_SUFFIX)' -f- $(DEFINES) $(ACDEFINES) $(INCLUDES) $< 2>/dev/null | sed -e "s|^[^ ]*/||" > $@
+endef
+
+$(MDDEPDIR)/%.pp: %.c
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_NOAUTO)
+
+$(MDDEPDIR)/%.pp: %.cpp
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_NOAUTO)
+
+$(MDDEPDIR)/%.pp: %.s
+ $(REPORT_BUILD)
+ @$(MAKE_DEPS_NOAUTO)
+
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS))
+depend:: $(SUBMAKEFILES) $(MAKE_DIRS) $(MDDEPFILES)
+else
+depend:: $(SUBMAKEFILES)
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+dependclean:: $(SUBMAKEFILES)
+ rm -f $(MDDEPFILES)
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
+
+endif # MOZ_AUTO_DEPS
+
+endif # COMPILER_DEPEND
+
+
+#############################################################################
+# MDDEPDIR is the subdirectory where all the dependency files are placed.
+# This uses a make rule (instead of a macro) to support parallel
+# builds (-jN). If this were done in the LOOP_OVER_DIRS macro, two
+# processes could simultaneously try to create the same directory.
+#
+# We use $(CURDIR) in the rule's target to ensure that we don't find
+# a dependency directory in the source tree via VPATH (perhaps from
+# a previous build in the source tree) and thus neglect to create a
+# dependency directory in the object directory, where we really need
+# it.
+
+$(CURDIR)/$(MDDEPDIR):
+ @if test ! -d $@; then echo Creating $@; rm -rf $@; mkdir $@; else true; fi
+
+ifneq (,$(filter-out all chrome default export realchrome tools clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
+ifneq (,$(OBJS)$(XPIDLSRCS)$(SDK_XPIDLSRCS)$(SIMPLE_PROGRAMS))
+MDDEPEND_FILES := $(strip $(wildcard $(MDDEPDIR)/*.pp))
+
+ifneq (,$(MDDEPEND_FILES))
+ifdef PERL
+# The script mddepend.pl checks the dependencies and writes to stdout
+# one rule to force out-of-date objects. For example,
+# foo.o boo.o: FORCE
+# The script has an advantage over including the *.pp files directly
+# because it handles the case when header files are removed from the build.
+# 'make' would complain that there is no way to build missing headers.
+ifeq (,$(MAKE_RESTARTS))
+$(MDDEPDIR)/.all.pp: FORCE
+ @$(PERL) $(BUILD_TOOLS)/mddepend.pl $@ $(MDDEPEND_FILES)
+endif
+-include $(MDDEPDIR)/.all.pp
+else
+include $(MDDEPEND_FILES)
+endif
+endif
+
+endif
+endif
+#############################################################################
+
+-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
+-include $(MY_RULES)
+
+#
+# This speeds up gmake's processing if these files don't exist.
+#
+$(MY_CONFIG) $(MY_RULES):
+ @touch $@
+
+#
+# Generate Emacs tags in a file named TAGS if ETAGS was set in $(MY_CONFIG)
+# or in $(MY_RULES)
+#
+ifdef ETAGS
+ifneq ($(CSRCS)$(CPPSRCS)$(HEADERS),)
+all:: TAGS
+TAGS:: $(CSRCS) $(CPPSRCS) $(HEADERS)
+ $(ETAGS) $(CSRCS) $(CPPSRCS) $(HEADERS)
+endif
+endif
+
+################################################################################
+# Special gmake rules.
+################################################################################
+
+
+#
+# Disallow parallel builds with MSVC < 8
+#
+ifneq (,$(filter 1200 1300 1310,$(_MSC_VER)))
+.NOTPARALLEL:
+endif
+
+#
+# Re-define the list of default suffixes, so gmake won't have to churn through
+# hundreds of built-in suffix rules for stuff we don't need.
+#
+.SUFFIXES:
+
+#
+# Fake targets. Always run these rules, even if a file/directory with that
+# name already exists.
+#
+.PHONY: all all_platforms alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_viewer run_apprunner tools $(DIRS) $(TOOL_DIRS) FORCE check check-interactive check-one
+
+# Used as a dependency to force targets to rebuild
+FORCE:
+
+# Delete target if error occurs when building target
+.DELETE_ON_ERROR:
+
+# Properly set LIBPATTERNS for the platform
+.LIBPATTERNS = $(if $(IMPORT_LIB_SUFFIX),$(LIB_PREFIX)%.$(IMPORT_LIB_SUFFIX)) $(LIB_PREFIX)%.$(LIB_SUFFIX) $(DLL_PREFIX)%$(DLL_SUFFIX)
+
+tags: TAGS
+
+TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+ -etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+echo-variable-%:
+ @echo $($*)
+
+echo-tiers:
+ @echo $(TIERS)
+
+echo-dirs:
+ @echo $(DIRS)
+
+echo-module:
+ @echo $(MODULE)
+
+echo-requires:
+ @echo $(REQUIRES)
+
+echo-requires-recursive::
+ifdef _REPORT_ALL_DIRS
+ @echo $(subst $(topsrcdir)/,,$(srcdir)): $(MODULE): $(REQUIRES)
+else
+ @$(if $(REQUIRES),echo $(subst $(topsrcdir)/,,$(srcdir)): $(MODULE): $(REQUIRES))
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+echo-depth-path:
+ @$(topsrcdir)/build/unix/print-depth-path.sh
+
+echo-module-name:
+ @$(topsrcdir)/build/package/rpm/print-module-name.sh
+
+echo-module-filelist:
+ @$(topsrcdir)/build/package/rpm/print-module-filelist.sh
+
+showtargs:
+ifneq (,$(filter $(PROGRAM) $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) $(HOST_LIBRARY) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS)))
+ @echo --------------------------------------------------------------------------------
+ @echo "PROGRAM = $(PROGRAM)"
+ @echo "SIMPLE_PROGRAMS = $(SIMPLE_PROGRAMS)"
+ @echo "LIBRARY = $(LIBRARY)"
+ @echo "SHARED_LIBRARY = $(SHARED_LIBRARY)"
+ @echo "SHARED_LIBRARY_LIBS = $(SHARED_LIBRARY_LIBS)"
+ @echo "LIBS = $(LIBS)"
+ @echo "DEF_FILE = $(DEF_FILE)"
+ @echo "IMPORT_LIBRARY = $(IMPORT_LIBRARY)"
+ @echo "STATIC_LIBS = $(STATIC_LIBS)"
+ @echo "SHARED_LIBS = $(SHARED_LIBS)"
+ @echo "EXTRA_DSO_LIBS = $(EXTRA_DSO_LIBS)"
+ @echo "EXTRA_DSO_LDOPTS = $(EXTRA_DSO_LDOPTS)"
+ @echo "DEPENDENT_LIBS = $(DEPENDENT_LIBS)"
+ @echo --------------------------------------------------------------------------------
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+showbuild:
+ @echo "MOZ_BUILD_ROOT = $(MOZ_BUILD_ROOT)"
+ @echo "MOZ_WIDGET_TOOLKIT = $(MOZ_WIDGET_TOOLKIT)"
+ @echo "CC = $(CC)"
+ @echo "CXX = $(CXX)"
+ @echo "CCC = $(CCC)"
+ @echo "CPP = $(CPP)"
+ @echo "LD = $(LD)"
+ @echo "AR = $(AR)"
+ @echo "IMPLIB = $(IMPLIB)"
+ @echo "FILTER = $(FILTER)"
+ @echo "MKSHLIB = $(MKSHLIB)"
+ @echo "MKCSHLIB = $(MKCSHLIB)"
+ @echo "RC = $(RC)"
+ @echo "CFLAGS = $(CFLAGS)"
+ @echo "OS_CFLAGS = $(OS_CFLAGS)"
+ @echo "COMPILE_CFLAGS = $(COMPILE_CFLAGS)"
+ @echo "CXXFLAGS = $(CXXFLAGS)"
+ @echo "OS_CXXFLAGS = $(OS_CXXFLAGS)"
+ @echo "COMPILE_CXXFLAGS = $(COMPILE_CXXFLAGS)"
+ @echo "COMPILE_CMFLAGS = $(COMPILE_CMFLAGS)"
+ @echo "COMPILE_CMMFLAGS = $(COMPILE_CMMFLAGS)"
+ @echo "LDFLAGS = $(LDFLAGS)"
+ @echo "OS_LDFLAGS = $(OS_LDFLAGS)"
+ @echo "DSO_LDOPTS = $(DSO_LDOPTS)"
+ @echo "OS_INCLUDES = $(OS_INCLUDES)"
+ @echo "OS_LIBS = $(OS_LIBS)"
+ @echo "EXTRA_LIBS = $(EXTRA_LIBS)"
+ @echo "BIN_FLAGS = $(BIN_FLAGS)"
+ @echo "INCLUDES = $(INCLUDES)"
+ @echo "DEFINES = $(DEFINES)"
+ @echo "ACDEFINES = $(ACDEFINES)"
+ @echo "BIN_SUFFIX = $(BIN_SUFFIX)"
+ @echo "LIB_SUFFIX = $(LIB_SUFFIX)"
+ @echo "DLL_SUFFIX = $(DLL_SUFFIX)"
+ @echo "IMPORT_LIB_SUFFIX = $(IMPORT_LIB_SUFFIX)"
+ @echo "INSTALL = $(INSTALL)"
+
+showhost:
+ @echo "HOST_CC = $(HOST_CC)"
+ @echo "HOST_CXX = $(HOST_CXX)"
+ @echo "HOST_CFLAGS = $(HOST_CFLAGS)"
+ @echo "HOST_LDFLAGS = $(HOST_LDFLAGS)"
+ @echo "HOST_LIBS = $(HOST_LIBS)"
+ @echo "HOST_EXTRA_LIBS = $(HOST_EXTRA_LIBS)"
+ @echo "HOST_EXTRA_DEPS = $(HOST_EXTRA_DEPS)"
+ @echo "HOST_PROGRAM = $(HOST_PROGRAM)"
+ @echo "HOST_OBJS = $(HOST_OBJS)"
+ @echo "HOST_PROGOBJS = $(HOST_PROGOBJS)"
+ @echo "HOST_LIBRARY = $(HOST_LIBRARY)"
+
+showbuildmods::
+ @echo "Build Modules = $(BUILD_MODULES)"
+ @echo "Module dirs = $(BUILD_MODULE_DIRS)"
+
+zipmakes:
+ifneq (,$(filter $(PROGRAM) $(SIMPLE_PROGRAMS) $(LIBRARY) $(SHARED_LIBRARY),$(TARGETS)))
+ zip $(DEPTH)/makefiles $(subst $(topsrcdir),$(MOZ_SRC)/mozilla,$(srcdir)/Makefile.in)
+endif
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+
+documentation:
+ @cd $(DEPTH)
+ $(DOXYGEN) $(DEPTH)/config/doxygen.cfg
+
+check:: $(SUBMAKEFILES) $(MAKE_DIRS)
+ +$(LOOP_OVER_PARALLEL_DIRS)
+ +$(LOOP_OVER_DIRS)
+ +$(LOOP_OVER_TOOL_DIRS)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/system-headers b/tools/node_modules/expresso/deps/jscoverage/js/config/system-headers
new file mode 100644
index 0000000..9d61c0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/system-headers
@@ -0,0 +1,1038 @@
+A4Stuff.h
+activscp.h
+AEDataModel.h
+AEObjects.h
+AEPackObject.h
+AERegistry.h
+AEUtils.h
+afxcmn.h
+afxcoll.h
+afxcview.h
+afxdisp.h
+afxdtctl.h
+afxext.h
+afxmt.h
+afxpriv.h
+afxtempl.h
+afxwin.h
+algorithm
+Aliases.h
+all.h
+alloca.h
+alloc.h
+alsa/asoundlib.h
+alsa/pcm.h
+alsa/mixer.h
+ansi_parms.h
+a.out.h
+app/Cursor.h
+Appearance.h
+AppFileInfo.h
+AppKit.h
+AppleEvents.h
+Application.h
+app/Message.h
+app/MessageRunner.h
+arpa/inet.h
+arpa/nameser.h
+asm/sigcontext.h
+asm/signal.h
+ASRegistry.h
+assert.h
+atk/atk.h
+atlbase.h
+atlcom.h
+atlconv.h
+atlctl.cpp
+atlctl.h
+ATLCTL.H
+atlhost.h
+atlimpl.cpp
+atlwin.cpp
+ATSTypes.h
+ATSUnicode.h
+Balloons.h
+base/pblock.h
+base/PCR_Base.h
+base/session.h
+basetyps.h
+be/app/Application.h
+Beep.h
+be/kernel/image.h
+be/kernel/OS.h
+bfd.h
+Bitmap.h
+bsd/libc.h
+bsd/syscall.h
+bstring.h
+builtin.h
+Button.h
+byteswap.h
+#if MOZ_ENABLE_LIBXUL!=1
+#define WRAP_CAIRO_HEADERS
+#endif
+#if MOZ_TREE_CAIRO!=1
+#define WRAP_CAIRO_HEADERS
+#endif
+#ifdef WRAP_CAIRO_HEADERS
+cairo.h
+cairo-atsui.h
+cairo-beos.h
+cairo-ft.h
+cairo-glitz.h
+cairo-os2.h
+cairo-pdf.h
+cairo-ps.h
+cairo-quartz.h
+cairo-win32.h
+cairo-xlib.h
+cairo-xlib-xrender.h
+cairo-directfb.h
+cairo-qpainter.h
+#endif
+dfiff.h
+fusion/reactor.h
+fusion/property.h
+fusion/conf.h
+fusion/build.h
+fusion/hash.h
+fusion/shm/shm.h
+fusion/shm/shm_internal.h
+fusion/shm/pool.h
+fusion/ref.h
+fusion/fusion_internal.h
+fusion/lock.h
+fusion/types.h
+fusion/vector.h
+fusion/call.h
+fusion/shmalloc.h
+fusion/protocol.h
+fusion/fusion.h
+fusion/arena.h
+fusion/object.h
+directfbgl.h
+directfb_version.h
+directfb.h
+directfb_util.h
+directfb_keynames.h
+dgiff.h
+direct/util.h
+direct/memcpy.h
+direct/interface.h
+direct/conf.h
+direct/tree.h
+direct/signals.h
+direct/build.h
+direct/interface_implementation.h
+direct/utf8.h
+direct/serial.h
+direct/hash.h
+direct/direct.h
+direct/clock.h
+direct/types.h
+direct/mem.h
+direct/thread.h
+direct/debug.h
+direct/stream.h
+direct/messages.h
+direct/trace.h
+direct/modules.h
+direct/log.h
+direct/system.h
+direct/list.h
+dfb_types.h
+directfb_strings.h
+directfb_keyboard.h
+callconv.h
+Carbon/Carbon.h
+CarbonEvents.h
+Carbon.h
+cassert
+c_asm.h
+cctype
+cderr.h
+cerrno
+cert.h
+CFBase.h
+CFBundle.h
+CFData.h
+CFDictionary.h
+cf.h
+CFNumber.h
+CFPlugIn.h
+CFPreferences.h
+CFString.h
+CFURL.h
+CGAffineTransform.h
+CheckBox.h
+climits
+Clipboard.h
+cmplrs/stsupport.h
+Cocoa/Cocoa.h
+CodeFragments.h
+comdef.h
+commctrl.h
+COMMCTRL.H
+commdlg.h
+compat.h
+condapi.h
+ConditionalMacros.h
+config.h
+conio.h
+console.h
+ControlDefinitions.h
+Controls.h
+CoreFoundation/CoreFoundation.h
+CoreServices/CoreServices.h
+CPalmRec.cpp
+Cpalmrec.h
+CPCatgry.cpp
+CPDbBMgr.h
+CPString.cpp
+CPString.h
+crtdbg.h
+crt_externs.h
+crypt.h
+cstdio
+cstdlib
+cstring
+ctime
+ctype.h
+curl/curl.h
+curl/easy.h
+curl/types.h
+curses.h
+cxxabi.h
+DateTimeUtils.h
+dbus/dbus.h
+dbus/dbus-glib.h
+dbus/dbus-glib-lowlevel.h
+ddeml.h
+Debug.h
+dem.h
+descrip.h
+Devices.h
+Dialogs.h
+direct.h
+dirent.h
+DiskInit.h
+dlfcn.h
+dlgs.h
+dl.h
+docobj.h
+dos/dosextens.h
+dos.h
+Drag.h
+DriverServices.h
+DriverSynchronization.h
+DropInPanel.h
+dvidef.h
+elf.h
+endian.h
+Entry.h
+errno.h
+Errors.h
+Events.h
+exdisp.h
+ExDisp.h
+exe386.h
+execinfo.h
+extras.h
+fabdef.h
+fcntl.h
+features.h
+fibdef.h
+File.h
+filehdr.h
+files.h
+Files.h
+FindDirectory.h
+Finder.h
+FinderRegistry.h
+FixMath.h
+float.h
+Folders.h
+fontconfig/fontconfig.h
+fontconfig/fcfreetype.h
+Font.h
+Fonts.h
+fp.h
+fpieee.h
+frame/log.h
+frame/req.h
+freetype/freetype.h
+freetype/ftcache.h
+freetype/ftglyph.h
+freetype/ftsynth.h
+freetype/ftoutln.h
+freetype/ttnameid.h
+freetype/tttables.h
+freetype/t1tables.h
+fribidi/fribidi.h
+FSp_fopen.h
+fstream.h
+ft2build.h
+gconf/gconf-client.h
+Gdiplus.h
+gdk/gdkevents.h
+gdk/gdk.h
+gdk/gdkkeysyms.h
+gdk/gdkpango.h
+gdk/gdkprivate.h
+gdk/gdkscreen.h
+gdk/gdkregion.h
+gdk/gdkwindow.h
+gdk/gdkx.h
+gdk/gdkdirectfb.h
+gdk-pixbuf/gdk-pixbuf.h
+Gestalt.h
+getopt.h
+glibconfig.h
+glib.h
+glib-object.h
+gmodule.h
+gnome.h
+gnu/libc-version.h
+grp.h
+gssapi_generic.h
+gssapi/gssapi_generic.h
+gssapi/gssapi.h
+gssapi.h
+gtk/gtkbindings.h
+gtk/gtkbutton.h
+gtk/gtkclipboard.h
+gtk/gtkcontainer.h
+gtk/gtkdialog.h
+gtk/gtkentry.h
+gtk/gtkfixed.h
+gtk/gtk.h
+gtk/gtkiconfactory.h
+gtk/gtkimage.h
+gtk/gtkimmulticontext.h
+gtk/gtkinvisible.h
+gtk/gtkmain.h
+gtk/gtkmessagedialog.h
+gtk/gtkobject.h
+gtk/gtkprinter.h
+gtk/gtkprintjob.h
+gtk/gtkprintunixdialog.h
+gtk/gtkprivate.h
+gtk/gtkselection.h
+gtk/gtksignal.h
+gtk/gtksocket.h
+gtk/gtkstock.h
+gtk/gtkstyle.h
+gtk/gtktextview.h
+gtk/gtkvscrollbar.h
+gtk/gtkwidget.h
+gtk/gtkwindow.h
+gtk/gtkversion.h
+HIToolbox/HIToolbox.h
+hlink.h
+htiface.h
+ia64/sys/inline.h
+Icons.h
+iconv.h
+IDL.h
+ieeefp.h
+ifaddrs.h
+image.h
+imagehlp.h
+imm.h
+initguid.h
+InterfaceDefs.h
+InternetConfig.h
+IntlResources.h
+ints.h
+intshcut.h
+inttypes.h
+iodef.h
+io.h
+IOKit/IOKitLib.h
+IOKit/IOMessage.h
+IOKit/pwr_mgt/IOPMLib.h
+iomanip
+iostream
+iostream.h
+jar.h
+JavaControl.h
+JavaEmbedding/JavaControl.h
+JavaVM/jni.h
+JManager.h
+JNIEnvTests.h
+jni.h
+#if MOZ_NATIVE_JPEG==1
+jpeglib.h
+#endif
+JVMManagerTests.h
+Kerberos/Kerberos.h
+kernel/image.h
+kernel/OS.h
+key.h
+keyt.h
+keythi.h
+LAction.h
+langinfo.h
+LApplication.h
+LArray.h
+LArrayIterator.h
+LAttachable.h
+LAttachment.h
+LaunchServices.h
+lber.h
+LBroadcaster.h
+LButton.h
+lcache.h
+LCaption.h
+LCheckBox.h
+LCicnButton.h
+LClipboard.h
+LCommander.h
+LComparator.h
+LControl.h
+ldap.h
+ldaplog.h
+ldappr.h
+ldap_ssl.h
+LDataStream.h
+ldfcn.h
+LDialogBox.h
+ldif.h
+LDocApplication.h
+LDocument.h
+LDragAndDrop.h
+LDragTask.h
+LEditField.h
+LEditText.h
+LEventDispatcher.h
+LFile.h
+LFileStream.h
+LFileTypeList.h
+LFocusBox.h
+LGrafPortView.h
+LHandleStream.h
+libc_r.h
+libelf.h
+libelf/libelf.h
+libgen.h
+libgnome/gnome-url.h
+libgnome/libgnome.h
+libgnomeui/gnome-icon-lookup.h
+libgnomeui/gnome-icon-theme.h
+libgnomeui/gnome-ui-init.h
+libgnomevfs/gnome-vfs-application-registry.h
+libgnomevfs/gnome-vfs-file-info.h
+libgnomevfs/gnome-vfs.h
+libgnomevfs/gnome-vfs-init.h
+libgnomevfs/gnome-vfs-mime.h
+libgnomevfs/gnome-vfs-mime-handlers.h
+libgnomevfs/gnome-vfs-mime-info.h
+libgnomevfs/gnome-vfs-mime-utils.h
+libgnomevfs/gnome-vfs-ops.h
+libgnomevfs/gnome-vfs-standard-callbacks.h
+libIDL/IDL.h
+lib$routines.h
+limits
+limits.h
+link.h
+linux/kernel.h
+linux/limits.h
+linux/rtc.h
+linux/version.h
+list
+List.h
+Lists.h
+LiveConnectManagerTests.h
+LListBox.h
+LListener.h
+LMenuBar.h
+LMenu.h
+LModelDirector.h
+LModelObject.h
+LModelProperty.h
+loader.h
+locale
+locale.h
+LOffscreenView.h
+logkeys.h
+logstrng.h
+Looper.h
+LowMem.h
+LPane.h
+LPeriodical.h
+LPicture.h
+LPlaceHolder.h
+LPrintout.h
+LProgressBar.h
+LPushButton.h
+LRadioGroup.h
+LRadioGroupView.h
+LRunArray.h
+LScroller.h
+LSharable.h
+LSingleDoc.h
+LStaticText.h
+LStdControl.h
+LStream.h
+LString.h
+LTabGroup.h
+LTabGroupView.h
+LTableArrayStorage.h
+LTableMonoGeometry.h
+LTableSingleSelector.h
+LTableView.h
+LTextEditView.h
+LTextTableView.h
+LUndoer.h
+LVariableArray.h
+LView.h
+LWindow.h
+m68881.h
+MacErrors.h
+MacHeadersCarbon.h
+machine/ansi.h
+machine/builtins.h
+machine/clock.h
+machine/endian.h
+machine/frame.h
+machine/inline.h
+machine/limits.h
+machine/signal.h
+machine/trap.h
+mach/mach_host.h
+mach/mach_init.h
+mach/mach_interface.h
+mach/mach_port.h
+mach-o/dyld.h
+MacLocales.h
+MacMemory.h
+MacTCP.h
+MacTypes.h
+MacWindows.h
+malloc.h
+map
+mapicode.h
+mapidefs.h
+mapiguid.h
+mapi.h
+mapitags.h
+mapiutil.h
+mapix.h
+Math64.h
+math.h
+mbstring.h
+mem.h
+memory
+memory.h
+Memory.h
+MenuBar.h
+Menu.h
+Menus.h
+Message.h
+Mime.h
+MixedMode.h
+mlang.h
+mmsystem.h
+model.h
+Movies.h
+mpw/errno.h
+mshtmhst.h
+mshtml.h
+mswsock.h
+Multiprocessing.h
+mutex.h
+Navigation.h
+ncompat.h
+ncurses.h
+netCore.h
+netdb.h
+net/if.h
+netinet/in.h
+netinet/in_systm.h
+netinet/tcp.h
+new
+newexe.h
+new.h
+nl_types.h
+NodeInfo.h
+nss.h
+nssilock.h
+objbase.h
+objidl.h
+Objsafe.h
+ojiapitests.h
+ole2.h
+oleidl.h
+OpenTptInternet.h
+OpenTransport.h
+os2.h
+OS.h
+osreldate.h
+OSUtils.h
+Packages.h
+Palettes.h
+PALM_CMN.H
+pango-engine.h
+pango-glyph.h
+pango-modules.h
+pango/pangocairo.h
+pango/pangofc-decoder.h
+pango/pangofc-font.h
+pango/pangofc-fontmap.h
+pango/pango-break.h
+pango/pango-fontmap.h
+pango/pango.h
+pango/pangoxft.h
+pango/pangox.h
+pango/pango-utils.h
+pango-types.h
+pascal.h
+Patches.h
+Path.h
+pcfs/pc_dir.h
+Pgenerr.h
+PGenErr.h
+Ph.h
+photon/Pg.h
+photon/PhProto.h
+photon/PhRender.h
+photon/PpProto.h
+photon/PtProgress.h
+photon/PtServer.h
+photon/PtWebClient.h
+photon/PxImage.h
+pk11func.h
+pk11pub.h
+pkcs11t.h
+PLStringFuncs.h
+PMApplication.h
+pmddim.h
+poll.h
+Polygon.h
+portable.h
+Power.h
+PP_ClassHeaders.cp
+PP_Constants.h
+PPCToolbox.h
+PP_DebugHeaders.cp
+PP_KeyCodes.h
+PP_Macros.h
+PP_Messages.h
+PP_Prefix.h
+PP_Resources.h
+PP_Types.h
+Printing.h
+Print/PMPrintingDialogExtensions.h
+private/qucomextra_p.h
+Processes.h
+process.h
+Process.h
+proto/dos.h
+proto/exec.h
+psap.h
+Pt.h
+pthread.h
+pwd.h
+Python.h
+QDOffscreen.h
+Quickdraw.h
+QuickDraw.h
+QuickTimeComponents.h
+quipu/attr.h
+rasdlg.h
+raserror.h
+ras.h
+regex.h
+Region.h
+resolv.h
+Resources.h
+Retrace.h
+rld_interface.h
+rmsdef.h
+Roster.h
+rpc.h
+rpcproxy.h
+rpc/types.h
+sane/sane.h
+sane/sanei.h
+sane/saneopts.h
+Scrap.h
+Screen.h
+Script.h
+ScrollBar.h
+seccomon.h
+sec.h
+secmod.h
+secmodt.h
+secrng.h
+security.h
+secutil.h
+semaphore.h
+servprov.h
+setjmp.h
+SFNTLayoutTypes.h
+SFNTTypes.h
+share.h
+shellapi.h
+shlguid.h
+shlobj.h
+sigcontext.h
+signal.h
+SimpleGameSound.h
+SIOUX.h
+size_t.h
+someincludefile.h
+Sound.h
+sqlite3.h
+ssdef.h
+sslerr.h
+ssl.h
+sslproto.h
+sstream
+stack
+StandardFile.h
+starlet.h
+stat.h
+statreg.cpp
+statreg.h
+stdarg.h
+stdbool.h
+stddef.h
+stdint.h
+stdio.h
+stdlib.h
+storage/FindDirectory.h
+StorageKit.h
+string
+StringCompare.h
+string.h
+String.h
+strings.h
+Strings.h
+StringView.h
+stropts.h
+strstrea.h
+structs.h
+stsdef.h
+SupportDefs.h
+support/String.h
+support/SupportDefs.h
+support/TLS.h
+svrcore.h
+symconst.h
+sym.h
+synch.h
+syncmgr.h
+sys/atomic_op.h
+sys/bitypes.h
+sys/byteorder.h
+syscall.h
+sys/cdefs.h
+sys/cfgodm.h
+sys/elf.h
+sys/endian.h
+sys/errno.h
+sys/fault.h
+sys/fcntl.h
+sys/file.h
+sys/filio.h
+sys/frame.h
+sys/immu.h
+sys/inttypes.h
+sys/ioccom.h
+sys/ioctl.h
+sys/ipc.h
+sys/ldr.h
+sys/link.h
+sys/locking.h
+syslog.h
+sys/lwp.h
+sys/machine.h
+sys/mman.h
+sys/mmu.h
+sys/mount.h
+sys/mpctl.h
+sys/param.h
+sys/pda.h
+sys/poll.h
+sys/ppc.h
+sys/prctl.h
+sys/priv.h
+sys/procfs.h
+sys/pstat.h
+sys/ptrace.h
+sys/queue.h
+sys/reg.h
+sys/regset.h
+sys/resource.h
+sys/sched.h
+sys/select.h
+sys/sem.h
+sys/sendfile.h
+sys/shm.h
+sys/siginfo.h
+sys/signal.h
+sys/socket.h
+sys/sockio.h
+sys/sparc/frame.h
+sys/stack.h
+sys/statfs.h
+sys/stat.h
+sys/statvfs.h
+sys/syscall.h
+sys/sysctl.h
+sys/sysinfo.h
+sys/sysmp.h
+sys/syssgi.h
+sys/systeminfo.h
+sys/timeb.h
+sys/time.h
+sys/times.h
+sys/ttycom.h
+sys/types.h
+sys/ucontext.h
+sys/uio.h
+sys/un.h
+sys/unistd.h
+sys/utsname.h
+sys/vfs.h
+sys/wait.h
+tables.h
+TArray.h
+TArrayIterator.h
+task.h
+tchar.h
+TCHAR.H
+termios.h
+TextCommon.h
+TextEdit.h
+TextEncodingConverter.h
+TextServices.h
+TextUtils.h
+TextView.h
+th/PCR_Th.h
+thread.h
+ThreadManagerTests.h
+Threads.h
+time.h
+Timer.h
+tlhelp32.h
+ToolUtils.h
+trace.h
+Traps.h
+typeinfo
+types.h
+Types.h
+UAppleEventsMgr.h
+UAttachments.h
+ucontext.h
+uconv.h
+UCursor.h
+ucx$inetdef.h
+UDebugging.h
+UDesktop.h
+UDrawingState.h
+UDrawingUtils.h
+UEnvironment.h
+UEventMgr.h
+UException.h
+UExtractFromAEDesc.h
+UGWorld.h
+UKeyFilters.h
+ulocks.h
+ulserrno.h
+UMemoryMgr.h
+UModalDialogs.h
+UNavServicesDialogs.h
+UnicodeBlockObjects.h
+UnicodeConverter.h
+UnicodeUtilities.h
+unidef.h
+unikbd.h
+unistd.h
+unix.h
+unixio.h
+unixlib.h
+unknwn.h
+UPrinting.h
+UQuickTime.h
+UReanimator.h
+URegions.h
+URegistrar.h
+UResourceMgr.h
+urlhist.h
+urlmon.h
+UScrap.h
+UScreenPort.h
+UTCUtils.h
+UTETextAction.h
+UTEViewTextAction.h
+UTextEdit.h
+UTextTraits.h
+utility
+utime.h
+UWindows.h
+values.h
+varargs.h
+vcclr.h
+vector
+View.h
+Volume.h
+wab.h
+wait.h
+wchar.h
+winbase.h
+win/compobj.h
+windef.h
+Window.h
+windows.h
+Windows.h
+windowsx.h
+Wininet.h
+winnls.h
+winperf.h
+winreg.h
+Winreg.h
+winsock2.h
+winsock.h
+winspool.h
+winsvc.h
+winuser.h
+winver.h
+wmem.h
+workbench/startup.h
+wtypes.h
+wx/image.h
+wx/listctrl.h
+wx/log.h
+wx/toolbar.h
+wx/wx.h
+wx/xrc/xmlres.h
+X11/cursorfont.h
+X11/extensions/Print.h
+X11/extensions/shape.h
+X11/extensions/XIElib.h
+X11/extensions/XShm.h
+X11/extensions/Xrender.h
+X11/Intrinsic.h
+X11/keysymdef.h
+X11/keysym.h
+X11/Shell.h
+X11/StringDefs.h
+X11/Xatom.h
+X11/Xft/Xft.h
+X11/Xfuncproto.h
+X11/X.h
+X11/XKBlib.h
+X11/Xlib.h
+X11/Xlibint.h
+X11/Xlocale.h
+X11/Xos.h
+X11/Xutil.h
+xpt_struct.h
+xpt_xdr.h
+zmouse.h
+sslt.h
+smime.h
+cms.h
+sechash.h
+secoidt.h
+certdb.h
+secerr.h
+nssb64.h
+secasn1.h
+secder.h
+certt.h
+ocsp.h
+keyhi.h
+cryptohi.h
+crmf.h
+pk11pqg.h
+cmmf.h
+base64.h
+secdert.h
+secitem.h
+secmime.h
+nssckbi.h
+pkcs12.h
+p12plcy.h
+pk11sdr.h
+nspr.h
+pratom.h
+prbit.h
+prclist.h
+prcmon.h
+prcountr.h
+prcvar.h
+prdtoa.h
+prenv.h
+prerr.h
+prerror.h
+prinet.h
+prinit.h
+prinrval.h
+prio.h
+pripcsem.h
+prlink.h
+prlock.h
+prlog.h
+prlong.h
+prmem.h
+prmon.h
+prmwait.h
+prnetdb.h
+prolock.h
+prpdce.h
+prprf.h
+prproces.h
+prrng.h
+prrwlock.h
+prshm.h
+prshma.h
+prsystem.h
+prthread.h
+prtime.h
+prtpool.h
+prtrace.h
+prtypes.h
+prvrsion.h
+plbase64.h
+plerror.h
+plgetopt.h
+plresolv.h
+plstr.h
+plarenas.h
+plarena.h
+plhash.h
+#if MOZ_NATIVE_PNG==1
+png.h
+#endif
+#if MOZ_NATIVE_ZLIB==1
+zlib.h
+#endif
+#if MOZ_ENABLE_LIBXUL!=1
+#if BUILD_STATIC_LIBS!=1
+#define WRAP_LCMS_HEADERS
+#endif
+#endif
+#if MOZ_NATIVE_LCMS==1
+#define WRAP_LCMS_HEADERS
+#endif
+#ifdef WRAP_LCMS_HEADERS
+icc34.h
+lcms.h
+#endif
+#ifdef MOZ_ENABLE_STARTUP_NOTIFICATION
+libsn/sn.h
+libsn/sn-common.h
+libsn/sn-launchee.h
+libsn/sn-launcher.h
+libsn/sn-monitor.h
+libsn/sn-util.h
+#endif
+#if MOZ_NATIVE_HUNSPELL==1
+hunspell.hxx
+#endif
+#if MOZ_NATIVE_BZ2==1
+bzlib.h
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/version.mk b/tools/node_modules/expresso/deps/jscoverage/js/config/version.mk
new file mode 100644
index 0000000..3993b3f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/version.mk
@@ -0,0 +1,85 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Netscape Communications Corporation
+# Portions created by the Initial Developer are Copyright (C) 2002
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifndef INCLUDED_VERSION_MK
+INCLUDED_VERSION_MK=1
+
+# Windows gmake build:
+# Build default .rc file if $(RESFILE) isn't defined.
+# TODO:
+# PBI : Private build info. Not used currently.
+# Guessing the best way would be to set an env var.
+# BINARY : Binary name. Not used currently.
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+ifndef RESFILE
+RCFILE=./module.rc
+RESFILE=./module.res
+_RC_STRING = -QUIET 1 -DEPTH $(DEPTH) -TOPSRCDIR $(topsrcdir) -BITS $(MOZ_BITS) -OBJDIR . -SRCDIR $(srcdir) -DISPNAME $(MOZ_APP_DISPLAYNAME)
+ifneq ($(BUILD_OFFICIAL)_$(MOZILLA_OFFICIAL),_)
+_RC_STRING += -OFFICIAL 1
+endif
+ifdef MOZ_DEBUG
+_RC_STRING += -DEBUG 1
+endif
+ifdef MODULE
+_RC_STRING += -MODNAME $(MODULE)
+endif
+ifdef PROGRAM
+_RC_STRING += -BINARY $(PROGRAM)
+else
+ifdef _PROGRAM
+_RC_STRING += -BINARY $(_PROGRAM)
+else
+ifdef SHARED_LIBRARY
+_RC_STRING += -BINARY $(SHARED_LIBRARY)
+endif
+endif
+endif
+ifdef RCINCLUDE
+_RC_STRING += -RCINCLUDE $(srcdir)/$(RCINCLUDE)
+endif
+
+GARBAGE += $(RESFILE) $(RCFILE)
+
+#dummy target so $(RCFILE) doesn't become the default =P
+all::
+
+$(RCFILE): $(RCINCLUDE) $(topsrcdir)/config/version_win.pl
+ $(PERL) $(topsrcdir)/config/version_win.pl $(_RC_STRING)
+
+endif # RESFILE
+endif # Windows
+
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl b/tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl
new file mode 100644
index 0000000..094530e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/config/version_win.pl
@@ -0,0 +1,423 @@
+#!/usr/bin/perl -w
+
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Win32 Version System.
+#
+# The Initial Developer of the Original Code is Brian Bober <netdemonz@yahoo.com>
+# Portions created by the Initial Developer are Copyright (C) 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#use diagnostics;
+require strict;
+my $dir = $0;
+$dir =~ s/[^\/]*$//;
+push(@INC, "$dir");
+require "Moz/Milestone.pm";
+use Getopt::Long;
+use Getopt::Std;
+use POSIX;
+
+# Calculate the number of days since Jan. 1, 2000 from a buildid string
+sub daysFromBuildID
+{
+ my ($buildid,) = @_;
+
+ my ($y, $m, $d, $h) = ($buildid =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/);
+ $d || die("Unrecognized buildid string.");
+
+ my $secondstodays = 60 * 60 * 24;
+ return (POSIX::mktime(00, 00, 00, $d, $m, $y - 1900) -
+ POSIX::mktime(00, 00, 00, 01, 01, 100)) / $secondstodays;
+}
+
+#Creates version resource file
+
+#Paramaters are passed on the command line:
+
+#Example: -MODNAME nsToolkitCompsModule -DEBUG=1
+
+# DEBUG - Mozilla's global debug variable - tells if its debug version
+# OFFICIAL - tells Mozilla is building a milestone or nightly
+# MSTONE - tells which milestone is being built;
+# OBJDIR - Holds the object directory;
+# MODNAME - tells what the name of the module is like nsBMPModule
+# DEPTH - Holds the path to the root obj dir
+# TOPSRCDIR - Holds the path to the root mozilla dir
+# SRCDIR - Holds module.ver and source
+# BINARY - Holds the name of the binary file
+# DISPNAME - Holds the display name of the built application
+# BITS - 16 or 32 bit
+# RCINCLUDE - Holds the name of the RC File to include or ""
+# QUIET - Turns off output
+
+#Description and Comment come from module.ver
+#Bug 23560
+#http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/rc_7x2d.asp
+
+#Get next .ver file entry
+sub getNextEntry
+{
+ while (<VERFILE>)
+ {
+ my $mline = $_;
+ ($mline) = split(/#/,$mline);
+ my ($entry, $value)=split(/=/,$mline,2);
+ if (defined($entry))
+ {
+ if (defined($value))
+ {
+ $entry =~ s/^\s*(.*?)\s*$/$1/;
+ $value =~ s/^\s*(.*?)\s*$/$1/;
+ return ($entry,$value);
+ }
+ }
+ }
+ return undef;
+}
+
+my ($quiet,$objdir,$debug,$official,$milestone,$buildid,$module,$binary,$depth,$rcinclude,$bits,$srcdir,$fileversion,$productversion);
+
+GetOptions( "QUIET" => \$quiet,
+ "DEBUG=s" => \$debug,
+ "OFFICIAL=s" => \$official,
+ "MSTONE=s" => \$milestone,
+ "MODNAME=s" => \$module,
+ "BINARY=s" => \$binary,
+ "DISPNAME=s" => \$displayname,
+ "SRCDIR=s" => \$srcdir,
+ "TOPSRCDIR=s" => \$topsrcdir,
+ "DEPTH=s" => \$depth,
+ "RCINCLUDE=s" => \$rcinclude,
+ "OBJDIR=s" => \$objdir,
+ "BITS=s" => \$bits);
+if (!defined($debug)) {$debug="";}
+if (!defined($official)) {$official="";}
+if (!defined($milestone)) {$milestone="";}
+if (!defined($module)) {$module="";}
+if (!defined($binary)) {$binary="";}
+if (!defined($displayname)) {$displayname="Mozilla";}
+if (!defined($depth)) {$depth=".";}
+if (!defined($rcinclude)) {$rcinclude="";}
+if (!defined($objdir)) {$objdir=".";}
+if (!defined($srcdir)) {$srcdir=".";}
+if (!defined($topsrcdir)) {$topsrcdir=".";}
+if (!defined($bits)) {$bits="";}
+my $mfversion = "Personal";
+my $mpversion = "Personal";
+my @fileflags = ("0");
+my $comment="";
+my $description="";
+if (!defined($module))
+{
+ $module = $binary;
+ ($module) = split(/\./,$module);
+}
+
+my $fileos = "VOS__WINDOWS32";
+if ($bits eq "16") { $fileos="VOS__WINDOWS16"; }
+
+my $bufferstr=" ";
+
+my $MILESTONE_FILE = "$topsrcdir/config/milestone.txt";
+my $BUILDID_FILE = "$depth/config/buildid";
+
+#Read module.ver file
+#Version file overrides for WIN32:
+#WIN32_MODULE_COMMENT
+#WIN32_MODULE_DESCRIPTION
+#WIN32_MODULE_FILEVERSION
+#WIN32_MODULE_COMPANYNAME
+#WIN32_MODULE_FILEVERSION_STRING
+#WIN32_MODULE_NAME
+#WIN32_MODULE_COPYRIGHT
+#WIN32_MODULE_TRADEMARKS
+#WIN32_MODULE_ORIGINAL_FILENAME
+#WIN32_MODULE_PRODUCTNAME
+#WIN32_MODULE_PRODUCTVERSION
+#WIN32_MODULE_PRODUCTVERSION_STRING
+
+#Override values obtained from the .ver file
+my $override_comment;
+my $override_description;
+my $override_fileversion;
+my $override_company;
+my $override_mfversion;
+my $override_module;
+my $override_copyright;
+my $override_trademarks;
+my $override_filename;
+my $override_productname;
+my $override_productversion;
+my $override_mpversion;
+if (open(VERFILE, "<$srcdir/module.ver"))
+{
+
+ my ($a,$b) = getNextEntry();
+ while (defined($a))
+ {
+ if ($a eq "WIN32_MODULE_COMMENT") { $override_comment = $b; }
+ if ($a eq "WIN32_MODULE_DESCRIPTION") { $override_description = $b; }
+ if ($a eq "WIN32_MODULE_FILEVERSION") { $override_fileversion = $b; }
+ if ($a eq "WIN32_MODULE_COMPANYNAME") { $override_company = $b; }
+ if ($a eq "WIN32_MODULE_FILEVERSION_STRING") { $override_mfversion = $b; }
+ if ($a eq "WIN32_MODULE_NAME") { $override_module = $b; }
+ if ($a eq "WIN32_MODULE_COPYRIGHT") { $override_copyright = $b; }
+ if ($a eq "WIN32_MODULE_TRADEMARKS") { $override_trademarks = $b; }
+ if ($a eq "WIN32_MODULE_ORIGINAL_FILENAME") { $override_filename = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTNAME") { $override_productname = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTVERSION") { $override_productversion = $b; }
+ if ($a eq "WIN32_MODULE_PRODUCTVERSION_STRING") { $override_mpversion = $b; }
+ ($a,$b) = getNextEntry();
+ }
+ close(VERFILE)
+}
+else
+{
+ if (!$quiet || $quiet ne "1") { print "$bufferstr" . "WARNING: No module.ver file included ($module, $binary). Default values used\n"; }
+}
+#Get rid of trailing and leading whitespace
+$debug =~ s/^\s*(.*)\s*$/$1/;
+$comment =~ s/^\s*(.*)\s*$/$1/;
+$official =~ s/^\s*(.*)\s*$/$1/;
+$milestone =~ s/^\s*(.*)\s*$/$1/;
+$description =~ s/^\s*(.*)\s*$/$1/;
+$module =~ s/^\s*(.*)\s*$/$1/;
+$depth =~ s/^\s*(.*)\s*$/$1/;
+$binary =~ s/^\s*(.*)\s*$/$1/;
+$displayname =~ s/^\s*(.*)\s*$/$1/;
+
+open(BUILDID, "<", $BUILDID_FILE) || die("Couldn't open buildid file: $BUILDID_FILE");
+$buildid = <BUILDID>;
+$buildid =~ s/\s*$//;
+close BUILDID;
+
+my $daycount = daysFromBuildID($buildid);
+
+if ($milestone eq "") {
+ $milestone = Moz::Milestone::getOfficialMilestone($MILESTONE_FILE);
+}
+
+$mfversion = $mpversion = $milestone;
+
+if ($debug eq "1")
+{
+ push @fileflags, "VS_FF_DEBUG";
+ $mpversion .= " Debug";
+ $mfversion .= " Debug";
+}
+
+if ($official ne "1") {
+ push @fileflags, "VS_FF_PRIVATEBUILD";
+}
+
+if ($milestone =~ /[a-z]/) {
+ push @fileflags, "VS_FF_PRERELEASE";
+}
+
+my @mstone = split(/\./,$milestone);
+$mstone[1] =~s/\D.*$//;
+if (!$mstone[2]) {
+ $mstone[2] = "0";
+}
+else {
+ $mstone[2] =~s/\D.*$//;
+}
+$fileversion = $productversion="$mstone[0],$mstone[1],$mstone[2],$daycount";
+
+my $copyright = "License: MPL 1.1/GPL 2.0/LGPL 2.1";
+my $company = "Mozilla Foundation";
+my $trademarks = "Mozilla";
+my $productname = $displayname;
+
+
+if (defined($override_comment)){$override_comment =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $comment=$override_comment;}
+if (defined($override_description)){$override_description =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $description=$override_description;}
+if (defined($override_fileversion)){$fileversion=$override_fileversion;}
+if (defined($override_mfversion)){$mfversion=$override_mfversion;}
+if (defined($override_company)){$company=$override_company;}
+if (defined($override_module)){$override_module =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $module=$override_module;}
+if (defined($override_copyright)){$override_copyright =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $copyright=$override_copyright;}
+if (defined($override_trademarks)){$override_trademarks =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $trademarks=$override_trademarks;}
+if (defined($override_filename)){$binary=$override_filename;}
+if (defined($override_productname)){$override_productname =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g; $productname=$override_productname;}
+if (defined($override_productversion)){$productversion=$override_productversion;}
+if (defined($override_mpversion)){$mpversion=$override_mpversion;}
+
+
+#Override section
+
+open(RCFILE, ">$objdir/module.rc") || die("Can't edit module.rc - It must be locked.\n");
+print RCFILE qq{
+// ***** BEGIN LICENSE BLOCK *****
+// Version: MPL 1.1/GPL 2.0/LGPL 2.1
+//
+// The contents of this file are subject to the Mozilla Public License Version
+// 1.1 (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.mozilla.org/MPL/
+//
+// Software distributed under the License is distributed on an "AS IS" basis,
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+// for the specific language governing rights and limitations under the
+// License.
+//
+// The Original Code is the Win32 Version System.
+//
+// The Initial Developer of the Original Code is Brian Bober <netdemonz\@yahoo.com>
+// Portions created by the Initial Developer are Copyright (C) 2001
+// the Initial Developer. All Rights Reserved.
+//
+// Contributor(s):
+//
+// Alternatively, the contents of this file may be used under the terms of
+// either the GNU General Public License Version 2 or later (the "GPL"), or
+// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+// in which case the provisions of the GPL or the LGPL are applicable instead
+// of those above. If you wish to allow use of your version of this file only
+// under the terms of either the GPL or the LGPL, and not to allow others to
+// use your version of this file under the terms of the MPL, indicate your
+// decision by deleting the provisions above and replace them with the notice
+// and other provisions required by the GPL or the LGPL. If you do not delete
+// the provisions above, a recipient may use your version of this file under
+// the terms of any one of the MPL, the GPL or the LGPL.
+//
+// ***** END LICENSE BLOCK *****
+
+#include<winver.h>
+
+// Note: if you contain versioning information in an included
+// RC script, it will be discarded
+// Use module.ver to explicitly set these values
+
+// Do not edit this file. Changes won't affect the build.
+
+};
+
+my $versionlevel=0;
+my $insideversion=0;
+if (open(RCINCLUDE, "<$rcinclude"))
+{
+ print RCFILE "// From included resource $rcinclude\n";
+# my $mstring="";
+ while (<RCINCLUDE>)
+ {
+ $_ =~ s/\@MOZ_APP_DISPLAYNAME\@/$displayname/g;
+ print RCFILE $_;
+# my $instr=$_;
+# chomp($instr);
+# $mstring .= "$instr\;";
+ }
+ close(RCINCLUDE);
+# $mstring =~ s/\/\*.*\*\///g;
+# my @mlines = split(/\;/,$mstring);
+# for(@mlines)
+# {
+# my ($nocomment)=split(/\/\//,$_);
+# if (defined($nocomment) && $nocomment ne "")
+# {
+# my ($firststring,$secondstring) = split(/\s+/,$nocomment);
+# if (!defined($firststring)) {$firststring="";}
+# if (!defined($secondstring)) {$secondstring="";}
+# if ($secondstring eq "VERSIONINFO")
+# {
+#if (!$quiet || $quiet ne "1") {
+# print "$bufferstr" . "WARNING: Included RC file ($rcinclude, $module, $binary)\n";
+# print "$bufferstr" . "WARNING: contains versioning information that will be discarded\n";
+# print "$bufferstr" . "WARNING: Remove it and use relevant overrides (in module.ver)\n";
+#}
+# $versionlevel = 0;
+# $insideversion = 1;
+# }
+# if ($firststring eq "BEGIN") { $versionlevel++; }
+# if ($secondstring eq "END")
+# {
+# $versionlevel--;
+# if ($insideversion==1 && $versionlevel==0) {$versionlevel=0;}
+# }
+# my $includecheck = $firststring . $secondstring;
+# $includecheck =~ s/<|>/"/g;
+# $includecheck = lc($includecheck);
+# if ($includecheck ne "#include\"winver.h\"")
+# {
+# if ($insideversion == 0 && $versionlevel == 0)
+# {
+# print RCFILE "$nocomment\n";
+# }
+# }
+# }
+# }
+
+}
+
+my $fileflags = join(' | ', @fileflags);
+
+print RCFILE qq{
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+1 VERSIONINFO
+ FILEVERSION $fileversion
+ PRODUCTVERSION $productversion
+ FILEFLAGSMASK 0x3fL
+ FILEFLAGS $fileflags
+ FILEOS $fileos
+ FILETYPE VFT_DLL
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "Comments", "$comment"
+ VALUE "LegalCopyright", "$copyright"
+ VALUE "CompanyName", "$company"
+ VALUE "FileDescription", "$description"
+ VALUE "FileVersion", "$mfversion"
+ VALUE "ProductVersion", "$mpversion"
+ VALUE "InternalName", "$module"
+ VALUE "LegalTrademarks", "$trademarks"
+ VALUE "OriginalFilename", "$binary"
+ VALUE "ProductName", "$productname"
+ VALUE "BuildID", "$buildid"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
+};
+close(RCFILE);
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/dtoa.c b/tools/node_modules/expresso/deps/jscoverage/js/dtoa.c
new file mode 100644
index 0000000..86e8adc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/dtoa.c
@@ -0,0 +1,3321 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/****************************************************************
+ *
+ * The author of this software is David M. Gay.
+ *
+ * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose without fee is hereby granted, provided that this entire notice
+ * is included in all copies of any software which is or includes a copy
+ * or modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ ***************************************************************/
+
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to "."). */
+
+/* On a machine with IEEE extended-precision registers, it is
+ * necessary to specify double-precision (53-bit) rounding precision
+ * before invoking strtod or dtoa. If the machine uses (the equivalent
+ * of) Intel 80x87 arithmetic, the call
+ * _control87(PC_53, MCW_PC);
+ * does this with many compilers. Whether this or another call is
+ * appropriate depends on the compiler; for this to work, it may be
+ * necessary to #include "float.h" or another system-dependent header
+ * file.
+ */
+
+/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
+ *
+ * This strtod returns a nearest machine number to the input decimal
+ * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
+ * broken by the IEEE round-even rule. Otherwise ties are broken by
+ * biased rounding (add half and chop).
+ *
+ * Inspired loosely by William D. Clinger's paper "How to Read Floating
+ * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *
+ * 1. We only require IEEE, IBM, or VAX double-precision
+ * arithmetic (not IEEE double-extended).
+ * 2. We get by with floating-point arithmetic in a case that
+ * Clinger missed -- when we're computing d * 10^n
+ * for a small integer d and the integer n is not too
+ * much larger than 22 (the maximum integer k for which
+ * we can represent 10^k exactly), we may be able to
+ * compute (d*10^k) * 10^(e-k) with just one roundoff.
+ * 3. Rather than a bit-at-a-time adjustment of the binary
+ * result in the hard case, we use floating-point
+ * arithmetic to determine the adjustment to within
+ * one bit; only in really hard cases do we need to
+ * compute a second residual.
+ * 4. Because of 3., we don't need a large table of powers of 10
+ * for ten-to-e (just some small tables, e.g. of 10^k
+ * for 0 <= k <= 22).
+ */
+
+/*
+ * #define IEEE_8087 for IEEE-arithmetic machines where the least
+ * significant byte has the lowest address.
+ * #define IEEE_MC68k for IEEE-arithmetic machines where the most
+ * significant byte has the lowest address.
+ * #define Long int on machines with 32-bit ints and 64-bit longs.
+ * #define IBM for IBM mainframe-style floating-point arithmetic.
+ * #define VAX for VAX-style floating-point arithmetic (D_floating).
+ * #define No_leftright to omit left-right logic in fast floating-point
+ * computation of dtoa.
+ * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and strtod and dtoa should round accordingly.
+ * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
+ * and Honor_FLT_ROUNDS is not #defined.
+ * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
+ * that use extended-precision instructions to compute rounded
+ * products and quotients) with IBM.
+ * #define ROUND_BIASED for IEEE-format with biased rounding.
+ * #define Inaccurate_Divide for IEEE-format with correctly rounded
+ * products but inaccurate quotients, e.g., for Intel i860.
+ * #define NO_LONG_LONG on machines that do not have a "long long"
+ * integer type (of >= 64 bits). On such machines, you can
+ * #define Just_16 to store 16 bits per 32-bit Long when doing
+ * high-precision integer arithmetic. Whether this speeds things
+ * up or slows things down depends on the machine and the number
+ * being converted. If long long is available and the name is
+ * something other than "long long", #define Llong to be the name,
+ * and if "unsigned Llong" does not work as an unsigned version of
+ * Llong, #define #ULLong to be the corresponding unsigned type.
+ * #define KR_headers for old-style C function headers.
+ * #define Bad_float_h if your system lacks a float.h or if it does not
+ * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
+ * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
+ * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
+ * if memory is available and otherwise does something you deem
+ * appropriate. If MALLOC is undefined, malloc will be invoked
+ * directly -- and assumed always to succeed.
+ * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
+ * memory allocations from a private pool of memory when possible.
+ * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
+ * unless #defined to be a different length. This default length
+ * suffices to get rid of MALLOC calls except for unusual cases,
+ * such as decimal-to-binary conversion of a very long string of
+ * digits. The longest string dtoa can return is about 751 bytes
+ * long. For conversions by strtod of strings of 800 digits and
+ * all dtoa conversions in single-threaded executions with 8-byte
+ * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
+ * pointers, PRIVATE_MEM >= 7112 appears adequate.
+ * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK
+ * #defined automatically on IEEE systems. On such systems,
+ * when INFNAN_CHECK is #defined, strtod checks
+ * for Infinity and NaN (case insensitively). On some systems
+ * (e.g., some HP systems), it may be necessary to #define NAN_WORD0
+ * appropriately -- to the most significant word of a quiet NaN.
+ * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
+ * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
+ * strtod also accepts (case insensitively) strings of the form
+ * NaN(x), where x is a string of hexadecimal digits and spaces;
+ * if there is only one string of hexadecimal digits, it is taken
+ * for the 52 fraction bits of the resulting NaN; if there are two
+ * or more strings of hex digits, the first is for the high 20 bits,
+ * the second and subsequent for the low 32 bits, with intervening
+ * white space ignored; but if this results in none of the 52
+ * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
+ * and NAN_WORD1 are used instead.
+ * #define MULTIPLE_THREADS if the system offers preemptively scheduled
+ * multiple threads. In this case, you must provide (or suitably
+ * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed
+ * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed
+ * in pow5mult, ensures lazy evaluation of only one copy of high
+ * powers of 5; omitting this lock would introduce a small
+ * probability of wasting memory, but would otherwise be harmless.)
+ * You must also invoke freedtoa(s) to free the value s returned by
+ * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined.
+ * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
+ * avoids underflows on inputs whose result does not underflow.
+ * If you #define NO_IEEE_Scale on a machine that uses IEEE-format
+ * floating-point numbers and flushes underflows to zero rather
+ * than implementing gradual underflow, then you must also #define
+ * Sudden_Underflow.
+ * #define USE_LOCALE to use the current locale's decimal_point value.
+ * #define SET_INEXACT if IEEE arithmetic is being used and extra
+ * computation should be done to set the inexact flag when the
+ * result is inexact and avoid setting inexact when the result
+ * is exact. In this case, dtoa.c must be compiled in
+ * an environment, perhaps provided by #include "dtoa.c" in a
+ * suitable wrapper, that defines two functions,
+ * int get_inexact(void);
+ * void clear_inexact(void);
+ * such that get_inexact() returns a nonzero value if the
+ * inexact bit is already set, and clear_inexact() sets the
+ * inexact bit to 0. When SET_INEXACT is #defined, strtod
+ * also does extra computations to set the underflow and overflow
+ * flags when appropriate (i.e., when the result is tiny and
+ * inexact or when it is a numeric value rounded to +-infinity).
+ * #define NO_ERRNO if strtod should not assign errno = ERANGE when
+ * the result overflows to +-Infinity or underflows to 0.
+ */
+
+#ifndef Long
+#define Long long
+#endif
+#ifndef ULong
+typedef unsigned Long ULong;
+#endif
+
+#ifdef DEBUG
+#include "stdio.h"
+#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
+#endif
+
+#include "stdlib.h"
+#include "string.h"
+
+#ifdef USE_LOCALE
+#include "locale.h"
+#endif
+
+#ifdef MALLOC
+#ifdef KR_headers
+extern char *MALLOC();
+#else
+extern void *MALLOC(size_t);
+#endif
+#else
+#define MALLOC malloc
+#endif
+
+#ifndef Omit_Private_Memory
+#ifndef PRIVATE_MEM
+#define PRIVATE_MEM 2304
+#endif
+#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
+static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
+#endif
+
+#undef IEEE_Arith
+#undef Avoid_Underflow
+#ifdef IEEE_MC68k
+#define IEEE_Arith
+#endif
+#ifdef IEEE_8087
+#define IEEE_Arith
+#endif
+
+#ifdef IEEE_Arith
+#ifndef NO_INFNAN_CHECK
+#undef INFNAN_CHECK
+#define INFNAN_CHECK
+#endif
+#else
+#undef INFNAN_CHECK
+#endif
+
+#include "errno.h"
+
+#ifdef Bad_float_h
+
+#ifdef IEEE_Arith
+#define DBL_DIG 15
+#define DBL_MAX_10_EXP 308
+#define DBL_MAX_EXP 1024
+#define FLT_RADIX 2
+#endif /*IEEE_Arith*/
+
+#ifdef IBM
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 75
+#define DBL_MAX_EXP 63
+#define FLT_RADIX 16
+#define DBL_MAX 7.2370055773322621e+75
+#endif
+
+#ifdef VAX
+#define DBL_DIG 16
+#define DBL_MAX_10_EXP 38
+#define DBL_MAX_EXP 127
+#define FLT_RADIX 2
+#define DBL_MAX 1.7014118346046923e+38
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX 2147483647
+#endif
+
+#else /* ifndef Bad_float_h */
+#include "float.h"
+#endif /* Bad_float_h */
+
+#ifndef __MATH_H__
+#include "math.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CONST
+#ifdef KR_headers
+#define CONST /* blank */
+#else
+#define CONST const
+#endif
+#endif
+
+#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1
+Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
+#endif
+
+typedef union { double d; ULong L[2]; } U;
+
+#define dval(x) ((x).d)
+#ifdef IEEE_8087
+#define word0(x) ((x).L[1])
+#define word1(x) ((x).L[0])
+#else
+#define word0(x) ((x).L[0])
+#define word1(x) ((x).L[1])
+#endif
+
+/* The following definition of Storeinc is appropriate for MIPS processors.
+ * An alternative that might be better on some machines is
+ * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ */
+#if defined(IEEE_8087) + defined(VAX)
+#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
+((unsigned short *)a)[0] = (unsigned short)c, a++)
+#else
+#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
+((unsigned short *)a)[1] = (unsigned short)c, a++)
+#endif
+
+/* #define P DBL_MANT_DIG */
+/* Ten_pmax = floor(P*log(2)/log(5)) */
+/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
+/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
+/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
+
+#ifdef IEEE_Arith
+#define Exp_shift 20
+#define Exp_shift1 20
+#define Exp_msk1 0x100000
+#define Exp_msk11 0x100000
+#define Exp_mask 0x7ff00000
+#define P 53
+#define Bias 1023
+#define Emin (-1022)
+#define Exp_1 0x3ff00000
+#define Exp_11 0x3ff00000
+#define Ebits 11
+#define Frac_mask 0xfffff
+#define Frac_mask1 0xfffff
+#define Ten_pmax 22
+#define Bletch 0x10
+#define Bndry_mask 0xfffff
+#define Bndry_mask1 0xfffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 1
+#define Tiny0 0
+#define Tiny1 1
+#define Quick_max 14
+#define Int_max 14
+#ifndef NO_IEEE_Scale
+#define Avoid_Underflow
+#ifdef Flush_Denorm /* debugging option */
+#undef Sudden_Underflow
+#endif
+#endif
+
+#ifndef Flt_Rounds
+#ifdef FLT_ROUNDS
+#define Flt_Rounds FLT_ROUNDS
+#else
+#define Flt_Rounds 1
+#endif
+#endif /*Flt_Rounds*/
+
+#ifdef Honor_FLT_ROUNDS
+#define Rounding rounding
+#undef Check_FLT_ROUNDS
+#define Check_FLT_ROUNDS
+#else
+#define Rounding Flt_Rounds
+#endif
+
+#else /* ifndef IEEE_Arith */
+#undef Check_FLT_ROUNDS
+#undef Honor_FLT_ROUNDS
+#undef SET_INEXACT
+#undef Sudden_Underflow
+#define Sudden_Underflow
+#ifdef IBM
+#undef Flt_Rounds
+#define Flt_Rounds 0
+#define Exp_shift 24
+#define Exp_shift1 24
+#define Exp_msk1 0x1000000
+#define Exp_msk11 0x1000000
+#define Exp_mask 0x7f000000
+#define P 14
+#define Bias 65
+#define Exp_1 0x41000000
+#define Exp_11 0x41000000
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Frac_mask 0xffffff
+#define Frac_mask1 0xffffff
+#define Bletch 4
+#define Ten_pmax 22
+#define Bndry_mask 0xefffff
+#define Bndry_mask1 0xffffff
+#define LSB 1
+#define Sign_bit 0x80000000
+#define Log2P 4
+#define Tiny0 0x100000
+#define Tiny1 0
+#define Quick_max 14
+#define Int_max 15
+#else /* VAX */
+#undef Flt_Rounds
+#define Flt_Rounds 1
+#define Exp_shift 23
+#define Exp_shift1 7
+#define Exp_msk1 0x80
+#define Exp_msk11 0x800000
+#define Exp_mask 0x7f80
+#define P 56
+#define Bias 129
+#define Exp_1 0x40800000
+#define Exp_11 0x4080
+#define Ebits 8
+#define Frac_mask 0x7fffff
+#define Frac_mask1 0xffff007f
+#define Ten_pmax 24
+#define Bletch 2
+#define Bndry_mask 0xffff007f
+#define Bndry_mask1 0xffff007f
+#define LSB 0x10000
+#define Sign_bit 0x8000
+#define Log2P 1
+#define Tiny0 0x80
+#define Tiny1 0
+#define Quick_max 15
+#define Int_max 15
+#endif /* IBM, VAX */
+#endif /* IEEE_Arith */
+
+#ifndef IEEE_Arith
+#define ROUND_BIASED
+#endif
+
+#ifdef RND_PRODQUOT
+#define rounded_product(a,b) a = rnd_prod(a, b)
+#define rounded_quotient(a,b) a = rnd_quot(a, b)
+#ifdef KR_headers
+extern double rnd_prod(), rnd_quot();
+#else
+extern double rnd_prod(double, double), rnd_quot(double, double);
+#endif
+#else
+#define rounded_product(a,b) a *= b
+#define rounded_quotient(a,b) a /= b
+#endif
+
+#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
+#define Big1 0xffffffff
+
+#ifndef Pack_32
+#define Pack_32
+#endif
+
+#ifdef KR_headers
+#define FFFFFFFF ((((unsigned long)0xffff)<<16)|(unsigned long)0xffff)
+#else
+#define FFFFFFFF 0xffffffffUL
+#endif
+
+#ifdef NO_LONG_LONG
+#undef ULLong
+#ifdef Just_16
+#undef Pack_32
+/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
+ * This makes some inner loops simpler and sometimes saves work
+ * during multiplications, but it often seems to make things slightly
+ * slower. Hence the default is now to store 32 bits per Long.
+ */
+#endif
+#else /* long long available */
+#ifndef Llong
+#define Llong long long
+#endif
+#ifndef ULLong
+#define ULLong unsigned Llong
+#endif
+#endif /* NO_LONG_LONG */
+
+#ifndef MULTIPLE_THREADS
+#define ACQUIRE_DTOA_LOCK(n) /*nothing*/
+#define FREE_DTOA_LOCK(n) /*nothing*/
+#endif
+
+#define Kmax 15
+
+ struct
+Bigint {
+ struct Bigint *next;
+ int k, maxwds, sign, wds;
+ ULong x[1];
+ };
+
+ typedef struct Bigint Bigint;
+
+ static Bigint *freelist[Kmax+1];
+
+ static Bigint *
+Balloc
+#ifdef KR_headers
+ (k) int k;
+#else
+ (int k)
+#endif
+{
+ int x;
+ Bigint *rv;
+#ifndef Omit_Private_Memory
+ size_t len;
+#endif
+
+ ACQUIRE_DTOA_LOCK(0);
+ if ((rv = freelist[k])) {
+ freelist[k] = rv->next;
+ }
+ else {
+ x = 1 << k;
+#ifdef Omit_Private_Memory
+ rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+#else
+ len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
+ /sizeof(double);
+ if (pmem_next - private_mem + len <= PRIVATE_mem) {
+ rv = (Bigint*)pmem_next;
+ pmem_next += len;
+ }
+ else
+ rv = (Bigint*)MALLOC(len*sizeof(double));
+#endif
+ rv->k = k;
+ rv->maxwds = x;
+ }
+ FREE_DTOA_LOCK(0);
+ rv->sign = rv->wds = 0;
+ return rv;
+ }
+
+ static void
+Bfree
+#ifdef KR_headers
+ (v) Bigint *v;
+#else
+ (Bigint *v)
+#endif
+{
+ if (v) {
+ ACQUIRE_DTOA_LOCK(0);
+ v->next = freelist[v->k];
+ freelist[v->k] = v;
+ FREE_DTOA_LOCK(0);
+ }
+ }
+
+#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
+y->wds*sizeof(Long) + 2*sizeof(int))
+
+ static Bigint *
+multadd
+#ifdef KR_headers
+ (b, m, a) Bigint *b; int m, a;
+#else
+ (Bigint *b, int m, int a) /* multiply by m and add a */
+#endif
+{
+ int i, wds;
+#ifdef ULLong
+ ULong *x;
+ ULLong carry, y;
+#else
+ ULong carry, *x, y;
+#ifdef Pack_32
+ ULong xi, z;
+#endif
+#endif
+ Bigint *b1;
+
+ wds = b->wds;
+ x = b->x;
+ i = 0;
+ carry = a;
+ do {
+#ifdef ULLong
+ y = *x * (ULLong)m + carry;
+ carry = y >> 32;
+ *x++ = (ULong) y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ xi = *x;
+ y = (xi & 0xffff) * m + carry;
+ z = (xi >> 16) * m + (y >> 16);
+ carry = z >> 16;
+ *x++ = (z << 16) + (y & 0xffff);
+#else
+ y = *x * m + carry;
+ carry = y >> 16;
+ *x++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(++i < wds);
+ if (carry) {
+ if (wds >= b->maxwds) {
+ b1 = Balloc(b->k+1);
+ Bcopy(b1, b);
+ Bfree(b);
+ b = b1;
+ }
+ b->x[wds++] = (ULong) carry;
+ b->wds = wds;
+ }
+ return b;
+ }
+
+ static Bigint *
+s2b
+#ifdef KR_headers
+ (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
+#else
+ (CONST char *s, int nd0, int nd, ULong y9)
+#endif
+{
+ Bigint *b;
+ int i, k;
+ Long x, y;
+
+ x = (nd + 8) / 9;
+ for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+ b = Balloc(k);
+ b->x[0] = y9;
+ b->wds = 1;
+#else
+ b = Balloc(k+1);
+ b->x[0] = y9 & 0xffff;
+ b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
+#endif
+
+ i = 9;
+ if (9 < nd0) {
+ s += 9;
+ do b = multadd(b, 10, *s++ - '0');
+ while(++i < nd0);
+ s++;
+ }
+ else
+ s += 10;
+ for(; i < nd; i++)
+ b = multadd(b, 10, *s++ - '0');
+ return b;
+ }
+
+ static int
+hi0bits
+#ifdef KR_headers
+ (x) register ULong x;
+#else
+ (register ULong x)
+#endif
+{
+ register int k = 0;
+
+ if (!(x & 0xffff0000)) {
+ k = 16;
+ x <<= 16;
+ }
+ if (!(x & 0xff000000)) {
+ k += 8;
+ x <<= 8;
+ }
+ if (!(x & 0xf0000000)) {
+ k += 4;
+ x <<= 4;
+ }
+ if (!(x & 0xc0000000)) {
+ k += 2;
+ x <<= 2;
+ }
+ if (!(x & 0x80000000)) {
+ k++;
+ if (!(x & 0x40000000))
+ return 32;
+ }
+ return k;
+ }
+
+ static int
+lo0bits
+#ifdef KR_headers
+ (y) ULong *y;
+#else
+ (ULong *y)
+#endif
+{
+ register int k;
+ register ULong x = *y;
+
+ if (x & 7) {
+ if (x & 1)
+ return 0;
+ if (x & 2) {
+ *y = x >> 1;
+ return 1;
+ }
+ *y = x >> 2;
+ return 2;
+ }
+ k = 0;
+ if (!(x & 0xffff)) {
+ k = 16;
+ x >>= 16;
+ }
+ if (!(x & 0xff)) {
+ k += 8;
+ x >>= 8;
+ }
+ if (!(x & 0xf)) {
+ k += 4;
+ x >>= 4;
+ }
+ if (!(x & 0x3)) {
+ k += 2;
+ x >>= 2;
+ }
+ if (!(x & 1)) {
+ k++;
+ x >>= 1;
+ if (!x)
+ return 32;
+ }
+ *y = x;
+ return k;
+ }
+
+ static Bigint *
+i2b
+#ifdef KR_headers
+ (i) int i;
+#else
+ (int i)
+#endif
+{
+ Bigint *b;
+
+ b = Balloc(1);
+ b->x[0] = i;
+ b->wds = 1;
+ return b;
+ }
+
+ static Bigint *
+mult
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int k, wa, wb, wc;
+ ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
+ ULong y;
+#ifdef ULLong
+ ULLong carry, z;
+#else
+ ULong carry, z;
+#ifdef Pack_32
+ ULong z2;
+#endif
+#endif
+
+ if (a->wds < b->wds) {
+ c = a;
+ a = b;
+ b = c;
+ }
+ k = a->k;
+ wa = a->wds;
+ wb = b->wds;
+ wc = wa + wb;
+ if (wc > a->maxwds)
+ k++;
+ c = Balloc(k);
+ for(x = c->x, xa = x + wc; x < xa; x++)
+ *x = 0;
+ xa = a->x;
+ xae = xa + wa;
+ xb = b->x;
+ xbe = xb + wb;
+ xc0 = c->x;
+#ifdef ULLong
+ for(; xb < xbe; xc0++) {
+ if ((y = *xb++)) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * (ULLong)y + *xc + carry;
+ carry = z >> 32;
+ *xc++ = (ULong) z & FFFFFFFF;
+ }
+ while(x < xae);
+ *xc = (ULong) carry;
+ }
+ }
+#else
+#ifdef Pack_32
+ for(; xb < xbe; xb++, xc0++) {
+ if (y = *xb & 0xffff) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
+ carry = z >> 16;
+ z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
+ carry = z2 >> 16;
+ Storeinc(xc, z2, z);
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ if (y = *xb >> 16) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ z2 = *xc;
+ do {
+ z = (*x & 0xffff) * y + (*xc >> 16) + carry;
+ carry = z >> 16;
+ Storeinc(xc, z, z2);
+ z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
+ carry = z2 >> 16;
+ }
+ while(x < xae);
+ *xc = z2;
+ }
+ }
+#else
+ for(; xb < xbe; xc0++) {
+ if (y = *xb++) {
+ x = xa;
+ xc = xc0;
+ carry = 0;
+ do {
+ z = *x++ * y + *xc + carry;
+ carry = z >> 16;
+ *xc++ = z & 0xffff;
+ }
+ while(x < xae);
+ *xc = carry;
+ }
+ }
+#endif
+#endif
+ for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
+ c->wds = wc;
+ return c;
+ }
+
+ static Bigint *p5s;
+
+ static Bigint *
+pow5mult
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ Bigint *b1, *p5, *p51;
+ int i;
+ static int p05[3] = { 5, 25, 125 };
+
+ if ((i = k & 3))
+ b = multadd(b, p05[i-1], 0);
+
+ if (!(k >>= 2))
+ return b;
+ if (!(p5 = p5s)) {
+ /* first time */
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p5 = p5s)) {
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p5 = p5s = i2b(625);
+ p5->next = 0;
+#endif
+ }
+ for(;;) {
+ if (k & 1) {
+ b1 = mult(b, p5);
+ Bfree(b);
+ b = b1;
+ }
+ if (!(k >>= 1))
+ break;
+ if (!(p51 = p5->next)) {
+#ifdef MULTIPLE_THREADS
+ ACQUIRE_DTOA_LOCK(1);
+ if (!(p51 = p5->next)) {
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+ }
+ FREE_DTOA_LOCK(1);
+#else
+ p51 = p5->next = mult(p5,p5);
+ p51->next = 0;
+#endif
+ }
+ p5 = p51;
+ }
+ return b;
+ }
+
+ static Bigint *
+lshift
+#ifdef KR_headers
+ (b, k) Bigint *b; int k;
+#else
+ (Bigint *b, int k)
+#endif
+{
+ int i, k1, n, n1;
+ Bigint *b1;
+ ULong *x, *x1, *xe, z;
+
+#ifdef Pack_32
+ n = k >> 5;
+#else
+ n = k >> 4;
+#endif
+ k1 = b->k;
+ n1 = n + b->wds + 1;
+ for(i = b->maxwds; n1 > i; i <<= 1)
+ k1++;
+ b1 = Balloc(k1);
+ x1 = b1->x;
+ for(i = 0; i < n; i++)
+ *x1++ = 0;
+ x = b->x;
+ xe = x + b->wds;
+#ifdef Pack_32
+ if (k &= 0x1f) {
+ k1 = 32 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if ((*x1 = z))
+ ++n1;
+ }
+#else
+ if (k &= 0xf) {
+ k1 = 16 - k;
+ z = 0;
+ do {
+ *x1++ = *x << k & 0xffff | z;
+ z = *x++ >> k1;
+ }
+ while(x < xe);
+ if (*x1 = z)
+ ++n1;
+ }
+#endif
+ else do
+ *x1++ = *x++;
+ while(x < xe);
+ b1->wds = n1 - 1;
+ Bfree(b);
+ return b1;
+ }
+
+ static int
+cmp
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ ULong *xa, *xa0, *xb, *xb0;
+ int i, j;
+
+ i = a->wds;
+ j = b->wds;
+#ifdef DEBUG
+ if (i > 1 && !a->x[i-1])
+ Bug("cmp called with a->x[a->wds-1] == 0");
+ if (j > 1 && !b->x[j-1])
+ Bug("cmp called with b->x[b->wds-1] == 0");
+#endif
+ if (i -= j)
+ return i;
+ xa0 = a->x;
+ xa = xa0 + j;
+ xb0 = b->x;
+ xb = xb0 + j;
+ for(;;) {
+ if (*--xa != *--xb)
+ return *xa < *xb ? -1 : 1;
+ if (xa <= xa0)
+ break;
+ }
+ return 0;
+ }
+
+ static Bigint *
+diff
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ Bigint *c;
+ int i, wa, wb;
+ ULong *xa, *xae, *xb, *xbe, *xc;
+#ifdef ULLong
+ ULLong borrow, y;
+#else
+ ULong borrow, y;
+#ifdef Pack_32
+ ULong z;
+#endif
+#endif
+
+ i = cmp(a,b);
+ if (!i) {
+ c = Balloc(0);
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+ if (i < 0) {
+ c = a;
+ a = b;
+ b = c;
+ i = 1;
+ }
+ else
+ i = 0;
+ c = Balloc(a->k);
+ c->sign = i;
+ wa = a->wds;
+ xa = a->x;
+ xae = xa + wa;
+ wb = b->wds;
+ xb = b->x;
+ xbe = xb + wb;
+ xc = c->x;
+ borrow = 0;
+#ifdef ULLong
+ do {
+ y = (ULLong)*xa++ - *xb++ - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *xc++ = (ULong) y & FFFFFFFF;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *xc++ = (ULong) y & FFFFFFFF;
+ }
+#else
+#ifdef Pack_32
+ do {
+ y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = (*xa & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*xa++ >> 16) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(xc, z, y);
+ }
+#else
+ do {
+ y = *xa++ - *xb++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+ while(xb < xbe);
+ while(xa < xae) {
+ y = *xa++ - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *xc++ = y & 0xffff;
+ }
+#endif
+#endif
+ while(!*--xc)
+ wa--;
+ c->wds = wa;
+ return c;
+ }
+
+ static double
+ulp
+#ifdef KR_headers
+ (x) U x;
+#else
+ (U x)
+#endif
+{
+ register Long L;
+ U a;
+
+ L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ if (L > 0) {
+#endif
+#endif
+#ifdef IBM
+ L |= Exp_msk1 >> 4;
+#endif
+ word0(a) = L;
+ word1(a) = 0;
+#ifndef Avoid_Underflow
+#ifndef Sudden_Underflow
+ }
+ else {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift) {
+ word0(a) = 0x80000 >> L;
+ word1(a) = 0;
+ }
+ else {
+ word0(a) = 0;
+ L -= Exp_shift;
+ word1(a) = L >= 31 ? 1 : 1 << 31 - L;
+ }
+ }
+#endif
+#endif
+ return dval(a);
+ }
+
+ static double
+b2d
+#ifdef KR_headers
+ (a, e) Bigint *a; int *e;
+#else
+ (Bigint *a, int *e)
+#endif
+{
+ ULong *xa, *xa0, w, y, z;
+ int k;
+ U d;
+#ifdef VAX
+ ULong d0, d1;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+ xa0 = a->x;
+ xa = xa0 + a->wds;
+ y = *--xa;
+#ifdef DEBUG
+ if (!y) Bug("zero y in b2d");
+#endif
+ k = hi0bits(y);
+ *e = 32 - k;
+#ifdef Pack_32
+ if (k < Ebits) {
+ d0 = Exp_1 | y >> (Ebits - k);
+ w = xa > xa0 ? *--xa : 0;
+ d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ if (k -= Ebits) {
+ d0 = Exp_1 | y << k | z >> (32 - k);
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k | y >> (32 - k);
+ }
+ else {
+ d0 = Exp_1 | y;
+ d1 = z;
+ }
+#else
+ if (k < Ebits + 16) {
+ z = xa > xa0 ? *--xa : 0;
+ d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
+ w = xa > xa0 ? *--xa : 0;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
+ goto ret_d;
+ }
+ z = xa > xa0 ? *--xa : 0;
+ w = xa > xa0 ? *--xa : 0;
+ k -= Ebits + 16;
+ d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
+ y = xa > xa0 ? *--xa : 0;
+ d1 = w << k + 16 | y << k;
+#endif
+ ret_d:
+#ifdef VAX
+ word0(d) = d0 >> 16 | d0 << 16;
+ word1(d) = d1 >> 16 | d1 << 16;
+#else
+#undef d0
+#undef d1
+#endif
+ return dval(d);
+ }
+
+ static Bigint *
+d2b
+#ifdef KR_headers
+ (d, e, bits) U d; int *e, *bits;
+#else
+ (U d, int *e, int *bits)
+#endif
+{
+ Bigint *b;
+ int de, k;
+ ULong *x, y, z;
+#ifndef Sudden_Underflow
+ int i;
+#endif
+#ifdef VAX
+ ULong d0, d1;
+ d0 = word0(d) >> 16 | word0(d) << 16;
+ d1 = word1(d) >> 16 | word1(d) << 16;
+#else
+#define d0 word0(d)
+#define d1 word1(d)
+#endif
+
+#ifdef Pack_32
+ b = Balloc(1);
+#else
+ b = Balloc(2);
+#endif
+ x = b->x;
+
+ z = d0 & Frac_mask;
+ d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
+#ifdef Sudden_Underflow
+ de = (int)(d0 >> Exp_shift);
+#ifndef IBM
+ z |= Exp_msk11;
+#endif
+#else
+ if ((de = (int)(d0 >> Exp_shift)))
+ z |= Exp_msk1;
+#endif
+#ifdef Pack_32
+ if ((y = d1)) {
+ if ((k = lo0bits(&y))) {
+ x[0] = y | z << (32 - k);
+ z >>= k;
+ }
+ else
+ x[0] = y;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = (x[1] = z) ? 2 : 1;
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ x[0] = z;
+#ifndef Sudden_Underflow
+ i =
+#endif
+ b->wds = 1;
+ k += 32;
+ }
+#else
+ if (y = d1) {
+ if (k = lo0bits(&y))
+ if (k >= 16) {
+ x[0] = y | z << 32 - k & 0xffff;
+ x[1] = z >> k - 16 & 0xffff;
+ x[2] = z >> k;
+ i = 2;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16 | z << 16 - k & 0xffff;
+ x[2] = z >> k & 0xffff;
+ x[3] = z >> k+16;
+ i = 3;
+ }
+ else {
+ x[0] = y & 0xffff;
+ x[1] = y >> 16;
+ x[2] = z & 0xffff;
+ x[3] = z >> 16;
+ i = 3;
+ }
+ }
+ else {
+#ifdef DEBUG
+ if (!z)
+ Bug("Zero passed to d2b");
+#endif
+ k = lo0bits(&z);
+ if (k >= 16) {
+ x[0] = z;
+ i = 0;
+ }
+ else {
+ x[0] = z & 0xffff;
+ x[1] = z >> 16;
+ i = 1;
+ }
+ k += 32;
+ }
+ while(!x[i])
+ --i;
+ b->wds = i + 1;
+#endif
+#ifndef Sudden_Underflow
+ if (de) {
+#endif
+#ifdef IBM
+ *e = (de - Bias - (P-1) << 2) + k;
+ *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
+#else
+ *e = de - Bias - (P-1) + k;
+ *bits = P - k;
+#endif
+#ifndef Sudden_Underflow
+ }
+ else {
+ *e = de - Bias - (P-1) + 1 + k;
+#ifdef Pack_32
+ *bits = 32*i - hi0bits(x[i-1]);
+#else
+ *bits = (i+2)*16 - hi0bits(x[i]);
+#endif
+ }
+#endif
+ return b;
+ }
+#undef d0
+#undef d1
+
+ static double
+ratio
+#ifdef KR_headers
+ (a, b) Bigint *a, *b;
+#else
+ (Bigint *a, Bigint *b)
+#endif
+{
+ U da, db;
+ int k, ka, kb;
+
+ dval(da) = b2d(a, &ka);
+ dval(db) = b2d(b, &kb);
+#ifdef Pack_32
+ k = ka - kb + 32*(a->wds - b->wds);
+#else
+ k = ka - kb + 16*(a->wds - b->wds);
+#endif
+#ifdef IBM
+ if (k > 0) {
+ word0(da) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(da) *= 1 << k;
+ }
+ else {
+ k = -k;
+ word0(db) += (k >> 2)*Exp_msk1;
+ if (k &= 3)
+ dval(db) *= 1 << k;
+ }
+#else
+ if (k > 0)
+ word0(da) += k*Exp_msk1;
+ else {
+ k = -k;
+ word0(db) += k*Exp_msk1;
+ }
+#endif
+ return dval(da) / dval(db);
+ }
+
+ static CONST double
+tens[] = {
+ 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+ 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+ 1e20, 1e21, 1e22
+#ifdef VAX
+ , 1e23, 1e24
+#endif
+ };
+
+ static CONST double
+#ifdef IEEE_Arith
+bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
+#ifdef Avoid_Underflow
+ 9007199254740992.*9007199254740992.e-256
+ /* = 2^106 * 1e-53 */
+#else
+ 1e-256
+#endif
+ };
+/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
+/* flag unnecessarily. It leads to a song and dance at the end of strtod. */
+#define Scale_Bit 0x10
+#define n_bigtens 5
+#else
+#ifdef IBM
+bigtens[] = { 1e16, 1e32, 1e64 };
+static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
+#define n_bigtens 3
+#else
+bigtens[] = { 1e16, 1e32 };
+static CONST double tinytens[] = { 1e-16, 1e-32 };
+#define n_bigtens 2
+#endif
+#endif
+
+#ifdef INFNAN_CHECK
+
+#ifndef NAN_WORD0
+#define NAN_WORD0 0x7ff80000
+#endif
+
+#ifndef NAN_WORD1
+#define NAN_WORD1 0
+#endif
+
+ static int
+match
+#ifdef KR_headers
+ (sp, t) char **sp, *t;
+#else
+ (CONST char **sp, CONST char *t)
+#endif
+{
+ int c, d;
+ CONST char *s = *sp;
+
+ while((d = *t++)) {
+ if ((c = *++s) >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != d)
+ return 0;
+ }
+ *sp = s + 1;
+ return 1;
+ }
+
+#ifndef No_Hex_NaN
+ static void
+hexnan
+#ifdef KR_headers
+ (rvp, sp) U *rvp; CONST char **sp;
+#else
+ (U *rvp, CONST char **sp)
+#endif
+{
+ ULong c, x[2];
+ CONST char *s;
+ int havedig, udx0, xshift;
+
+ x[0] = x[1] = 0;
+ havedig = xshift = 0;
+ udx0 = 1;
+ s = *sp;
+ /* allow optional initial 0x or 0X */
+ while((c = *(CONST unsigned char*)(s+1)) && c <= ' ')
+ ++s;
+ if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X'))
+ s += 2;
+ while((c = *(CONST unsigned char*)++s)) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c += 10 - 'a';
+ else if (c >= 'A' && c <= 'F')
+ c += 10 - 'A';
+ else if (c <= ' ') {
+ if (udx0 && havedig) {
+ udx0 = 0;
+ xshift = 1;
+ }
+ continue;
+ }
+#ifdef GDTOA_NON_PEDANTIC_NANCHECK
+ else if (/*(*/ c == ')' && havedig) {
+ *sp = s + 1;
+ break;
+ }
+ else
+ return; /* invalid form: don't change *sp */
+#else
+ else {
+ do {
+ if (/*(*/ c == ')') {
+ *sp = s + 1;
+ break;
+ }
+ } while((c = *++s));
+ break;
+ }
+#endif
+ havedig = 1;
+ if (xshift) {
+ xshift = 0;
+ x[0] = x[1];
+ x[1] = 0;
+ }
+ if (udx0)
+ x[0] = (x[0] << 4) | (x[1] >> 28);
+ x[1] = (x[1] << 4) | c;
+ }
+ if ((x[0] &= 0xfffff) || x[1]) {
+ word0(*rvp) = Exp_mask | x[0];
+ word1(*rvp) = x[1];
+ }
+ }
+#endif /*No_Hex_NaN*/
+#endif /* INFNAN_CHECK */
+
+ static double
+_strtod
+#ifdef KR_headers
+ (s00, se) CONST char *s00; char **se;
+#else
+ (CONST char *s00, char **se)
+#endif
+{
+#ifdef Avoid_Underflow
+ int scale;
+#endif
+ int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
+ e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+ CONST char *s, *s0, *s1;
+ double aadj, adj;
+ U aadj1, rv, rv0;
+ Long L;
+ ULong y, z;
+ Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+#ifdef USE_LOCALE
+ CONST char *s2;
+#endif
+
+#ifdef __GNUC__
+ delta = bb = bd = bs = 0;
+#endif
+
+ sign = nz0 = nz = 0;
+ dval(rv) = 0.;
+ for(s = s00;;s++) switch(*s) {
+ case '-':
+ sign = 1;
+ /* no break */
+ case '+':
+ if (*++s)
+ goto break2;
+ /* no break */
+ case 0:
+ goto ret0;
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ continue;
+ default:
+ goto break2;
+ }
+ break2:
+ if (*s == '0') {
+ nz0 = 1;
+ while(*++s == '0') ;
+ if (!*s)
+ goto ret;
+ }
+ s0 = s;
+ y = z = 0;
+ for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
+ if (nd < 9)
+ y = 10*y + c - '0';
+ else if (nd < 16)
+ z = 10*z + c - '0';
+ nd0 = nd;
+#ifdef USE_LOCALE
+ s1 = localeconv()->decimal_point;
+ if (c == *s1) {
+ c = '.';
+ if (*++s1) {
+ s2 = s;
+ for(;;) {
+ if (*++s2 != *s1) {
+ c = 0;
+ break;
+ }
+ if (!*++s1) {
+ s = s2;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ if (c == '.') {
+ c = *++s;
+ if (!nd) {
+ for(; c == '0'; c = *++s)
+ nz++;
+ if (c > '0' && c <= '9') {
+ s0 = s;
+ nf += nz;
+ nz = 0;
+ goto have_dig;
+ }
+ goto dig_done;
+ }
+ for(; c >= '0' && c <= '9'; c = *++s) {
+ have_dig:
+ nz++;
+ if (c -= '0') {
+ nf += nz;
+ for(i = 1; i < nz; i++)
+ if (nd++ < 9)
+ y *= 10;
+ else if (nd <= DBL_DIG + 1)
+ z *= 10;
+ if (nd++ < 9)
+ y = 10*y + c;
+ else if (nd <= DBL_DIG + 1)
+ z = 10*z + c;
+ nz = 0;
+ }
+ }
+ }
+ dig_done:
+ e = 0;
+ if (c == 'e' || c == 'E') {
+ if (!nd && !nz && !nz0) {
+ goto ret0;
+ }
+ s00 = s;
+ esign = 0;
+ switch(c = *++s) {
+ case '-':
+ esign = 1;
+ case '+':
+ c = *++s;
+ }
+ if (c >= '0' && c <= '9') {
+ while(c == '0')
+ c = *++s;
+ if (c > '0' && c <= '9') {
+ L = c - '0';
+ s1 = s;
+ while((c = *++s) >= '0' && c <= '9')
+ L = 10*L + c - '0';
+ if (s - s1 > 8 || L > 19999)
+ /* Avoid confusion from exponents
+ * so large that e might overflow.
+ */
+ e = 19999; /* safe for 16 bit ints */
+ else
+ e = (int)L;
+ if (esign)
+ e = -e;
+ }
+ else
+ e = 0;
+ }
+ else
+ s = s00;
+ }
+ if (!nd) {
+ if (!nz && !nz0) {
+#ifdef INFNAN_CHECK
+ /* Check for Nan and Infinity */
+ switch(c) {
+ case 'i':
+ case 'I':
+ if (match(&s,"nf")) {
+ --s;
+ if (!match(&s,"inity"))
+ ++s;
+ word0(rv) = 0x7ff00000;
+ word1(rv) = 0;
+ goto ret;
+ }
+ break;
+ case 'n':
+ case 'N':
+ if (match(&s, "an")) {
+ word0(rv) = NAN_WORD0;
+ word1(rv) = NAN_WORD1;
+#ifndef No_Hex_NaN
+ if (*s == '(') /*)*/
+ hexnan(&rv, &s);
+#endif
+ goto ret;
+ }
+ }
+#endif /* INFNAN_CHECK */
+ ret0:
+ s = s00;
+ sign = 0;
+ }
+ goto ret;
+ }
+ e1 = e -= nf;
+
+ /* Now we have nd0 digits, starting at s0, followed by a
+ * decimal point, followed by nd-nd0 digits. The number we're
+ * after is the integer represented by those digits times
+ * 10**e */
+
+ if (!nd0)
+ nd0 = nd;
+ k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
+ dval(rv) = y;
+ if (k > 9) {
+#ifdef SET_INEXACT
+ if (k > DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+ dval(rv) = tens[k - 9] * dval(rv) + z;
+ }
+ bd0 = 0;
+ if (nd <= DBL_DIG
+#ifndef RND_PRODQUOT
+#ifndef Honor_FLT_ROUNDS
+ && Flt_Rounds == 1
+#endif
+#endif
+ ) {
+ if (!e)
+ goto ret;
+ if (e > 0) {
+ if (e <= Ten_pmax) {
+#ifdef VAX
+ goto vax_ovfl_check;
+#else
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ goto ret;
+#endif
+ }
+ i = DBL_DIG - nd;
+ if (e <= Ten_pmax + i) {
+ /* A fancier test would sometimes let us do
+ * this for larger i values.
+ */
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ e -= i;
+ dval(rv) *= tens[i];
+#ifdef VAX
+ /* VAX exponent range is so narrow we must
+ * worry about overflow here...
+ */
+ vax_ovfl_check:
+ word0(rv) -= P*Exp_msk1;
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+ if ((word0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+ goto ovfl;
+ word0(rv) += P*Exp_msk1;
+#else
+ /* rv = */ rounded_product(dval(rv), tens[e]);
+#endif
+ goto ret;
+ }
+ }
+#ifndef Inaccurate_Divide
+ else if (e >= -Ten_pmax) {
+#ifdef Honor_FLT_ROUNDS
+ /* round correctly FLT_ROUNDS = 2 or 3 */
+ if (sign) {
+ rv = -rv;
+ sign = 0;
+ }
+#endif
+ /* rv = */ rounded_quotient(dval(rv), tens[-e]);
+ goto ret;
+ }
+#endif
+ }
+ e1 += nd - k;
+
+#ifdef IEEE_Arith
+#ifdef SET_INEXACT
+ inexact = 1;
+ if (k <= DBL_DIG)
+ oldinexact = get_inexact();
+#endif
+#ifdef Avoid_Underflow
+ scale = 0;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding = Flt_Rounds) >= 2) {
+ if (sign)
+ rounding = rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding = 0;
+ }
+#endif
+#endif /*IEEE_Arith*/
+
+ /* Get starting approximation = rv * 10**e1 */
+
+ if (e1 > 0) {
+ if ((i = e1 & 15))
+ dval(rv) *= tens[i];
+ if (e1 &= ~15) {
+ if (e1 > DBL_MAX_10_EXP) {
+ ovfl:
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ /* Can't trust HUGE_VAL */
+#ifdef IEEE_Arith
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case 0: /* toward 0 */
+ case 3: /* toward -infinity */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ break;
+ default:
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+ }
+#else /*Honor_FLT_ROUNDS*/
+ word0(rv) = Exp_mask;
+ word1(rv) = 0;
+#endif /*Honor_FLT_ROUNDS*/
+#ifdef SET_INEXACT
+ /* set overflow bit */
+ dval(rv0) = 1e300;
+ dval(rv0) *= dval(rv0);
+#endif
+#else /*IEEE_Arith*/
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+#endif /*IEEE_Arith*/
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+ e1 >>= 4;
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= bigtens[j];
+ /* The last multiplication could overflow. */
+ word0(rv) -= P*Exp_msk1;
+ dval(rv) *= bigtens[j];
+ if ((z = word0(rv) & Exp_mask)
+ > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+ goto ovfl;
+ if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
+ /* set to largest number */
+ /* (Can't trust DBL_MAX) */
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ }
+ else
+ word0(rv) += P*Exp_msk1;
+ }
+ }
+ else if (e1 < 0) {
+ e1 = -e1;
+ if ((i = e1 & 15))
+ dval(rv) /= tens[i];
+ if (e1 >>= 4) {
+ if (e1 >= 1 << n_bigtens)
+ goto undfl;
+#ifdef Avoid_Underflow
+ if (e1 & Scale_Bit)
+ scale = 2*P;
+ for(j = 0; e1 > 0; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
+ >> Exp_shift)) > 0) {
+ /* scaled rv is denormal; zap j low bits */
+ if (j >= 32) {
+ word1(rv) = 0;
+ if (j >= 53)
+ word0(rv) = (P+2)*Exp_msk1;
+ else
+ word0(rv) &= 0xffffffff << (j-32);
+ }
+ else
+ word1(rv) &= 0xffffffff << j;
+ }
+#else
+ for(j = 0; e1 > 1; j++, e1 >>= 1)
+ if (e1 & 1)
+ dval(rv) *= tinytens[j];
+ /* The last multiplication could underflow. */
+ dval(rv0) = dval(rv);
+ dval(rv) *= tinytens[j];
+ if (!dval(rv)) {
+ dval(rv) = 2.*dval(rv0);
+ dval(rv) *= tinytens[j];
+#endif
+ if (!dval(rv)) {
+ undfl:
+ dval(rv) = 0.;
+#ifndef NO_ERRNO
+ errno = ERANGE;
+#endif
+ if (bd0)
+ goto retfree;
+ goto ret;
+ }
+#ifndef Avoid_Underflow
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ /* The refinement below will clean
+ * this approximation up.
+ */
+ }
+#endif
+ }
+ }
+
+ /* Now the hard part -- adjusting rv to the correct value.*/
+
+ /* Put digits into bd: true value = bd * 10^e */
+
+ bd0 = s2b(s0, nd0, nd, y);
+
+ for(;;) {
+ bd = Balloc(bd0->k);
+ Bcopy(bd, bd0);
+ bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
+ bs = i2b(1);
+
+ if (e >= 0) {
+ bb2 = bb5 = 0;
+ bd2 = bd5 = e;
+ }
+ else {
+ bb2 = bb5 = -e;
+ bd2 = bd5 = 0;
+ }
+ if (bbe >= 0)
+ bb2 += bbe;
+ else
+ bd2 -= bbe;
+ bs2 = bb2;
+#ifdef Honor_FLT_ROUNDS
+ if (rounding != 1)
+ bs2++;
+#endif
+#ifdef Avoid_Underflow
+ j = bbe - scale;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#else /*Avoid_Underflow*/
+#ifdef Sudden_Underflow
+#ifdef IBM
+ j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
+#else
+ j = P + 1 - bbbits;
+#endif
+#else /*Sudden_Underflow*/
+ j = bbe;
+ i = j + bbbits - 1; /* logb(rv) */
+ if (i < Emin) /* denormal */
+ j += P - Emin;
+ else
+ j = P + 1 - bbbits;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ bb2 += j;
+ bd2 += j;
+#ifdef Avoid_Underflow
+ bd2 += scale;
+#endif
+ i = bb2 < bd2 ? bb2 : bd2;
+ if (i > bs2)
+ i = bs2;
+ if (i > 0) {
+ bb2 -= i;
+ bd2 -= i;
+ bs2 -= i;
+ }
+ if (bb5 > 0) {
+ bs = pow5mult(bs, bb5);
+ bb1 = mult(bs, bb);
+ Bfree(bb);
+ bb = bb1;
+ }
+ if (bb2 > 0)
+ bb = lshift(bb, bb2);
+ if (bd5 > 0)
+ bd = pow5mult(bd, bd5);
+ if (bd2 > 0)
+ bd = lshift(bd, bd2);
+ if (bs2 > 0)
+ bs = lshift(bs, bs2);
+ delta = diff(bb, bd);
+ dsign = delta->sign;
+ delta->sign = 0;
+ i = cmp(delta, bs);
+#ifdef Honor_FLT_ROUNDS
+ if (rounding != 1) {
+ if (i < 0) {
+ /* Error is less than an ulp */
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (rounding) {
+ if (dsign) {
+ adj = 1.;
+ goto apply_adj;
+ }
+ }
+ else if (!dsign) {
+ adj = -1.;
+ if (!word1(rv)
+ && !(word0(rv) & Frac_mask)) {
+ y = word0(rv) & Exp_mask;
+#ifdef Avoid_Underflow
+ if (!scale || y > 2*P*Exp_msk1)
+#else
+ if (y)
+#endif
+ {
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) <= 0)
+ adj = -0.5;
+ }
+ }
+ apply_adj:
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(rv) & Exp_mask)
+ <= 2*P*Exp_msk1)
+ word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <=
+ P*Exp_msk1) {
+ word0(rv) += P*Exp_msk1;
+ dval(rv) += adj*ulp(rv);
+ word0(rv) -= P*Exp_msk1;
+ }
+ else
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ dval(rv) += adj*ulp(rv);
+ }
+ break;
+ }
+ adj = ratio(delta, bs);
+ if (adj < 1.)
+ adj = 1.;
+ if (adj <= 0x7ffffffe) {
+ /* adj = rounding ? ceil(adj) : floor(adj); */
+ y = adj;
+ if (y != adj) {
+ if (!((rounding>>1) ^ dsign))
+ y++;
+ adj = y;
+ }
+ }
+#ifdef Avoid_Underflow
+ if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ word0(adj) += (2*P+1)*Exp_msk1 - y;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+ word0(rv) += P*Exp_msk1;
+ adj *= ulp(rv);
+ if (dsign)
+ dval(rv) += adj;
+ else
+ dval(rv) -= adj;
+ word0(rv) -= P*Exp_msk1;
+ goto cont;
+ }
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ adj *= ulp(rv);
+ if (dsign)
+ dval(rv) += adj;
+ else
+ dval(rv) -= adj;
+ goto cont;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+
+ if (i < 0) {
+ /* Error is less than half an ulp -- check for
+ * special case of mantissa a power of two.
+ */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask
+#ifdef IEEE_Arith
+#ifdef Avoid_Underflow
+ || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
+#else
+ || (word0(rv) & Exp_mask) <= Exp_msk1
+#endif
+#endif
+ ) {
+#ifdef SET_INEXACT
+ if (!delta->x[0] && delta->wds <= 1)
+ inexact = 0;
+#endif
+ break;
+ }
+ if (!delta->x[0] && delta->wds <= 1) {
+ /* exact result */
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ delta = lshift(delta,Log2P);
+ if (cmp(delta, bs) > 0)
+ goto drop_down;
+ break;
+ }
+ if (i == 0) {
+ /* exactly half-way between */
+ if (dsign) {
+ if ((word0(rv) & Bndry_mask1) == Bndry_mask1
+ && word1(rv) == (
+#ifdef Avoid_Underflow
+ (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
+ ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
+#endif
+ 0xffffffff)) {
+ /*boundary case -- increment exponent*/
+ word0(rv) = (word0(rv) & Exp_mask)
+ + Exp_msk1
+#ifdef IBM
+ | Exp_msk1 >> 4
+#endif
+ ;
+ word1(rv) = 0;
+#ifdef Avoid_Underflow
+ dsign = 0;
+#endif
+ break;
+ }
+ }
+ else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
+ drop_down:
+ /* boundary case -- decrement exponent */
+#ifdef Sudden_Underflow /*{{*/
+ L = word0(rv) & Exp_mask;
+#ifdef IBM
+ if (L < Exp_msk1)
+#else
+#ifdef Avoid_Underflow
+ if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
+#else
+ if (L <= Exp_msk1)
+#endif /*Avoid_Underflow*/
+#endif /*IBM*/
+ goto undfl;
+ L -= Exp_msk1;
+#else /*Sudden_Underflow}{*/
+#ifdef Avoid_Underflow
+ if (scale) {
+ L = word0(rv) & Exp_mask;
+ if (L <= (2*P+1)*Exp_msk1) {
+ if (L > (P+2)*Exp_msk1)
+ /* round even ==> */
+ /* accept rv */
+ break;
+ /* rv = smallest denormal */
+ goto undfl;
+ }
+ }
+#endif /*Avoid_Underflow*/
+ L = (word0(rv) & Exp_mask) - Exp_msk1;
+#endif /*Sudden_Underflow}}*/
+ word0(rv) = L | Bndry_mask1;
+ word1(rv) = 0xffffffff;
+#ifdef IBM
+ goto cont;
+#else
+ break;
+#endif
+ }
+#ifndef ROUND_BIASED
+ if (!(word1(rv) & LSB))
+ break;
+#endif
+ if (dsign)
+ dval(rv) += ulp(rv);
+#ifndef ROUND_BIASED
+ else {
+ dval(rv) -= ulp(rv);
+#ifndef Sudden_Underflow
+ if (!dval(rv))
+ goto undfl;
+#endif
+ }
+#ifdef Avoid_Underflow
+ dsign = 1 - dsign;
+#endif
+#endif
+ break;
+ }
+ if ((aadj = ratio(delta, bs)) <= 2.) {
+ if (dsign)
+ aadj = dval(aadj1) = 1.;
+ else if (word1(rv) || word0(rv) & Bndry_mask) {
+#ifndef Sudden_Underflow
+ if (word1(rv) == Tiny1 && !word0(rv))
+ goto undfl;
+#endif
+ aadj = 1.;
+ dval(aadj1) = -1.;
+ }
+ else {
+ /* special case -- power of FLT_RADIX to be */
+ /* rounded down... */
+
+ if (aadj < 2./FLT_RADIX)
+ aadj = 1./FLT_RADIX;
+ else
+ aadj *= 0.5;
+ dval(aadj1) = -aadj;
+ }
+ }
+ else {
+ aadj *= 0.5;
+ dval(aadj1) = dsign ? aadj : -aadj;
+#ifdef Check_FLT_ROUNDS
+ switch(Rounding) {
+ case 2: /* towards +infinity */
+ dval(aadj1) -= 0.5;
+ break;
+ case 0: /* towards 0 */
+ case 3: /* towards -infinity */
+ dval(aadj1) += 0.5;
+ }
+#else
+ if (Flt_Rounds == 0)
+ dval(aadj1) += 0.5;
+#endif /*Check_FLT_ROUNDS*/
+ }
+ y = word0(rv) & Exp_mask;
+
+ /* Check for overflow */
+
+ if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
+ dval(rv0) = dval(rv);
+ word0(rv) -= P*Exp_msk1;
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+ if ((word0(rv) & Exp_mask) >=
+ Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
+ if (word0(rv0) == Big0 && word1(rv0) == Big1)
+ goto ovfl;
+ word0(rv) = Big0;
+ word1(rv) = Big1;
+ goto cont;
+ }
+ else
+ word0(rv) += P*Exp_msk1;
+ }
+ else {
+#ifdef Avoid_Underflow
+ if (scale && y <= 2*P*Exp_msk1) {
+ if (aadj <= 0x7fffffff) {
+ if ((z = (ULong) aadj) <= 0)
+ z = 1;
+ aadj = z;
+ dval(aadj1) = dsign ? aadj : -aadj;
+ }
+ word0(aadj1) += (2*P+1)*Exp_msk1 - y;
+ }
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+#else
+#ifdef Sudden_Underflow
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
+ dval(rv0) = dval(rv);
+ word0(rv) += P*Exp_msk1;
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+#ifdef IBM
+ if ((word0(rv) & Exp_mask) < P*Exp_msk1)
+#else
+ if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+#endif
+ {
+ if (word0(rv0) == Tiny0
+ && word1(rv0) == Tiny1)
+ goto undfl;
+ word0(rv) = Tiny0;
+ word1(rv) = Tiny1;
+ goto cont;
+ }
+ else
+ word0(rv) -= P*Exp_msk1;
+ }
+ else {
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+ }
+#else /*Sudden_Underflow*/
+ /* Compute adj so that the IEEE rounding rules will
+ * correctly round rv + adj in some half-way cases.
+ * If rv * ulp(rv) is denormalized (i.e.,
+ * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
+ * trouble from bits lost to denormalization;
+ * example: 1.2e-307 .
+ */
+ if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
+ dval(aadj1) = (double)(int)(aadj + 0.5);
+ if (!dsign)
+ dval(aadj1) = -dval(aadj1);
+ }
+ adj = dval(aadj1) * ulp(rv);
+ dval(rv) += adj;
+#endif /*Sudden_Underflow*/
+#endif /*Avoid_Underflow*/
+ }
+ z = word0(rv) & Exp_mask;
+#ifndef SET_INEXACT
+#ifdef Avoid_Underflow
+ if (!scale)
+#endif
+ if (y == z) {
+ /* Can we stop now? */
+ L = (Long)aadj;
+ aadj -= L;
+ /* The tolerances below are conservative. */
+ if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
+ if (aadj < .4999999 || aadj > .5000001)
+ break;
+ }
+ else if (aadj < .4999999/FLT_RADIX)
+ break;
+ }
+#endif
+ cont:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(delta);
+ }
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(rv0) = Exp_1 + (70 << Exp_shift);
+ word1(rv0) = 0;
+ dval(rv0) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+#ifdef Avoid_Underflow
+ if (scale) {
+ word0(rv0) = Exp_1 - 2*P*Exp_msk1;
+ word1(rv0) = 0;
+ dval(rv) *= dval(rv0);
+#ifndef NO_ERRNO
+ /* try to avoid the bug of testing an 8087 register value */
+ if (word0(rv) == 0 && word1(rv) == 0)
+ errno = ERANGE;
+#endif
+ }
+#endif /* Avoid_Underflow */
+#ifdef SET_INEXACT
+ if (inexact && !(word0(rv) & Exp_mask)) {
+ /* set underflow bit */
+ dval(rv0) = 1e-300;
+ dval(rv0) *= dval(rv0);
+ }
+#endif
+ retfree:
+ Bfree(bb);
+ Bfree(bd);
+ Bfree(bs);
+ Bfree(bd0);
+ Bfree(delta);
+ ret:
+ if (se)
+ *se = (char *)s;
+ return sign ? -dval(rv) : dval(rv);
+ }
+
+ static int
+quorem
+#ifdef KR_headers
+ (b, S) Bigint *b, *S;
+#else
+ (Bigint *b, Bigint *S)
+#endif
+{
+ int n;
+ ULong *bx, *bxe, q, *sx, *sxe;
+#ifdef ULLong
+ ULLong borrow, carry, y, ys;
+#else
+ ULong borrow, carry, y, ys;
+#ifdef Pack_32
+ ULong si, z, zs;
+#endif
+#endif
+
+ n = S->wds;
+#ifdef DEBUG
+ /*debug*/ if (b->wds > n)
+ /*debug*/ Bug("oversize b in quorem");
+#endif
+ if (b->wds < n)
+ return 0;
+ sx = S->x;
+ sxe = sx + --n;
+ bx = b->x;
+ bxe = bx + n;
+ q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
+#ifdef DEBUG
+ /*debug*/ if (q > 9)
+ /*debug*/ Bug("oversized quotient in quorem");
+#endif
+ if (q) {
+ borrow = 0;
+ carry = 0;
+ do {
+#ifdef ULLong
+ ys = *sx++ * (ULLong)q + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = (ULong) y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) * q + carry;
+ zs = (si >> 16) * q + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ * q + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ if (!*bxe) {
+ bx = b->x;
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ if (cmp(b, S) >= 0) {
+ q++;
+ borrow = 0;
+ carry = 0;
+ bx = b->x;
+ sx = S->x;
+ do {
+#ifdef ULLong
+ ys = *sx++ + carry;
+ carry = ys >> 32;
+ y = *bx - (ys & FFFFFFFF) - borrow;
+ borrow = y >> 32 & (ULong)1;
+ *bx++ = (ULong) y & FFFFFFFF;
+#else
+#ifdef Pack_32
+ si = *sx++;
+ ys = (si & 0xffff) + carry;
+ zs = (si >> 16) + (ys >> 16);
+ carry = zs >> 16;
+ y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ z = (*bx >> 16) - (zs & 0xffff) - borrow;
+ borrow = (z & 0x10000) >> 16;
+ Storeinc(bx, z, y);
+#else
+ ys = *sx++ + carry;
+ carry = ys >> 16;
+ y = *bx - (ys & 0xffff) - borrow;
+ borrow = (y & 0x10000) >> 16;
+ *bx++ = y & 0xffff;
+#endif
+#endif
+ }
+ while(sx <= sxe);
+ bx = b->x;
+ bxe = bx + n;
+ if (!*bxe) {
+ while(--bxe > bx && !*bxe)
+ --n;
+ b->wds = n;
+ }
+ }
+ return q;
+ }
+
+#ifndef MULTIPLE_THREADS
+ static char *dtoa_result;
+#endif
+
+ static char *
+#ifdef KR_headers
+rv_alloc(i) int i;
+#else
+rv_alloc(int i)
+#endif
+{
+ int j, k, *r;
+
+ j = sizeof(ULong);
+ for(k = 0;
+ sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= (unsigned) i;
+ j <<= 1)
+ k++;
+ r = (int*)Balloc(k);
+ *r = k;
+ return
+#ifndef MULTIPLE_THREADS
+ dtoa_result =
+#endif
+ (char *)(r+1);
+ }
+
+ static char *
+#ifdef KR_headers
+nrv_alloc(s, rve, n) char *s, **rve; int n;
+#else
+nrv_alloc(CONST char *s, char **rve, int n)
+#endif
+{
+ char *rv, *t;
+
+ t = rv = rv_alloc(n);
+ while((*t = *s++)) t++;
+ if (rve)
+ *rve = t;
+ return rv;
+ }
+
+/* freedtoa(s) must be used to free values s returned by dtoa
+ * when MULTIPLE_THREADS is #defined. It should be used in all cases,
+ * but for consistency with earlier versions of dtoa, it is optional
+ * when MULTIPLE_THREADS is not defined.
+ */
+
+ void
+#ifdef KR_headers
+freedtoa(s) char *s;
+#else
+freedtoa(char *s)
+#endif
+{
+ Bigint *b = (Bigint *)((int *)s - 1);
+ b->maxwds = 1 << (b->k = *(int*)b);
+ Bfree(b);
+#ifndef MULTIPLE_THREADS
+ if (s == dtoa_result)
+ dtoa_result = 0;
+#endif
+ }
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
+ *
+ * Modifications:
+ * 1. Rather than iterating, we use a simple numeric overestimate
+ * to determine k = floor(log10(d)). We scale relevant
+ * quantities using O(log2(k)) rather than O(k) multiplications.
+ * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ * try to generate digits strictly left to right. Instead, we
+ * compute with fewer bits and propagate the carry if necessary
+ * when rounding the final digit up. This is often faster.
+ * 3. Under the assumption that input will be rounded nearest,
+ * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ * That is, we allow equality in stopping tests when the
+ * round-nearest rule will give the same floating-point value
+ * as would satisfaction of the stopping test with strict
+ * inequality.
+ * 4. We remove common factors of powers of 2 from relevant
+ * quantities.
+ * 5. When converting floating-point integers less than 1e16,
+ * we use floating-point arithmetic rather than resorting
+ * to multiple-precision integers.
+ * 6. When asked to produce fewer than 15 digits, we first try
+ * to get by with floating-point arithmetic; we resort to
+ * multiple-precision integer arithmetic only if we cannot
+ * guarantee that the floating-point calculation has given
+ * the correctly rounded result. For k requested digits and
+ * "uniformly" distributed input, the probability is
+ * something like 10^(k-15) that we must resort to the Long
+ * calculation.
+ */
+
+ static char *
+dtoa
+#ifdef KR_headers
+ (d, mode, ndigits, decpt, sign, rve)
+ U d; int mode, ndigits, *decpt, *sign; char **rve;
+#else
+ (U d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+#endif
+{
+ /* Arguments ndigits, decpt, sign are similar to those
+ of ecvt and fcvt; trailing zeros are suppressed from
+ the returned string. If not null, *rve is set to point
+ to the end of the return value. If d is +-Infinity or NaN,
+ then *decpt is set to 9999.
+
+ mode:
+ 0 ==> shortest string that yields d when read in
+ and rounded to nearest.
+ 1 ==> like 0, but with Steele & White stopping rule;
+ e.g. with IEEE P754 arithmetic , mode 0 gives
+ 1e23 whereas mode 1 gives 9.999999999999999e22.
+ 2 ==> max(1,ndigits) significant digits. This gives a
+ return value similar to that of ecvt, except
+ that trailing zeros are suppressed.
+ 3 ==> through ndigits past the decimal point. This
+ gives a return value similar to that from fcvt,
+ except that trailing zeros are suppressed, and
+ ndigits can be negative.
+ 4,5 ==> similar to 2 and 3, respectively, but (in
+ round-nearest mode) with the tests of mode 0 to
+ possibly return a shorter string that rounds to d.
+ With IEEE arithmetic and compilation with
+ -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
+ as modes 2 and 3 when FLT_ROUNDS != 1.
+ 6-9 ==> Debugging modes similar to mode - 4: don't try
+ fast floating-point estimate (if applicable).
+
+ Values of mode other than 0-9 are treated as mode 0.
+
+ Sufficient space is allocated to the return value
+ to hold the suppressed trailing zeros.
+ */
+
+ int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
+ j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+ spec_case, try_quick;
+ Long L;
+#ifndef Sudden_Underflow
+ int denorm;
+ ULong x;
+#endif
+ Bigint *b, *b1, *delta, *mlo, *mhi, *S;
+ U d2, eps;
+ double ds;
+ char *s, *s0;
+#ifdef Honor_FLT_ROUNDS
+ int rounding;
+#endif
+#ifdef SET_INEXACT
+ int inexact, oldinexact;
+#endif
+
+#ifdef __GNUC__
+ ilim = ilim1 = 0;
+ mlo = NULL;
+#endif
+
+#ifndef MULTIPLE_THREADS
+ if (dtoa_result) {
+ freedtoa(dtoa_result);
+ dtoa_result = 0;
+ }
+#endif
+
+ if (word0(d) & Sign_bit) {
+ /* set sign for everything, including 0's and NaNs */
+ *sign = 1;
+ word0(d) &= ~Sign_bit; /* clear sign bit */
+ }
+ else
+ *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+ if ((word0(d) & Exp_mask) == Exp_mask)
+#else
+ if (word0(d) == 0x8000)
+#endif
+ {
+ /* Infinity or NaN */
+ *decpt = 9999;
+#ifdef IEEE_Arith
+ if (!word1(d) && !(word0(d) & 0xfffff))
+ return nrv_alloc("Infinity", rve, 8);
+#endif
+ return nrv_alloc("NaN", rve, 3);
+ }
+#endif
+#ifdef IBM
+ dval(d) += 0; /* normalize */
+#endif
+ if (!dval(d)) {
+ *decpt = 1;
+ return nrv_alloc("0", rve, 1);
+ }
+
+#ifdef SET_INEXACT
+ try_quick = oldinexact = get_inexact();
+ inexact = 1;
+#endif
+#ifdef Honor_FLT_ROUNDS
+ if ((rounding = Flt_Rounds) >= 2) {
+ if (*sign)
+ rounding = rounding == 2 ? 0 : 2;
+ else
+ if (rounding != 2)
+ rounding = 0;
+ }
+#endif
+
+ b = d2b(d, &be, &bbits);
+#ifdef Sudden_Underflow
+ i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+ if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
+#endif
+ dval(d2) = dval(d);
+ word0(d2) &= Frac_mask1;
+ word0(d2) |= Exp_11;
+#ifdef IBM
+ if (j = 11 - hi0bits(word0(d2) & Frac_mask))
+ dval(d2) /= 1 << j;
+#endif
+
+ /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
+ * log10(x) = log(x) / log(10)
+ * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+ * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+ *
+ * This suggests computing an approximation k to log10(d) by
+ *
+ * k = (i - Bias)*0.301029995663981
+ * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+ *
+ * We want k to be too large rather than too small.
+ * The error in the first-order Taylor series approximation
+ * is in our favor, so we just round up the constant enough
+ * to compensate for any error in the multiplication of
+ * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+ * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+ * adding 1e-13 to the constant term more than suffices.
+ * Hence we adjust the constant term to 0.1760912590558.
+ * (We could get a more accurate k by invoking log10,
+ * but this is probably not worthwhile.)
+ */
+
+ i -= Bias;
+#ifdef IBM
+ i <<= 2;
+ i += j;
+#endif
+#ifndef Sudden_Underflow
+ denorm = 0;
+ }
+ else {
+ /* d is denormalized */
+
+ i = bbits + be + (Bias + (P-1) - 1);
+ x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
+ : word1(d) << (32 - i);
+ dval(d2) = x;
+ word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+ i -= (Bias + (P-1) - 1) + 1;
+ denorm = 1;
+ }
+#endif
+ ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+ k = (int)ds;
+ if (ds < 0. && ds != k)
+ k--; /* want k = floor(ds) */
+ k_check = 1;
+ if (k >= 0 && k <= Ten_pmax) {
+ if (dval(d) < tens[k])
+ k--;
+ k_check = 0;
+ }
+ j = bbits - i - 1;
+ if (j >= 0) {
+ b2 = 0;
+ s2 = j;
+ }
+ else {
+ b2 = -j;
+ s2 = 0;
+ }
+ if (k >= 0) {
+ b5 = 0;
+ s5 = k;
+ s2 += k;
+ }
+ else {
+ b2 -= k;
+ b5 = -k;
+ s5 = 0;
+ }
+ if (mode < 0 || mode > 9)
+ mode = 0;
+
+#ifndef SET_INEXACT
+#ifdef Check_FLT_ROUNDS
+ try_quick = Rounding == 1;
+#else
+ try_quick = 1;
+#endif
+#endif /*SET_INEXACT*/
+
+ if (mode > 5) {
+ mode -= 4;
+ try_quick = 0;
+ }
+ leftright = 1;
+ switch(mode) {
+ case 0:
+ case 1:
+ ilim = ilim1 = -1;
+ i = 18;
+ ndigits = 0;
+ break;
+ case 2:
+ leftright = 0;
+ /* no break */
+ case 4:
+ if (ndigits <= 0)
+ ndigits = 1;
+ ilim = ilim1 = i = ndigits;
+ break;
+ case 3:
+ leftright = 0;
+ /* no break */
+ case 5:
+ i = ndigits + k + 1;
+ ilim = i;
+ ilim1 = i - 1;
+ if (i <= 0)
+ i = 1;
+ }
+ s = s0 = rv_alloc(i);
+
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1 && rounding != 1)
+ leftright = 0;
+#endif
+
+ if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+ /* Try to get by with floating-point arithmetic. */
+
+ i = 0;
+ dval(d2) = dval(d);
+ k0 = k;
+ ilim0 = ilim;
+ ieps = 2; /* conservative */
+ if (k > 0) {
+ ds = tens[k&0xf];
+ j = k >> 4;
+ if (j & Bletch) {
+ /* prevent overflows */
+ j &= Bletch - 1;
+ dval(d) /= bigtens[n_bigtens-1];
+ ieps++;
+ }
+ for(; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ ds *= bigtens[i];
+ }
+ dval(d) /= ds;
+ }
+ else if ((j1 = -k)) {
+ dval(d) *= tens[j1 & 0xf];
+ for(j = j1 >> 4; j; j >>= 1, i++)
+ if (j & 1) {
+ ieps++;
+ dval(d) *= bigtens[i];
+ }
+ }
+ if (k_check && dval(d) < 1. && ilim > 0) {
+ if (ilim1 <= 0)
+ goto fast_failed;
+ ilim = ilim1;
+ k--;
+ dval(d) *= 10.;
+ ieps++;
+ }
+ dval(eps) = ieps*dval(d) + 7.;
+ word0(eps) -= (P-1)*Exp_msk1;
+ if (ilim == 0) {
+ S = mhi = 0;
+ dval(d) -= 5.;
+ if (dval(d) > dval(eps))
+ goto one_digit;
+ if (dval(d) < -dval(eps))
+ goto no_digits;
+ goto fast_failed;
+ }
+#ifndef No_leftright
+ if (leftright) {
+ /* Use Steele & White method of only
+ * generating digits needed.
+ */
+ dval(eps) = 0.5/tens[ilim-1] - dval(eps);
+ for(i = 0;;) {
+ L = (ULong) dval(d);
+ dval(d) -= L;
+ *s++ = '0' + (int)L;
+ if (dval(d) < dval(eps))
+ goto ret1;
+ if (1. - dval(d) < dval(eps))
+ goto bump_up;
+ if (++i >= ilim)
+ break;
+ dval(eps) *= 10.;
+ dval(d) *= 10.;
+ }
+ }
+ else {
+#endif
+ /* Generate ilim digits, then fix them up. */
+ dval(eps) *= tens[ilim-1];
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long)(dval(d));
+ if (!(dval(d) -= L))
+ ilim = i;
+ *s++ = '0' + (int)L;
+ if (i == ilim) {
+ if (dval(d) > 0.5 + dval(eps))
+ goto bump_up;
+ else if (dval(d) < 0.5 - dval(eps)) {
+ while(*--s == '0');
+ s++;
+ goto ret1;
+ }
+ break;
+ }
+ }
+#ifndef No_leftright
+ }
+#endif
+ fast_failed:
+ s = s0;
+ dval(d) = dval(d2);
+ k = k0;
+ ilim = ilim0;
+ }
+
+ /* Do we have a "small" integer? */
+
+ if (be >= 0 && k <= Int_max) {
+ /* Yes. */
+ ds = tens[k];
+ if (ndigits < 0 && ilim <= 0) {
+ S = mhi = 0;
+ if (ilim < 0 || dval(d) <= 5*ds)
+ goto no_digits;
+ goto one_digit;
+ }
+ for(i = 1;; i++, dval(d) *= 10.) {
+ L = (Long)(dval(d) / ds);
+ dval(d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+ /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+ if (dval(d) < 0) {
+ L--;
+ dval(d) += ds;
+ }
+#endif
+ *s++ = '0' + (int)L;
+ if (!dval(d)) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ break;
+ }
+ if (i == ilim) {
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(rounding) {
+ case 0: goto ret1;
+ case 2: goto bump_up;
+ }
+#endif
+ dval(d) += dval(d);
+ if (dval(d) > ds || (dval(d) == ds && L & 1)) {
+ bump_up:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s = '0';
+ break;
+ }
+ ++*s++;
+ }
+ break;
+ }
+ }
+ goto ret1;
+ }
+
+ m2 = b2;
+ m5 = b5;
+ mhi = mlo = 0;
+ if (leftright) {
+ i =
+#ifndef Sudden_Underflow
+ denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+ 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+ 1 + P - bbits;
+#endif
+ b2 += i;
+ s2 += i;
+ mhi = i2b(1);
+ }
+ if (m2 > 0 && s2 > 0) {
+ i = m2 < s2 ? m2 : s2;
+ b2 -= i;
+ m2 -= i;
+ s2 -= i;
+ }
+ if (b5 > 0) {
+ if (leftright) {
+ if (m5 > 0) {
+ mhi = pow5mult(mhi, m5);
+ b1 = mult(mhi, b);
+ Bfree(b);
+ b = b1;
+ }
+ if ((j = b5 - m5))
+ b = pow5mult(b, j);
+ }
+ else
+ b = pow5mult(b, b5);
+ }
+ S = i2b(1);
+ if (s5 > 0)
+ S = pow5mult(S, s5);
+
+ /* Check for special case that d is a normalized power of 2. */
+
+ spec_case = 0;
+ if ((mode < 2 || leftright)
+#ifdef Honor_FLT_ROUNDS
+ && rounding == 1
+#endif
+ ) {
+ if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & ~Exp_msk1)
+#endif
+ ) {
+ /* The special case */
+ b2 += Log2P;
+ s2 += Log2P;
+ spec_case = 1;
+ }
+ }
+
+ /* Arrange for convenient computation of quotients:
+ * shift left if necessary so divisor has 4 leading 0 bits.
+ *
+ * Perhaps we should just compute leading 28 bits of S once
+ * and for all and pass them and a shift to quorem, so it
+ * can do shifts and ors to compute the numerator for q.
+ */
+#ifdef Pack_32
+ if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f))
+ i = 32 - i;
+#else
+ if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
+ i = 16 - i;
+#endif
+ if (i > 4) {
+ i -= 4;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ else if (i < 4) {
+ i += 28;
+ b2 += i;
+ m2 += i;
+ s2 += i;
+ }
+ if (b2 > 0)
+ b = lshift(b, b2);
+ if (s2 > 0)
+ S = lshift(S, s2);
+ if (k_check) {
+ if (cmp(b,S) < 0) {
+ k--;
+ b = multadd(b, 10, 0); /* we botched the k estimate */
+ if (leftright)
+ mhi = multadd(mhi, 10, 0);
+ ilim = ilim1;
+ }
+ }
+ if (ilim <= 0 && (mode == 3 || mode == 5)) {
+ if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+ /* no digits, fcvt style */
+ no_digits:
+ /* MOZILLA CHANGE: Always return a non-empty string. */
+ *s++ = '0';
+ k = 0;
+ goto ret;
+ }
+ one_digit:
+ *s++ = '1';
+ k++;
+ goto ret;
+ }
+ if (leftright) {
+ if (m2 > 0)
+ mhi = lshift(mhi, m2);
+
+ /* Compute mlo -- check for special case
+ * that d is a normalized power of 2.
+ */
+
+ mlo = mhi;
+ if (spec_case) {
+ mhi = Balloc(mhi->k);
+ Bcopy(mhi, mlo);
+ mhi = lshift(mhi, Log2P);
+ }
+
+ for(i = 1;;i++) {
+ dig = quorem(b,S) + '0';
+ /* Do we yet have the shortest decimal string
+ * that will round to d?
+ */
+ j = cmp(b, mlo);
+ delta = diff(S, mhi);
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+#ifndef ROUND_BIASED
+ if (j1 == 0 && mode != 1 && !(word1(d) & 1)
+#ifdef Honor_FLT_ROUNDS
+ && rounding >= 1
+#endif
+ ) {
+ if (dig == '9')
+ goto round_9_up;
+ if (j > 0)
+ dig++;
+#ifdef SET_INEXACT
+ else if (!b->x[0] && b->wds <= 1)
+ inexact = 0;
+#endif
+ *s++ = dig;
+ goto ret;
+ }
+#endif
+ if (j < 0 || (j == 0 && mode != 1
+#ifndef ROUND_BIASED
+ && !(word1(d) & 1)
+#endif
+ )) {
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto accept_dig;
+ }
+#ifdef Honor_FLT_ROUNDS
+ if (mode > 1)
+ switch(rounding) {
+ case 0: goto accept_dig;
+ case 2: goto keep_dig;
+ }
+#endif /*Honor_FLT_ROUNDS*/
+ if (j1 > 0) {
+ b = lshift(b, 1);
+ j1 = cmp(b, S);
+ if ((j1 > 0 || (j1 == 0 && dig & 1))
+ && dig++ == '9')
+ goto round_9_up;
+ }
+ accept_dig:
+ *s++ = dig;
+ goto ret;
+ }
+ if (j1 > 0) {
+#ifdef Honor_FLT_ROUNDS
+ if (!rounding)
+ goto accept_dig;
+#endif
+ if (dig == '9') { /* possible if i == 1 */
+ round_9_up:
+ *s++ = '9';
+ goto roundoff;
+ }
+ *s++ = dig + 1;
+ goto ret;
+ }
+#ifdef Honor_FLT_ROUNDS
+ keep_dig:
+#endif
+ *s++ = dig;
+ if (i == ilim)
+ break;
+ b = multadd(b, 10, 0);
+ if (mlo == mhi)
+ mlo = mhi = multadd(mhi, 10, 0);
+ else {
+ mlo = multadd(mlo, 10, 0);
+ mhi = multadd(mhi, 10, 0);
+ }
+ }
+ }
+ else
+ for(i = 1;; i++) {
+ *s++ = dig = quorem(b,S) + '0';
+ if (!b->x[0] && b->wds <= 1) {
+#ifdef SET_INEXACT
+ inexact = 0;
+#endif
+ goto ret;
+ }
+ if (i >= ilim)
+ break;
+ b = multadd(b, 10, 0);
+ }
+
+ /* Round off last digit */
+
+#ifdef Honor_FLT_ROUNDS
+ switch(rounding) {
+ case 0: goto trimzeros;
+ case 2: goto roundoff;
+ }
+#endif
+ b = lshift(b, 1);
+ j = cmp(b, S);
+ if (j > 0 || (j == 0 && dig & 1)) {
+ roundoff:
+ while(*--s == '9')
+ if (s == s0) {
+ k++;
+ *s++ = '1';
+ goto ret;
+ }
+ ++*s++;
+ }
+ else {
+#ifdef Honor_FLT_ROUNDS
+ trimzeros:
+#endif
+ while(*--s == '0');
+ s++;
+ }
+ ret:
+ Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ ret1:
+#ifdef SET_INEXACT
+ if (inexact) {
+ if (!oldinexact) {
+ word0(d) = Exp_1 + (70 << Exp_shift);
+ word1(d) = 0;
+ dval(d) += 1.;
+ }
+ }
+ else if (!oldinexact)
+ clear_inexact();
+#endif
+ Bfree(b);
+ *s = 0;
+ *decpt = k + 1;
+ if (rve)
+ *rve = s;
+ return s0;
+ }
+#ifdef __cplusplus
+}
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref b/tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref
new file mode 100644
index 0000000..c902c88
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/Makefile.ref
@@ -0,0 +1,143 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Simmule Turner and Rich Salz.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+#
+# This software is not subject to any license of the American Telephone
+# and Telegraph Company or of the Regents of the University of California.
+#
+# Permission is granted to anyone to use this software for any purpose on
+# any computer system, and to alter it and redistribute it freely, subject
+# to the following restrictions:
+# 1. The authors are not responsible for the consequences of use of this
+# software, no matter how awful, even if they arise from flaws in it.
+# 2. The origin of this software must not be misrepresented, either by
+# explicit claim or by omission. Since few users ever read sources,
+# credits must appear in the documentation.
+# 3. Altered versions must be plainly marked as such, and must not be
+# misrepresented as being the original software. Since few users
+# ever read sources, credits must appear in the documentation.
+# 4. This notice may not be removed or altered.
+#
+
+#
+# Unix makefile for editline library.
+#
+
+## Set your options:
+## -DANSI_ARROWS ANSI arrows keys work like emacs.
+## -DHAVE_STDLIB Have <stdlib.h>.
+## -DHAVE_TCGETATTR Have tcgetattr(), tcsetattr().
+## -DHAVE_TERMIO Have "struct termio" and <termio.h>
+## (If neither of above two, we use <sgttyb.h> and BSD ioctl's)
+## -DHIDE Make static functions static (non debug).
+## -DHIST_SIZE=n History size.
+## -DNEED_STRDUP Don't have strdup().
+## -DUNIQUE_HISTORY Don't save command if same as last one.
+## -DUSE_DIRENT Use <dirent.h>, not <sys/dir.h>?
+## -DUSE_TERMCAP Use the termcap library for terminal size
+## see LDFLAGS, below, if you set this.
+## -DNEED_PERROR Don't have perror() (used in testit)
+
+## If you have -DUSE_TERMCAP, set this as appropriate:
+#LDFLAGS = -ltermlib
+#LDFLAGS = -ltermcap
+
+DEFS = -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX \
+ -DHAVE_STDLIB -DUNIQUE_HISTORY
+
+DEPTH = ..
+
+include $(DEPTH)/config.mk
+
+LOCAL_OBJDIR = $(OBJDIR)/editline
+
+#
+# Default IEEE libm
+#
+CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
+ -DJSFILE $(XCFLAGS) $(DEFS)
+
+INCFILES = editline.h
+.INIT: $(INCFILES)
+.KEEP_STATE:
+EDITLINE_CFILES = editline.c sysunix.c
+
+EDITLINE_OBJS = $(addprefix $(LOCAL_OBJDIR)/, $(EDITLINE_CFILES:.c=.o))
+
+LIBRARY = $(LOCAL_OBJDIR)/libedit.a
+
+all: $(LIBRARY)
+
+export:
+
+# make objects to depen on $(LOCAL_OBJDIR) only when it exists
+$(EDITLINE_OBJS) : $(filter-out $(wildcard $(LOCAL_OBJDIR)), $(LOCAL_OBJDIR))
+
+$(LOCAL_OBJDIR) :
+ mkdir -p $@
+
+$(LOCAL_OBJDIR)/%: %.c
+ $(CC) -o $@ $(CFLAGS) $*.c $(LDFLAGS)
+
+$(LOCAL_OBJDIR)/%.o: %.c
+ $(CC) -o $@ -c $(CFLAGS) $*.c
+
+$(LOCAL_OBJDIR)/%.o: %.s
+ $(AS) -o $@ $(ASFLAGS) $*.s
+
+$(LIBRARY): $(EDITLINE_OBJS)
+ $(AR) rv $@ $?
+ $(RANLIB) $@
+
+#libedit.a : $(EDITLINE_OBJS)
+# $(AR) cru $(LOCAL_OBJDIR)/libedit.a $(EDITLINE_OBJS)
+# $(RANLIB) $(LOCAL_OBJDIR)/libedit.a
+
+clean:
+ rm -rf $(EDITLINE_OBJS) $(EDITLINE_OBJS:.o=.d)
+
+clobber: clean
+ rm -rf $(LIBRARY) $(DEPENDENCIES)
+ if test -d $(LOCAL_OBJDIR); then rmdir $(LOCAL_OBJDIR); fi
+
+SUFFIXES: .i
+%.i: %.c
+ $(CC) -C -E $(CFLAGS) $< > $*.i
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/README b/tools/node_modules/expresso/deps/jscoverage/js/editline/README
new file mode 100644
index 0000000..53ec359
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/README
@@ -0,0 +1,83 @@
+The files in this directory provide simple line-editing and history
+support for the standalone javascript engine, through the 'editline'
+library.
+
+editline has only been enabled for those platforms on which it is
+known to build; to try it on a different platform, define JS_EDITLINE
+before building. Line editing (and js.c) is not a supported feature
+of the javascript library, so your mileage my vary.
+
+The editline API is a compatible subset of the FSF readline API; if
+you have readline installed and would like to link to that instead,
+define JS_READLINE. Note that the readline library is distributed
+under the GPL, so any resulting binaries are not legally
+distributable.
+
+The editline files used here have been modified to work with the js
+build system and to quiet some compiler warnings, and also to remove
+filename-completion support.
+
+If anyone knows of a more recent version of these files, or a site on
+which they are being maintained, please let me know!
+
+Mike McCabe, mccabe@netscape.com
+
+
+The original README file distributed with the editline library follows.
+
+
+
+This is a line-editing library. It can be linked into almost any
+program to provide command-line editing and recall.
+
+It is call-compatible with the FSF readline library, but it is a
+fraction of the size (and offers fewer features). It does not use
+standard I/O. It is distributed under a "C News-like" copyright.
+
+Configuration is done in the Makefile. Type "make testit" to get
+a small slow shell for testing.
+
+An earlier version was distributed with Byron's rc. Principal
+changes over that version include:
+ Faster.
+ Is eight-bit clean (thanks to brendan@cs.widener.edu)
+ Written in K&R C, but ANSI compliant (gcc all warnings)
+ Propagates EOF properly; rc trip test now passes
+ Doesn't need or use or provide memmove.
+ More robust
+ Calling sequence changed to be compatible with readline.
+ Test program, new manpage, better configuration
+ More system-independant; includes Unix and OS-9 support.
+
+This contains some changes since the posting to comp.sources.misc:
+ Bugfix for completion on absolute pathnames.
+ Better handling of M-n versus showing raw 8bit chars.
+ Better signal handling.
+ Now supports termios/termio/sgttyb ioctl's.
+ Add M-m command to toggle how 8bit data is displayed.
+
+There is one known bug:
+ History-searching redraws the line wrong if the text
+ retrieved is shorter then the prompt.
+
+Enjoy,
+ Rich $alz
+ <rsalz@osf.org>
+
+ Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+
+ This software is not subject to any license of the American Telephone
+ and Telegraph Company or of the Regents of the University of California.
+
+ Permission is granted to anyone to use this software for any purpose on
+ any computer system, and to alter it and redistribute it freely, subject
+ to the following restrictions:
+ 1. The authors are not responsible for the consequences of use of this
+ software, no matter how awful, even if they arise from flaws in it.
+ 2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission. Since few users ever read sources,
+ credits must appear in the documentation.
+ 3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software. Since few users
+ ever read sources, credits must appear in the documentation.
+ 4. This notice may not be removed or altered.
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3 b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3
new file mode 100644
index 0000000..21a72ca
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.3
@@ -0,0 +1,175 @@
+.TH EDITLINE 3
+.SH NAME
+editline \- command-line editing library with history
+.SH SYNOPSIS
+.nf
+.B "char *"
+.B "readline(prompt)"
+.B " char *prompt;"
+
+.B "void"
+.B "add_history(line)"
+.B " char *line;"
+.fi
+.SH DESCRIPTION
+.I Editline
+is a library that provides an line-editing interface with text recall.
+It is intended to be compatible with the
+.I readline
+library provided by the Free Software Foundation, but much smaller.
+The bulk of this manual page describes the user interface.
+.PP
+The
+.I readline
+routine returns a line of text with the trailing newline removed.
+The data is returned in a buffer allocated with
+.IR malloc (3),
+so the space should be released with
+.IR free (3)
+when the calling program is done with it.
+Before accepting input from the user, the specified
+.I prompt
+is displayed on the terminal.
+.PP
+The
+.I add_history
+routine makes a copy of the specified
+.I line
+and adds it to the internal history list.
+.SS "User Interface"
+A program that uses this library provides a simple emacs-like editing
+interface to its users.
+A line may be edited before it is sent to the calling program by typing either
+control characters or escape sequences.
+A control character, shown as a caret followed by a letter, is typed by
+holding down the ``control'' key while the letter is typed.
+For example, ``^A'' is a control-A.
+An escape sequence is entered by typing the ``escape'' key followed by one or
+more characters.
+The escape key is abbreviated as ``ESC.''
+Note that unlike control keys, case matters in escape sequences; ``ESC\ F''
+is not the same as ``ESC\ f''.
+.PP
+An editing command may be typed anywhere on the line, not just at the
+beginning.
+In addition, a return may also be typed anywhere on the line, not just at
+the end.
+.PP
+Most editing commands may be given a repeat count,
+.IR n ,
+where
+.I n
+is a number.
+To enter a repeat count, type the escape key, the number, and then
+the command to execute.
+For example, ``ESC\ 4\ ^f'' moves forward four characters.
+If a command may be given a repeat count then the text ``[n]'' is given at the
+end of its description.
+.PP
+The following control characters are accepted:
+.RS
+.nf
+.ta \w'ESC DEL 'u
+^A Move to the beginning of the line
+^B Move left (backwards) [n]
+^D Delete character [n]
+^E Move to end of line
+^F Move right (forwards) [n]
+^G Ring the bell
+^H Delete character before cursor (backspace key) [n]
+^I Complete filename (tab key); see below
+^J Done with line (return key)
+^K Kill to end of line (or column [n])
+^L Redisplay line
+^M Done with line (alternate return key)
+^N Get next line from history [n]
+^P Get previous line from history [n]
+^R Search backward (forward if [n]) through history for text;
+\& must start line if text begins with an uparrow
+^T Transpose characters
+^V Insert next character, even if it is an edit command
+^W Wipe to the mark
+^X^X Exchange current location and mark
+^Y Yank back last killed text
+^[ Start an escape sequence (escape key)
+^]c Move forward to next character ``c''
+^? Delete character before cursor (delete key) [n]
+.fi
+.RE
+.PP
+The following escape sequences are provided.
+.RS
+.nf
+.ta \w'ESC DEL 'u
+ESC\ ^H Delete previous word (backspace key) [n]
+ESC\ DEL Delete previous word (delete key) [n]
+ESC\ SP Set the mark (space key); see ^X^X and ^Y above
+ESC\ \. Get the last (or [n]'th) word from previous line
+ESC\ \? Show possible completions; see below
+ESC\ < Move to start of history
+ESC\ > Move to end of history
+ESC\ b Move backward a word [n]
+ESC\ d Delete word under cursor [n]
+ESC\ f Move forward a word [n]
+ESC\ l Make word lowercase [n]
+ESC\ m Toggle if 8bit chars display normally or with ``M\-'' prefix
+ESC\ u Make word uppercase [n]
+ESC\ y Yank back last killed text
+ESC\ v Show library version
+ESC\ w Make area up to mark yankable
+ESC\ nn Set repeat count to the number nn
+ESC\ C Read from environment variable ``_C_'', where C is
+\& an uppercase letter
+.fi
+.RE
+.PP
+The
+.I editline
+library has a small macro facility.
+If you type the escape key followed by an uppercase letter,
+.IR C ,
+then the contents of the environment variable
+.I _C_
+are read in as if you had typed them at the keyboard.
+For example, if the variable
+.I _L_
+contains the following:
+.RS
+^A^Kecho '^V^[[H^V^[[2J'^M
+.RE
+Then typing ``ESC L'' will move to the beginning of the line, kill the
+entire line, enter the echo command needed to clear the terminal (if your
+terminal is like a VT-100), and send the line back to the shell.
+.PP
+The
+.I editline
+library also does filename completion.
+Suppose the root directory has the following files in it:
+.RS
+.nf
+.ta \w'core 'u
+bin vmunix
+core vmunix.old
+.fi
+.RE
+If you type ``rm\ /v'' and then the tab key.
+.I Editline
+will then finish off as much of the name as possible by adding ``munix''.
+Because the name is not unique, it will then beep.
+If you type the escape key and a question mark, it will display the
+two choices.
+If you then type a period and a tab, the library will finish off the filename
+for you:
+.RS
+.nf
+.RI "rm /v[TAB]" munix .TAB old
+.fi
+.RE
+The tab key is shown by ``[TAB]'' and the automatically-entered text
+is shown in italics.
+.SH "BUGS AND LIMITATIONS"
+Cannot handle lines more than 80 columns.
+.SH AUTHORS
+Simmule R. Turner <uunet.uu.net!capitol!sysgo!simmy>
+and Rich $alz <rsalz@osf.org>.
+Original manual page by DaviD W. Sanderson <dws@ssec.wisc.edu>.
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c
new file mode 100644
index 0000000..8ca93b3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.c
@@ -0,0 +1,1368 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+
+/*
+** Main editing routines for editline library.
+*/
+#include "editline.h"
+#include <signal.h>
+#include <ctype.h>
+#include <unistd.h>
+
+/*
+** Manifest constants.
+*/
+#define SCREEN_WIDTH 80
+#define SCREEN_ROWS 24
+#define NO_ARG (-1)
+#define DEL 127
+#define CTL(x) ((x) & 0x1F)
+#define ISCTL(x) ((x) && (x) < ' ')
+#define UNCTL(x) ((x) + 64)
+#define META(x) ((x) | 0x80)
+#define ISMETA(x) ((x) & 0x80)
+#define UNMETA(x) ((x) & 0x7F)
+#if !defined(HIST_SIZE)
+#define HIST_SIZE 20
+#endif /* !defined(HIST_SIZE) */
+
+/*
+** Command status codes.
+*/
+typedef enum _STATUS {
+ CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
+} STATUS;
+
+/*
+** The type of case-changing to perform.
+*/
+typedef enum _CASE {
+ TOupper, TOlower
+} CASE;
+
+/*
+** Key to command mapping.
+*/
+typedef struct _KEYMAP {
+ CHAR Key;
+ STATUS (*Function)();
+} KEYMAP;
+
+/*
+** Command history structure.
+*/
+typedef struct _HISTORY {
+ int Size;
+ int Pos;
+ CHAR *Lines[HIST_SIZE];
+} HISTORY;
+
+/*
+** Globals.
+*/
+int rl_eof;
+int rl_erase;
+int rl_intr;
+int rl_kill;
+int rl_quit;
+
+STATIC CHAR NIL[] = "";
+STATIC CONST CHAR *Input = NIL;
+STATIC CHAR *Line;
+STATIC CONST char *Prompt;
+STATIC CHAR *Yanked;
+STATIC char *Screen;
+STATIC char NEWLINE[]= CRLF;
+STATIC HISTORY H;
+STATIC int Repeat;
+STATIC int End;
+STATIC int Mark;
+STATIC int OldPoint;
+STATIC int Point;
+STATIC int PushBack;
+STATIC int Pushed;
+STATIC int Signal;
+FORWARD KEYMAP Map[32];
+FORWARD KEYMAP MetaMap[16];
+STATIC SIZE_T Length;
+STATIC SIZE_T ScreenCount;
+STATIC SIZE_T ScreenSize;
+STATIC char *backspace;
+STATIC int TTYwidth;
+STATIC int TTYrows;
+
+/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
+int rl_meta_chars = 0;
+
+/*
+** Declarations.
+*/
+STATIC CHAR *editinput();
+#if defined(USE_TERMCAP)
+#include <stdlib.h>
+#include <curses.h>
+#include <term.h>
+#endif /* defined(USE_TERMCAP) */
+
+/*
+** TTY input/output functions.
+*/
+
+STATIC void
+TTYflush()
+{
+ if (ScreenCount) {
+ (void)write(1, Screen, ScreenCount);
+ ScreenCount = 0;
+ }
+}
+
+STATIC void
+TTYput(c)
+ CHAR c;
+{
+ Screen[ScreenCount] = c;
+ if (++ScreenCount >= ScreenSize - 1) {
+ ScreenSize += SCREEN_INC;
+ RENEW(Screen, char, ScreenSize);
+ }
+}
+
+STATIC void
+TTYputs(p)
+ CHAR *p;
+{
+ while (*p)
+ TTYput(*p++);
+}
+
+STATIC void
+TTYshow(c)
+ CHAR c;
+{
+ if (c == DEL) {
+ TTYput('^');
+ TTYput('?');
+ }
+ else if (ISCTL(c)) {
+ TTYput('^');
+ TTYput(UNCTL(c));
+ }
+ else if (rl_meta_chars && ISMETA(c)) {
+ TTYput('M');
+ TTYput('-');
+ TTYput(UNMETA(c));
+ }
+ else
+ TTYput(c);
+}
+
+STATIC void
+TTYstring(p)
+ CHAR *p;
+{
+ while (*p)
+ TTYshow(*p++);
+}
+
+STATIC unsigned int
+TTYget()
+{
+ CHAR c;
+
+ TTYflush();
+ if (Pushed) {
+ Pushed = 0;
+ return PushBack;
+ }
+ if (*Input)
+ return *Input++;
+ return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
+}
+
+#define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
+
+STATIC void
+TTYbackn(n)
+ int n;
+{
+ while (--n >= 0)
+ TTYback();
+}
+
+STATIC void
+TTYinfo()
+{
+ static int init;
+#if defined(USE_TERMCAP)
+ char *term;
+ char buff[2048];
+ char *bp, *p;
+#endif /* defined(USE_TERMCAP) */
+#if defined(TIOCGWINSZ)
+ struct winsize W;
+#endif /* defined(TIOCGWINSZ) */
+
+ if (init) {
+#if defined(TIOCGWINSZ)
+ /* Perhaps we got resized. */
+ if (ioctl(0, TIOCGWINSZ, &W) >= 0
+ && W.ws_col > 0 && W.ws_row > 0) {
+ TTYwidth = (int)W.ws_col;
+ TTYrows = (int)W.ws_row;
+ }
+#endif /* defined(TIOCGWINSZ) */
+ return;
+ }
+ init++;
+
+ TTYwidth = TTYrows = 0;
+#if defined(USE_TERMCAP)
+ bp = &buff[0];
+ if ((term = getenv("TERM")) == NULL)
+ term = "dumb";
+ if (tgetent(buff, term) < 0) {
+ TTYwidth = SCREEN_WIDTH;
+ TTYrows = SCREEN_ROWS;
+ return;
+ }
+ p = tgetstr("le", &bp);
+ backspace = p ? strdup(p) : NULL;
+ TTYwidth = tgetnum("co");
+ TTYrows = tgetnum("li");
+#endif /* defined(USE_TERMCAP) */
+
+#if defined(TIOCGWINSZ)
+ if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
+ TTYwidth = (int)W.ws_col;
+ TTYrows = (int)W.ws_row;
+ }
+#endif /* defined(TIOCGWINSZ) */
+
+ if (TTYwidth <= 0 || TTYrows <= 0) {
+ TTYwidth = SCREEN_WIDTH;
+ TTYrows = SCREEN_ROWS;
+ }
+}
+
+
+STATIC void
+reposition()
+{
+ int i;
+ CHAR *p;
+
+ TTYput('\r');
+ TTYputs((CONST CHAR *)Prompt);
+ for (i = Point, p = Line; --i >= 0; p++)
+ TTYshow(*p);
+}
+
+STATIC void
+left(Change)
+ STATUS Change;
+{
+ TTYback();
+ if (Point) {
+ if (ISCTL(Line[Point - 1]))
+ TTYback();
+ else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
+ TTYback();
+ TTYback();
+ }
+ }
+ if (Change == CSmove)
+ Point--;
+}
+
+STATIC void
+right(Change)
+ STATUS Change;
+{
+ TTYshow(Line[Point]);
+ if (Change == CSmove)
+ Point++;
+}
+
+STATIC STATUS
+ring_bell()
+{
+ TTYput('\07');
+ TTYflush();
+ return CSstay;
+}
+
+STATIC STATUS
+do_macro(c)
+ unsigned int c;
+{
+ CHAR name[4];
+
+ name[0] = '_';
+ name[1] = c;
+ name[2] = '_';
+ name[3] = '\0';
+
+ if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
+ Input = NIL;
+ return ring_bell();
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+do_forward(move)
+ STATUS move;
+{
+ int i;
+ CHAR *p;
+
+ i = 0;
+ do {
+ p = &Line[Point];
+ for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
+ if (move == CSmove)
+ right(CSstay);
+
+ for (; Point < End && isalnum(*p); Point++, p++)
+ if (move == CSmove)
+ right(CSstay);
+
+ if (Point == End)
+ break;
+ } while (++i < Repeat);
+
+ return CSstay;
+}
+
+STATIC STATUS
+do_case(type)
+ CASE type;
+{
+ int i;
+ int end;
+ int count;
+ CHAR *p;
+
+ (void)do_forward(CSstay);
+ if (OldPoint != Point) {
+ if ((count = Point - OldPoint) < 0)
+ count = -count;
+ Point = OldPoint;
+ if ((end = Point + count) > End)
+ end = End;
+ for (i = Point, p = &Line[i]; i < end; i++, p++) {
+ if (type == TOupper) {
+ if (islower(*p))
+ *p = toupper(*p);
+ }
+ else if (isupper(*p))
+ *p = tolower(*p);
+ right(CSmove);
+ }
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+case_down_word()
+{
+ return do_case(TOlower);
+}
+
+STATIC STATUS
+case_up_word()
+{
+ return do_case(TOupper);
+}
+
+STATIC void
+ceol()
+{
+ int extras;
+ int i;
+ CHAR *p;
+
+ for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
+ TTYput(' ');
+ if (ISCTL(*p)) {
+ TTYput(' ');
+ extras++;
+ }
+ else if (rl_meta_chars && ISMETA(*p)) {
+ TTYput(' ');
+ TTYput(' ');
+ extras += 2;
+ }
+ }
+
+ for (i += extras; i > Point; i--)
+ TTYback();
+}
+
+STATIC void
+clear_line()
+{
+ Point = -strlen(Prompt);
+ TTYput('\r');
+ ceol();
+ Point = 0;
+ End = 0;
+ Line[0] = '\0';
+}
+
+STATIC STATUS
+insert_string(p)
+ CHAR *p;
+{
+ SIZE_T len;
+ int i;
+ CHAR *new;
+ CHAR *q;
+
+ len = strlen((char *)p);
+ if (End + len >= Length) {
+ if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
+ return CSstay;
+ if (Length) {
+ COPYFROMTO(new, Line, Length);
+ DISPOSE(Line);
+ }
+ Line = new;
+ Length += len + MEM_INC;
+ }
+
+ for (q = &Line[Point], i = End - Point; --i >= 0; )
+ q[len + i] = q[i];
+ COPYFROMTO(&Line[Point], p, len);
+ End += len;
+ Line[End] = '\0';
+ TTYstring(&Line[Point]);
+ Point += len;
+
+ return Point == End ? CSstay : CSmove;
+}
+
+STATIC STATUS
+redisplay()
+{
+ TTYputs((CONST CHAR *)NEWLINE);
+ TTYputs((CONST CHAR *)Prompt);
+ TTYstring(Line);
+ return CSmove;
+}
+
+STATIC STATUS
+toggle_meta_mode()
+{
+ rl_meta_chars = ! rl_meta_chars;
+ return redisplay();
+}
+
+
+STATIC CHAR *
+next_hist()
+{
+ return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
+}
+
+STATIC CHAR *
+prev_hist()
+{
+ return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
+}
+
+STATIC STATUS
+do_insert_hist(p)
+ CHAR *p;
+{
+ if (p == NULL)
+ return ring_bell();
+ Point = 0;
+ reposition();
+ ceol();
+ End = 0;
+ return insert_string(p);
+}
+
+STATIC STATUS
+do_hist(move)
+ CHAR *(*move)();
+{
+ CHAR *p;
+ int i;
+
+ i = 0;
+ do {
+ if ((p = (*move)()) == NULL)
+ return ring_bell();
+ } while (++i < Repeat);
+ return do_insert_hist(p);
+}
+
+STATIC STATUS
+h_next()
+{
+ return do_hist(next_hist);
+}
+
+STATIC STATUS
+h_prev()
+{
+ return do_hist(prev_hist);
+}
+
+STATIC STATUS
+h_first()
+{
+ return do_insert_hist(H.Lines[H.Pos = 0]);
+}
+
+STATIC STATUS
+h_last()
+{
+ return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
+}
+
+/*
+** Return zero if pat appears as a substring in text.
+*/
+STATIC int
+substrcmp(text, pat, len)
+ char *text;
+ char *pat;
+ int len;
+{
+ char c;
+
+ if ((c = *pat) == '\0')
+ return *text == '\0';
+ for ( ; *text; text++)
+ if (*text == c && strncmp(text, pat, len) == 0)
+ return 0;
+ return 1;
+}
+
+STATIC CHAR *
+search_hist(search, move)
+ CHAR *search;
+ CHAR *(*move)();
+{
+ static CHAR *old_search;
+ int len;
+ int pos;
+ int (*match)();
+ char *pat;
+
+ /* Save or get remembered search pattern. */
+ if (search && *search) {
+ if (old_search)
+ DISPOSE(old_search);
+ old_search = (CHAR *)strdup((char *)search);
+ }
+ else {
+ if (old_search == NULL || *old_search == '\0')
+ return NULL;
+ search = old_search;
+ }
+
+ /* Set up pattern-finder. */
+ if (*search == '^') {
+ match = strncmp;
+ pat = (char *)(search + 1);
+ }
+ else {
+ match = substrcmp;
+ pat = (char *)search;
+ }
+ len = strlen(pat);
+
+ for (pos = H.Pos; (*move)() != NULL; )
+ if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
+ return H.Lines[H.Pos];
+ H.Pos = pos;
+ return NULL;
+}
+
+STATIC STATUS
+h_search()
+{
+ static int Searching;
+ CONST char *old_prompt;
+ CHAR *(*move)();
+ CHAR *p;
+
+ if (Searching)
+ return ring_bell();
+ Searching = 1;
+
+ clear_line();
+ old_prompt = Prompt;
+ Prompt = "Search: ";
+ TTYputs((CONST CHAR *)Prompt);
+ move = Repeat == NO_ARG ? prev_hist : next_hist;
+ p = editinput();
+ Prompt = old_prompt;
+ Searching = 0;
+ TTYputs((CONST CHAR *)Prompt);
+ if (p == NULL && Signal > 0) {
+ Signal = 0;
+ clear_line();
+ return redisplay();
+ }
+ p = search_hist(p, move);
+ clear_line();
+ if (p == NULL) {
+ (void)ring_bell();
+ return redisplay();
+ }
+ return do_insert_hist(p);
+}
+
+STATIC STATUS
+fd_char()
+{
+ int i;
+
+ i = 0;
+ do {
+ if (Point >= End)
+ break;
+ right(CSmove);
+ } while (++i < Repeat);
+ return CSstay;
+}
+
+STATIC void
+save_yank(begin, i)
+ int begin;
+ int i;
+{
+ if (Yanked) {
+ DISPOSE(Yanked);
+ Yanked = NULL;
+ }
+
+ if (i < 1)
+ return;
+
+ if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
+ COPYFROMTO(Yanked, &Line[begin], i);
+ Yanked[i] = '\0';
+ }
+}
+
+STATIC STATUS
+delete_string(count)
+ int count;
+{
+ int i;
+ CHAR *p;
+
+ if (count <= 0 || End == Point)
+ return ring_bell();
+
+ if (count == 1 && Point == End - 1) {
+ /* Optimize common case of delete at end of line. */
+ End--;
+ p = &Line[Point];
+ i = 1;
+ TTYput(' ');
+ if (ISCTL(*p)) {
+ i = 2;
+ TTYput(' ');
+ }
+ else if (rl_meta_chars && ISMETA(*p)) {
+ i = 3;
+ TTYput(' ');
+ TTYput(' ');
+ }
+ TTYbackn(i);
+ *p = '\0';
+ return CSmove;
+ }
+ if (Point + count > End && (count = End - Point) <= 0)
+ return CSstay;
+
+ if (count > 1)
+ save_yank(Point, count);
+
+ for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
+ p[0] = p[count];
+ ceol();
+ End -= count;
+ TTYstring(&Line[Point]);
+ return CSmove;
+}
+
+STATIC STATUS
+bk_char()
+{
+ int i;
+
+ i = 0;
+ do {
+ if (Point == 0)
+ break;
+ left(CSmove);
+ } while (++i < Repeat);
+
+ return CSstay;
+}
+
+STATIC STATUS
+bk_del_char()
+{
+ int i;
+
+ i = 0;
+ do {
+ if (Point == 0)
+ break;
+ left(CSmove);
+ } while (++i < Repeat);
+
+ return delete_string(i);
+}
+
+STATIC STATUS
+kill_line()
+{
+ int i;
+
+ if (Repeat != NO_ARG) {
+ if (Repeat < Point) {
+ i = Point;
+ Point = Repeat;
+ reposition();
+ (void)delete_string(i - Point);
+ }
+ else if (Repeat > Point) {
+ right(CSmove);
+ (void)delete_string(Repeat - Point - 1);
+ }
+ return CSmove;
+ }
+
+ save_yank(Point, End - Point);
+ Line[Point] = '\0';
+ ceol();
+ End = Point;
+ return CSstay;
+}
+
+STATIC STATUS
+insert_char(c)
+ int c;
+{
+ STATUS s;
+ CHAR buff[2];
+ CHAR *p;
+ CHAR *q;
+ int i;
+
+ if (Repeat == NO_ARG || Repeat < 2) {
+ buff[0] = c;
+ buff[1] = '\0';
+ return insert_string(buff);
+ }
+
+ if ((p = NEW(CHAR, Repeat + 1)) == NULL)
+ return CSstay;
+ for (i = Repeat, q = p; --i >= 0; )
+ *q++ = c;
+ *q = '\0';
+ Repeat = 0;
+ s = insert_string(p);
+ DISPOSE(p);
+ return s;
+}
+
+STATIC STATUS
+meta()
+{
+ unsigned int c;
+ KEYMAP *kp;
+
+ if ((c = TTYget()) == EOF)
+ return CSeof;
+#if defined(ANSI_ARROWS)
+ /* Also include VT-100 arrows. */
+ if (c == '[' || c == 'O')
+ switch (c = TTYget()) {
+ default: return ring_bell();
+ case EOF: return CSeof;
+ case 'A': return h_prev();
+ case 'B': return h_next();
+ case 'C': return fd_char();
+ case 'D': return bk_char();
+ }
+#endif /* defined(ANSI_ARROWS) */
+
+ if (isdigit(c)) {
+ for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
+ Repeat = Repeat * 10 + c - '0';
+ Pushed = 1;
+ PushBack = c;
+ return CSstay;
+ }
+
+ if (isupper(c))
+ return do_macro(c);
+ for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
+ if (kp->Key == c)
+ return (*kp->Function)();
+
+ return ring_bell();
+}
+
+STATIC STATUS
+emacs(c)
+ unsigned int c;
+{
+ STATUS s;
+ KEYMAP *kp;
+
+ if (rl_meta_chars && ISMETA(c)) {
+ Pushed = 1;
+ PushBack = UNMETA(c);
+ return meta();
+ }
+ for (kp = Map; kp->Function; kp++)
+ if (kp->Key == c)
+ break;
+ s = kp->Function ? (*kp->Function)() : insert_char((int)c);
+ if (!Pushed)
+ /* No pushback means no repeat count; hacky, but true. */
+ Repeat = NO_ARG;
+ return s;
+}
+
+STATIC STATUS
+TTYspecial(c)
+ unsigned int c;
+{
+ if (ISMETA(c))
+ return CSdispatch;
+
+ if (c == rl_erase || c == DEL)
+ return bk_del_char();
+ if (c == rl_kill) {
+ if (Point != 0) {
+ Point = 0;
+ reposition();
+ }
+ Repeat = NO_ARG;
+ return kill_line();
+ }
+ if (c == rl_eof && Point == 0 && End == 0)
+ return CSeof;
+ if (c == rl_intr) {
+ Signal = SIGINT;
+ return CSsignal;
+ }
+ if (c == rl_quit) {
+ Signal = SIGQUIT;
+ return CSeof;
+ }
+
+ return CSdispatch;
+}
+
+STATIC CHAR *
+editinput()
+{
+ unsigned int c;
+
+ Repeat = NO_ARG;
+ OldPoint = Point = Mark = End = 0;
+ Line[0] = '\0';
+
+ Signal = -1;
+ while ((c = TTYget()) != EOF)
+ switch (TTYspecial(c)) {
+ case CSdone:
+ return Line;
+ case CSeof:
+ return NULL;
+ case CSsignal:
+ return (CHAR *)"";
+ case CSmove:
+ reposition();
+ break;
+ case CSdispatch:
+ switch (emacs(c)) {
+ case CSdone:
+ return Line;
+ case CSeof:
+ return NULL;
+ case CSsignal:
+ return (CHAR *)"";
+ case CSmove:
+ reposition();
+ break;
+ case CSdispatch:
+ case CSstay:
+ break;
+ }
+ break;
+ case CSstay:
+ break;
+ }
+ return NULL;
+}
+
+STATIC void
+hist_add(p)
+ CHAR *p;
+{
+ int i;
+
+ if ((p = (CHAR *)strdup((char *)p)) == NULL)
+ return;
+ if (H.Size < HIST_SIZE)
+ H.Lines[H.Size++] = p;
+ else {
+ DISPOSE(H.Lines[0]);
+ for (i = 0; i < HIST_SIZE - 1; i++)
+ H.Lines[i] = H.Lines[i + 1];
+ H.Lines[i] = p;
+ }
+ H.Pos = H.Size - 1;
+}
+
+/*
+** For compatibility with FSF readline.
+*/
+/* ARGSUSED0 */
+void
+rl_reset_terminal(p)
+ char *p;
+{
+}
+
+void
+rl_initialize()
+{
+}
+
+char *
+readline(prompt)
+ CONST char *prompt;
+{
+ CHAR *line;
+ int s;
+
+ if (Line == NULL) {
+ Length = MEM_INC;
+ if ((Line = NEW(CHAR, Length)) == NULL)
+ return NULL;
+ }
+
+ TTYinfo();
+ rl_ttyset(0);
+ hist_add(NIL);
+ ScreenSize = SCREEN_INC;
+ Screen = NEW(char, ScreenSize);
+ Prompt = prompt ? prompt : (char *)NIL;
+ TTYputs((CONST CHAR *)Prompt);
+ if ((line = editinput()) != NULL) {
+ line = (CHAR *)strdup((char *)line);
+ TTYputs((CHAR *)NEWLINE);
+ TTYflush();
+ }
+ rl_ttyset(1);
+ DISPOSE(Screen);
+ DISPOSE(H.Lines[--H.Size]);
+ if (Signal > 0) {
+ s = Signal;
+ Signal = 0;
+ (void)kill(getpid(), s);
+ }
+ return (char *)line;
+}
+
+void
+add_history(p)
+ char *p;
+{
+ if (p == NULL || *p == '\0')
+ return;
+
+#if defined(UNIQUE_HISTORY)
+ if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0)
+ return;
+#endif /* defined(UNIQUE_HISTORY) */
+ hist_add((CHAR *)p);
+}
+
+
+STATIC STATUS
+beg_line()
+{
+ if (Point) {
+ Point = 0;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+del_char()
+{
+ return delete_string(Repeat == NO_ARG ? 1 : Repeat);
+}
+
+STATIC STATUS
+end_line()
+{
+ if (Point != End) {
+ Point = End;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+accept_line()
+{
+ Line[End] = '\0';
+ return CSdone;
+}
+
+STATIC STATUS
+transpose()
+{
+ CHAR c;
+
+ if (Point) {
+ if (Point == End)
+ left(CSmove);
+ c = Line[Point - 1];
+ left(CSstay);
+ Line[Point - 1] = Line[Point];
+ TTYshow(Line[Point - 1]);
+ Line[Point++] = c;
+ TTYshow(c);
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+quote()
+{
+ unsigned int c;
+
+ return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
+}
+
+STATIC STATUS
+wipe()
+{
+ int i;
+
+ if (Mark > End)
+ return ring_bell();
+
+ if (Point > Mark) {
+ i = Point;
+ Point = Mark;
+ Mark = i;
+ reposition();
+ }
+
+ return delete_string(Mark - Point);
+}
+
+STATIC STATUS
+mk_set()
+{
+ Mark = Point;
+ return CSstay;
+}
+
+STATIC STATUS
+exchange()
+{
+ unsigned int c;
+
+ if ((c = TTYget()) != CTL('X'))
+ return c == EOF ? CSeof : ring_bell();
+
+ if ((c = Mark) <= End) {
+ Mark = Point;
+ Point = c;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+yank()
+{
+ if (Yanked && *Yanked)
+ return insert_string(Yanked);
+ return CSstay;
+}
+
+STATIC STATUS
+copy_region()
+{
+ if (Mark > End)
+ return ring_bell();
+
+ if (Point > Mark)
+ save_yank(Mark, Point - Mark);
+ else
+ save_yank(Point, Mark - Point);
+
+ return CSstay;
+}
+
+STATIC STATUS
+move_to_char()
+{
+ unsigned int c;
+ int i;
+ CHAR *p;
+
+ if ((c = TTYget()) == EOF)
+ return CSeof;
+ for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
+ if (*p == c) {
+ Point = i;
+ return CSmove;
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+fd_word()
+{
+ return do_forward(CSmove);
+}
+
+STATIC STATUS
+fd_kill_word()
+{
+ int i;
+
+ (void)do_forward(CSstay);
+ if (OldPoint != Point) {
+ i = Point - OldPoint;
+ Point = OldPoint;
+ return delete_string(i);
+ }
+ return CSstay;
+}
+
+STATIC STATUS
+bk_word()
+{
+ int i;
+ CHAR *p;
+
+ i = 0;
+ do {
+ for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
+ left(CSmove);
+
+ for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
+ left(CSmove);
+
+ if (Point == 0)
+ break;
+ } while (++i < Repeat);
+
+ return CSstay;
+}
+
+STATIC STATUS
+bk_kill_word()
+{
+ (void)bk_word();
+ if (OldPoint != Point)
+ return delete_string(OldPoint - Point);
+ return CSstay;
+}
+
+STATIC int
+argify(line, avp)
+ CHAR *line;
+ CHAR ***avp;
+{
+ CHAR *c;
+ CHAR **p;
+ CHAR **new;
+ int ac;
+ int i;
+
+ i = MEM_INC;
+ if ((*avp = p = NEW(CHAR*, i))== NULL)
+ return 0;
+
+ for (c = line; isspace(*c); c++)
+ continue;
+ if (*c == '\n' || *c == '\0')
+ return 0;
+
+ for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
+ if (isspace(*c)) {
+ *c++ = '\0';
+ if (*c && *c != '\n') {
+ if (ac + 1 == i) {
+ new = NEW(CHAR*, i + MEM_INC);
+ if (new == NULL) {
+ p[ac] = NULL;
+ return ac;
+ }
+ COPYFROMTO(new, p, i * sizeof (char **));
+ i += MEM_INC;
+ DISPOSE(p);
+ *avp = p = new;
+ }
+ p[ac++] = c;
+ }
+ }
+ else
+ c++;
+ }
+ *c = '\0';
+ p[ac] = NULL;
+ return ac;
+}
+
+STATIC STATUS
+last_argument()
+{
+ CHAR **av;
+ CHAR *p;
+ STATUS s;
+ int ac;
+
+ if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
+ return ring_bell();
+
+ if ((p = (CHAR *)strdup((char *)p)) == NULL)
+ return CSstay;
+ ac = argify(p, &av);
+
+ if (Repeat != NO_ARG)
+ s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
+ else
+ s = ac ? insert_string(av[ac - 1]) : CSstay;
+
+ if (ac)
+ DISPOSE(av);
+ DISPOSE(p);
+ return s;
+}
+
+STATIC KEYMAP Map[32] = {
+ { CTL('@'), ring_bell },
+ { CTL('A'), beg_line },
+ { CTL('B'), bk_char },
+ { CTL('D'), del_char },
+ { CTL('E'), end_line },
+ { CTL('F'), fd_char },
+ { CTL('G'), ring_bell },
+ { CTL('H'), bk_del_char },
+ { CTL('J'), accept_line },
+ { CTL('K'), kill_line },
+ { CTL('L'), redisplay },
+ { CTL('M'), accept_line },
+ { CTL('N'), h_next },
+ { CTL('O'), ring_bell },
+ { CTL('P'), h_prev },
+ { CTL('Q'), ring_bell },
+ { CTL('R'), h_search },
+ { CTL('S'), ring_bell },
+ { CTL('T'), transpose },
+ { CTL('U'), ring_bell },
+ { CTL('V'), quote },
+ { CTL('W'), wipe },
+ { CTL('X'), exchange },
+ { CTL('Y'), yank },
+ { CTL('Z'), ring_bell },
+ { CTL('['), meta },
+ { CTL(']'), move_to_char },
+ { CTL('^'), ring_bell },
+ { CTL('_'), ring_bell },
+ { 0, NULL }
+};
+
+STATIC KEYMAP MetaMap[16]= {
+ { CTL('H'), bk_kill_word },
+ { DEL, bk_kill_word },
+ { ' ', mk_set },
+ { '.', last_argument },
+ { '<', h_first },
+ { '>', h_last },
+ { 'b', bk_word },
+ { 'd', fd_kill_word },
+ { 'f', fd_word },
+ { 'l', case_down_word },
+ { 'm', toggle_meta_mode },
+ { 'u', case_up_word },
+ { 'y', yank },
+ { 'w', copy_region },
+ { 0, NULL }
+};
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h
new file mode 100644
index 0000000..e820049
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/editline.h
@@ -0,0 +1,135 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+/*
+** Internal header file for editline library.
+*/
+#include <stdio.h>
+#if defined(HAVE_STDLIB)
+#include <stdlib.h>
+#include <string.h>
+#endif /* defined(HAVE_STDLIB) */
+#if defined(SYS_UNIX)
+#include "unix.h"
+#endif /* defined(SYS_UNIX) */
+#if defined(SYS_OS9)
+#include "os9.h"
+#endif /* defined(SYS_OS9) */
+
+#if !defined(SIZE_T)
+#define SIZE_T unsigned int
+#endif /* !defined(SIZE_T) */
+
+typedef unsigned char CHAR;
+
+#if defined(HIDE)
+#define STATIC static
+#else
+#define STATIC /* NULL */
+#endif /* !defined(HIDE) */
+
+#if !defined(CONST)
+#if defined(__STDC__)
+#define CONST const
+#else
+#define CONST
+#endif /* defined(__STDC__) */
+#endif /* !defined(CONST) */
+
+
+#define MEM_INC 64
+#define SCREEN_INC 256
+
+#define DISPOSE(p) free((char *)(p))
+#define NEW(T, c) \
+ ((T *)malloc((unsigned int)(sizeof (T) * (c))))
+#define RENEW(p, T, c) \
+ (p = (T *)realloc((char *)(p), (unsigned int)(sizeof (T) * (c))))
+#define COPYFROMTO(new, p, len) \
+ (void)memcpy((char *)(new), (char *)(p), (int)(len))
+
+
+/*
+** Variables and routines internal to this package.
+*/
+extern int rl_eof;
+extern int rl_erase;
+extern int rl_intr;
+extern int rl_kill;
+extern int rl_quit;
+extern char *rl_complete();
+extern int rl_list_possib();
+extern void rl_ttyset();
+extern void rl_add_slash();
+
+#if !defined(HAVE_STDLIB)
+extern char *getenv();
+extern char *malloc();
+extern char *realloc();
+extern char *memcpy();
+extern char *strcat();
+extern char *strchr();
+extern char *strrchr();
+extern char *strcpy();
+extern char *strdup();
+extern int strcmp();
+extern int strlen();
+extern int strncmp();
+#endif /* !defined(HAVE_STDLIB) */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c b/tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c
new file mode 100644
index 0000000..17227ea
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/sysunix.c
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+
+/*
+** Unix system-dependant routines for editline library.
+*/
+#include "editline.h"
+
+#if defined(HAVE_TCGETATTR)
+#include <termios.h>
+
+void
+rl_ttyset(Reset)
+ int Reset;
+{
+ static struct termios old;
+ struct termios new;
+
+ if (Reset == 0) {
+ (void)tcgetattr(0, &old);
+ rl_erase = old.c_cc[VERASE];
+ rl_kill = old.c_cc[VKILL];
+ rl_eof = old.c_cc[VEOF];
+ rl_intr = old.c_cc[VINTR];
+ rl_quit = old.c_cc[VQUIT];
+
+ new = old;
+ new.c_cc[VINTR] = -1;
+ new.c_cc[VQUIT] = -1;
+ new.c_lflag &= ~(ECHO | ICANON);
+ new.c_iflag &= ~(ISTRIP | INPCK);
+ new.c_cc[VMIN] = 1;
+ new.c_cc[VTIME] = 0;
+ (void)tcsetattr(0, TCSADRAIN, &new);
+ }
+ else
+ (void)tcsetattr(0, TCSADRAIN, &old);
+}
+
+#else
+#if defined(HAVE_TERMIO)
+#include <termio.h>
+
+void
+rl_ttyset(Reset)
+ int Reset;
+{
+ static struct termio old;
+ struct termio new;
+
+ if (Reset == 0) {
+ (void)ioctl(0, TCGETA, &old);
+ rl_erase = old.c_cc[VERASE];
+ rl_kill = old.c_cc[VKILL];
+ rl_eof = old.c_cc[VEOF];
+ rl_intr = old.c_cc[VINTR];
+ rl_quit = old.c_cc[VQUIT];
+
+ new = old;
+ new.c_cc[VINTR] = -1;
+ new.c_cc[VQUIT] = -1;
+ new.c_lflag &= ~(ECHO | ICANON);
+ new.c_iflag &= ~(ISTRIP | INPCK);
+ new.c_cc[VMIN] = 1;
+ new.c_cc[VTIME] = 0;
+ (void)ioctl(0, TCSETAW, &new);
+ }
+ else
+ (void)ioctl(0, TCSETAW, &old);
+}
+
+#else
+#include <sgtty.h>
+
+void
+rl_ttyset(Reset)
+ int Reset;
+{
+ static struct sgttyb old_sgttyb;
+ static struct tchars old_tchars;
+ struct sgttyb new_sgttyb;
+ struct tchars new_tchars;
+
+ if (Reset == 0) {
+ (void)ioctl(0, TIOCGETP, &old_sgttyb);
+ rl_erase = old_sgttyb.sg_erase;
+ rl_kill = old_sgttyb.sg_kill;
+
+ (void)ioctl(0, TIOCGETC, &old_tchars);
+ rl_eof = old_tchars.t_eofc;
+ rl_intr = old_tchars.t_intrc;
+ rl_quit = old_tchars.t_quitc;
+
+ new_sgttyb = old_sgttyb;
+ new_sgttyb.sg_flags &= ~ECHO;
+ new_sgttyb.sg_flags |= RAW;
+#if defined(PASS8)
+ new_sgttyb.sg_flags |= PASS8;
+#endif /* defined(PASS8) */
+ (void)ioctl(0, TIOCSETP, &new_sgttyb);
+
+ new_tchars = old_tchars;
+ new_tchars.t_intrc = -1;
+ new_tchars.t_quitc = -1;
+ (void)ioctl(0, TIOCSETC, &new_tchars);
+ }
+ else {
+ (void)ioctl(0, TIOCSETP, &old_sgttyb);
+ (void)ioctl(0, TIOCSETC, &old_tchars);
+ }
+}
+#endif /* defined(HAVE_TERMIO) */
+#endif /* defined(HAVE_TCGETATTR) */
+
+void
+rl_add_slash(path, p)
+ char *path;
+ char *p;
+{
+ struct stat Sb;
+
+ if (stat(path, &Sb) >= 0)
+ (void)strcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ");
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h b/tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h
new file mode 100644
index 0000000..c99b729
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/editline/unix.h
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Simmule Turner and Rich Salz.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
+ *
+ * This software is not subject to any license of the American Telephone
+ * and Telegraph Company or of the Regents of the University of California.
+ *
+ * Permission is granted to anyone to use this software for any purpose on
+ * any computer system, and to alter it and redistribute it freely, subject
+ * to the following restrictions:
+ * 1. The authors are not responsible for the consequences of use of this
+ * software, no matter how awful, even if they arise from flaws in it.
+ * 2. The origin of this software must not be misrepresented, either by
+ * explicit claim or by omission. Since few users ever read sources,
+ * credits must appear in the documentation.
+ * 3. Altered versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software. Since few users
+ * ever read sources, credits must appear in the documentation.
+ * 4. This notice may not be removed or altered.
+ */
+
+
+/*
+** Editline system header file for Unix.
+*/
+
+#define CRLF "\r\n"
+#define FORWARD STATIC
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(USE_DIRENT)
+#include <dirent.h>
+typedef struct dirent DIRENTRY;
+#else
+#include <sys/dir.h>
+typedef struct direct DIRENTRY;
+#endif /* defined(USE_DIRENT) */
+
+#if !defined(S_ISDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif /* !defined(S_ISDIR) */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d b/tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d
new file mode 100644
index 0000000..258c6cd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/javascript-trace.d
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * javascript provider probes
+ *
+ * function-entry (filename, classname, funcname)
+ * function-info (filename, classname, funcname, lineno,
+ * runfilename, runlineno)
+ * function-args (filename, classname, funcname, argc, argv, argv0,
+ * argv1, argv2, argv3, argv4)
+ * function-rval (filename, classname, funcname, lineno, rval, rval0)
+ * function-return (filename, classname, funcname)
+ * object-create-start (filename, classname)
+ * object-create (filename, classname, *object, rlineno)
+ * object-create-done (filename, classname)
+ * object-finalize (NULL, classname, *object)
+ * execute-start (filename, lineno)
+ * execute-done (filename, lineno)
+ */
+
+provider javascript {
+ probe function__entry(char *, char *, char *);
+ probe function__info(char *, char *, char *, int, char *, int);
+ probe function__args(char *, char *, char *, int, void *, void *, void *,
+ void *, void *, void *);
+ probe function__rval(char *, char *, char *, int, void *, void *);
+ probe function__return(char *, char *, char *);
+ probe object__create__start(char *, char *);
+ probe object__create__done(char *, char *);
+ /* XXX must use unsigned longs here instead of uintptr_t for OS X
+ (Apple radar: 5194316 & 5565198) */
+ probe object__create(char *, char *, unsigned long, int);
+ probe object__finalize(char *, char *, unsigned long);
+ probe execute__start(char *, int);
+ probe execute__done(char *, int);
+};
+
+/*
+#pragma D attributes Unstable/Unstable/Common provider mozilla provider
+#pragma D attributes Private/Private/Unknown provider mozilla module
+#pragma D attributes Private/Private/Unknown provider mozilla function
+#pragma D attributes Unstable/Unstable/Common provider mozilla name
+#pragma D attributes Unstable/Unstable/Common provider mozilla args
+*/
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl
new file mode 100644
index 0000000..047d390
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jitstats.tbl
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * June 22, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Brian Crowder <crowder@fiverocks.com>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+JITSTAT(recorderStarted)
+JITSTAT(recorderAborted)
+JITSTAT(traceCompleted)
+JITSTAT(sideExitIntoInterpreter)
+JITSTAT(typeMapMismatchAtEntry)
+JITSTAT(returnToDifferentLoopHeader)
+JITSTAT(traceTriggered)
+JITSTAT(globalShapeMismatchAtEntry)
+JITSTAT(treesTrashed)
+JITSTAT(slotPromoted)
+JITSTAT(unstableLoopVariable)
+JITSTAT(breakLoopExits)
+JITSTAT(returnLoopExits)
+JITSTAT(mergedLoopExits)
+JITSTAT(noCompatInnerTrees)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in b/tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in
new file mode 100644
index 0000000..600253e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js-config.h.in
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_config_h___
+#define js_config_h___
+
+/* Definitions set at build time that affect SpiderMonkey's public API.
+ This header file is generated by the SpiderMonkey configure script,
+ and installed along with jsapi.h. */
+
+/* Define to 1 if SpiderMonkey should support multi-threaded clients. */
+#undef JS_THREADSAFE
+
+/* Define to 1 if SpiderMonkey should support the ability to perform
+ entirely too much GC. */
+#undef JS_GC_ZEAL
+
+#endif /* js_config_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js-config.in b/tools/node_modules/expresso/deps/jscoverage/js/js-config.in
new file mode 100644
index 0000000..59b4719
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js-config.in
@@ -0,0 +1,111 @@
+#!/bin/sh
+
+prefix='@prefix@'
+mozilla_version='@MOZILLA_VERSION@'
+LIBRARY_NAME='@LIBRARY_NAME@'
+NSPR_CFLAGS='@NSPR_CFLAGS@'
+JS_CONFIG_LIBS='@JS_CONFIG_LIBS@'
+MOZ_JS_LIBS='@MOZ_JS_LIBS@'
+
+usage()
+{
+ cat <<EOF
+Usage: js-config [OPTIONS]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--includedir[=DIR]]
+ [--libdir[=DIR]]
+ [--version]
+ [--libs]
+ [--cflags]
+ [--lib-filenames]
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case $1 in
+ --prefix=*)
+ prefix=$optarg
+ ;;
+ --prefix)
+ echo_prefix=yes
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=yes
+ ;;
+ --includedir=*)
+ includedir=$optarg
+ ;;
+ --includedir)
+ echo_includedir=yes
+ ;;
+ --libdir=*)
+ libdir=$optarg
+ ;;
+ --libdir)
+ echo_libdir=yes
+ ;;
+ --version)
+ echo "$mozilla_version"
+ ;;
+ --cflags)
+ echo_cflags=yes
+ ;;
+ --libs)
+ echo_libs=yes
+ ;;
+ *)
+ usage 1 1>&2
+ ;;
+ esac
+ shift
+done
+
+# Set variables that may be dependent upon other variables
+if test -z "$exec_prefix"; then
+ exec_prefix=@exec_prefix@
+fi
+if test -z "$includedir"; then
+ includedir=@includedir@
+fi
+if test -z "$libdir"; then
+ libdir=@libdir@
+fi
+
+if test "$echo_prefix" = "yes"; then
+ echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+ echo $exec_prefix
+fi
+
+if test "$echo_includedir" = "yes"; then
+ echo $includedir
+fi
+
+if test "$echo_libdir" = "yes"; then
+ echo $libdir
+fi
+
+if test "$echo_cflags" = "yes"; then
+ echo "-I$includedir/js $NSPR_CFLAGS"
+fi
+
+if test "$echo_libs" = "yes"; then
+ echo "$MOZ_JS_LIBS $JS_CONFIG_LIBS"
+fi
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js.cpp b/tools/node_modules/expresso/deps/jscoverage/js/js.cpp
new file mode 100644
index 0000000..9ffc847
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js.cpp
@@ -0,0 +1,4050 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS shell.
+ */
+#include "jsstddef.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include "jstypes.h"
+#include "jsarena.h"
+#include "jsutil.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+
+#ifdef LIVECONNECT
+#include "jsjava.h"
+#endif
+
+#ifdef JSDEBUGGER
+#include "jsdebug.h"
+#ifdef JSDEBUGGER_JAVA_UI
+#include "jsdjava.h"
+#endif /* JSDEBUGGER_JAVA_UI */
+#ifdef JSDEBUGGER_C_UI
+#include "jsdb.h"
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+#if defined(XP_WIN) || defined(XP_OS2)
+#include <io.h> /* for isatty() */
+#endif
+
+typedef enum JSShellExitCode {
+ EXITCODE_RUNTIME_ERROR = 3,
+ EXITCODE_FILE_NOT_FOUND = 4,
+ EXITCODE_OUT_OF_MEMORY = 5
+} JSShellExitCode;
+
+size_t gStackChunkSize = 8192;
+
+/* Assume that we can not use more than 5e5 bytes of C stack by default. */
+static size_t gMaxStackSize = 500000;
+static jsuword gStackBase;
+
+static size_t gScriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
+
+static JSBool gEnableBranchCallback = JS_FALSE;
+static uint32 gBranchCount;
+static uint32 gBranchLimit;
+
+int gExitCode = 0;
+JSBool gQuitting = JS_FALSE;
+FILE *gErrFile = NULL;
+FILE *gOutFile = NULL;
+
+static JSBool reportWarnings = JS_TRUE;
+static JSBool compileOnly = JS_FALSE;
+
+typedef enum JSShellErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+ name = number,
+#include "jsshell.msg"
+#undef MSG_DEF
+ JSShellErr_Limit
+#undef MSGDEF
+} JSShellErrNum;
+
+static const JSErrorFormatString *
+my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
+static JSObject *
+split_setup(JSContext *cx);
+
+#ifdef EDITLINE
+JS_BEGIN_EXTERN_C
+extern char *readline(const char *prompt);
+extern void add_history(char *line);
+JS_END_EXTERN_C
+#endif
+
+static JSBool
+GetLine(JSContext *cx, char *bufp, FILE *file, const char *prompt) {
+#ifdef EDITLINE
+ /*
+ * Use readline only if file is stdin, because there's no way to specify
+ * another handle. Are other filehandles interactive?
+ */
+ if (file == stdin) {
+ char *linep = readline(prompt);
+ if (!linep)
+ return JS_FALSE;
+ if (linep[0] != '\0')
+ add_history(linep);
+ strcpy(bufp, linep);
+ JS_free(cx, linep);
+ bufp += strlen(bufp);
+ *bufp++ = '\n';
+ *bufp = '\0';
+ } else
+#endif
+ {
+ char line[256];
+ fprintf(gOutFile, prompt);
+ fflush(gOutFile);
+ if (!fgets(line, sizeof line, file))
+ return JS_FALSE;
+ strcpy(bufp, line);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+my_BranchCallback(JSContext *cx, JSScript *script)
+{
+ if (++gBranchCount == gBranchLimit) {
+ if (script) {
+ if (script->filename)
+ fprintf(gErrFile, "%s:", script->filename);
+ fprintf(gErrFile, "%u: script branch callback (%u callbacks)\n",
+ script->lineno, gBranchLimit);
+ } else {
+ fprintf(gErrFile, "native branch callback (%u callbacks)\n",
+ gBranchLimit);
+ }
+ gBranchCount = 0;
+ return JS_FALSE;
+ }
+#ifdef JS_THREADSAFE
+ if ((gBranchCount & 0xff) == 1) {
+#endif
+ if ((gBranchCount & 0x3fff) == 1)
+ JS_MaybeGC(cx);
+#ifdef JS_THREADSAFE
+ else
+ JS_YieldRequest(cx);
+ }
+#endif
+ return JS_TRUE;
+}
+
+static void
+SetContextOptions(JSContext *cx)
+{
+ jsuword stackLimit;
+
+ if (gMaxStackSize == 0) {
+ /*
+ * Disable checking for stack overflow if limit is zero.
+ */
+ stackLimit = 0;
+ } else {
+#if JS_STACK_GROWTH_DIRECTION > 0
+ stackLimit = gStackBase + gMaxStackSize;
+#else
+ stackLimit = gStackBase - gMaxStackSize;
+#endif
+ }
+ JS_SetThreadStackLimit(cx, stackLimit);
+ JS_SetScriptStackQuota(cx, gScriptStackQuota);
+ if (gEnableBranchCallback) {
+ JS_SetBranchCallback(cx, my_BranchCallback);
+ JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
+ }
+}
+
+static void
+Process(JSContext *cx, JSObject *obj, char *filename, JSBool forceTTY)
+{
+ JSBool ok, hitEOF;
+ JSScript *script;
+ jsval result;
+ JSString *str;
+ char buffer[4096];
+ char *bufp;
+ int lineno;
+ int startline;
+ FILE *file;
+ uint32 oldopts;
+
+ if (forceTTY || !filename || strcmp(filename, "-") == 0) {
+ file = stdin;
+ } else {
+ file = fopen(filename, "r");
+ if (!file) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_CANT_OPEN, filename, strerror(errno));
+ gExitCode = EXITCODE_FILE_NOT_FOUND;
+ return;
+ }
+ }
+
+ SetContextOptions(cx);
+
+ if (!forceTTY && !isatty(fileno(file))) {
+ /*
+ * It's not interactive - just execute it.
+ *
+ * Support the UNIX #! shell hack; gobble the first line if it starts
+ * with '#'. TODO - this isn't quite compatible with sharp variables,
+ * as a legal js program (using sharp variables) might start with '#'.
+ * But that would require multi-character lookahead.
+ */
+ int ch = fgetc(file);
+ if (ch == '#') {
+ while((ch = fgetc(file)) != EOF) {
+ if (ch == '\n' || ch == '\r')
+ break;
+ }
+ }
+ ungetc(ch, file);
+
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+ script = JS_CompileFileHandle(cx, obj, filename, file);
+ JS_SetOptions(cx, oldopts);
+ if (script) {
+ if (!compileOnly)
+ (void)JS_ExecuteScript(cx, obj, script, NULL);
+ JS_DestroyScript(cx, script);
+ }
+
+ if (file != stdin)
+ fclose(file);
+ return;
+ }
+
+ /* It's an interactive filehandle; drop into read-eval-print loop. */
+ lineno = 1;
+ hitEOF = JS_FALSE;
+ do {
+ bufp = buffer;
+ *bufp = '\0';
+
+ /*
+ * Accumulate lines until we get a 'compilable unit' - one that either
+ * generates an error (before running out of source) or that compiles
+ * cleanly. This should be whenever we get a complete statement that
+ * coincides with the end of a line.
+ */
+ startline = lineno;
+ do {
+ if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) {
+ hitEOF = JS_TRUE;
+ break;
+ }
+ bufp += strlen(bufp);
+ lineno++;
+ } while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
+
+ /* Clear any pending exception from previous failed compiles. */
+ JS_ClearPendingException(cx);
+ script = JS_CompileScript(cx, obj, buffer, strlen(buffer), "typein",
+ startline);
+ if (script) {
+ if (!compileOnly) {
+ ok = JS_ExecuteScript(cx, obj, script, &result);
+ if (ok && !JSVAL_IS_VOID(result)) {
+ str = JS_ValueToString(cx, result);
+ if (str)
+ fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
+ else
+ ok = JS_FALSE;
+ }
+ }
+ JS_DestroyScript(cx, script);
+ }
+ } while (!hitEOF && !gQuitting);
+ fprintf(gOutFile, "\n");
+ if (file != stdin)
+ fclose(file);
+ return;
+}
+
+static int
+usage(void)
+{
+ fprintf(gErrFile, "%s\n", JS_GetImplementationVersion());
+ fprintf(gErrFile, "usage: js [-zKPswWxCi] [-b branchlimit] [-c stackchunksize] [-o option] [-v version] [-f scriptfile] [-e script] [-S maxstacksize] "
+#ifdef JS_GC_ZEAL
+"[-Z gczeal] "
+#endif
+"[scriptfile] [scriptarg...]\n");
+ return 2;
+}
+
+static struct {
+ const char *name;
+ uint32 flag;
+} js_options[] = {
+ {"strict", JSOPTION_STRICT},
+ {"werror", JSOPTION_WERROR},
+ {"atline", JSOPTION_ATLINE},
+ {"xml", JSOPTION_XML},
+ {"relimit", JSOPTION_RELIMIT},
+ {"anonfunfix", JSOPTION_ANONFUNFIX},
+ {"jit", JSOPTION_JIT},
+ {NULL, 0}
+};
+
+extern JSClass global_class;
+
+static int
+ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
+{
+ int i, j, length;
+ JSObject *argsObj;
+ char *filename = NULL;
+ JSBool isInteractive = JS_TRUE;
+ JSBool forceTTY = JS_FALSE;
+
+ /*
+ * Scan past all optional arguments so we can create the arguments object
+ * before processing any -f options, which must interleave properly with
+ * -v and -w options. This requires two passes, and without getopt, we'll
+ * have to keep the option logic here and in the second for loop in sync.
+ */
+ for (i = 0; i < argc; i++) {
+ if (argv[i][0] != '-' || argv[i][1] == '\0') {
+ ++i;
+ break;
+ }
+ switch (argv[i][1]) {
+ case 'b':
+ case 'c':
+ case 'f':
+ case 'e':
+ case 'v':
+ case 'S':
+#ifdef JS_GC_ZEAL
+ case 'Z':
+#endif
+ ++i;
+ break;
+ default:;
+ }
+ }
+
+ /*
+ * Create arguments early and define it to root it, so it's safe from any
+ * GC calls nested below, and so it is available to -f <file> arguments.
+ */
+ argsObj = JS_NewArrayObject(cx, 0, NULL);
+ if (!argsObj)
+ return 1;
+ if (!JS_DefineProperty(cx, obj, "arguments", OBJECT_TO_JSVAL(argsObj),
+ NULL, NULL, 0)) {
+ return 1;
+ }
+
+ length = argc - i;
+ for (j = 0; j < length; j++) {
+ JSString *str = JS_NewStringCopyZ(cx, argv[i++]);
+ if (!str)
+ return 1;
+ if (!JS_DefineElement(cx, argsObj, j, STRING_TO_JSVAL(str),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return 1;
+ }
+ }
+
+ for (i = 0; i < argc; i++) {
+ if (argv[i][0] != '-' || argv[i][1] == '\0') {
+ filename = argv[i++];
+ isInteractive = JS_FALSE;
+ break;
+ }
+
+ switch (argv[i][1]) {
+ case 'v':
+ if (++i == argc)
+ return usage();
+
+ JS_SetVersion(cx, (JSVersion) atoi(argv[i]));
+ break;
+
+#ifdef JS_GC_ZEAL
+ case 'Z':
+ if (++i == argc)
+ return usage();
+ JS_SetGCZeal(cx, atoi(argv[i]));
+ break;
+#endif
+
+ case 'w':
+ reportWarnings = JS_TRUE;
+ break;
+
+ case 'W':
+ reportWarnings = JS_FALSE;
+ break;
+
+ case 's':
+ JS_ToggleOptions(cx, JSOPTION_STRICT);
+ break;
+
+ case 'E':
+ JS_ToggleOptions(cx, JSOPTION_RELIMIT);
+ break;
+
+ case 'x':
+ JS_ToggleOptions(cx, JSOPTION_XML);
+ break;
+
+ case 'j':
+ JS_ToggleOptions(cx, JSOPTION_JIT);
+#if defined(JS_TRACER) && defined(DEBUG)
+extern struct JSClass jitstats_class;
+extern void js_InitJITStatsClass(JSContext *cx, JSObject *glob);
+ js_InitJITStatsClass(cx, JS_GetGlobalObject(cx));
+ JS_DefineObject(cx, JS_GetGlobalObject(cx), "tracemonkey",
+ &jitstats_class, NULL, 0);
+#endif
+ break;
+
+ case 'o':
+ if (++i == argc)
+ return usage();
+
+ for (j = 0; js_options[j].name; ++j) {
+ if (strcmp(js_options[j].name, argv[i]) == 0) {
+ JS_ToggleOptions(cx, js_options[j].flag);
+ break;
+ }
+ }
+ break;
+
+ case 'P':
+ if (JS_GET_CLASS(cx, JS_GetPrototype(cx, obj)) != &global_class) {
+ JSObject *gobj;
+
+ if (!JS_SealObject(cx, obj, JS_TRUE))
+ return JS_FALSE;
+ gobj = JS_NewObject(cx, &global_class, NULL, NULL);
+ if (!gobj)
+ return JS_FALSE;
+ if (!JS_SetPrototype(cx, gobj, obj))
+ return JS_FALSE;
+ JS_SetParent(cx, gobj, NULL);
+ JS_SetGlobalObject(cx, gobj);
+ obj = gobj;
+ }
+ break;
+
+ case 'b':
+ gBranchLimit = atoi(argv[++i]);
+ gEnableBranchCallback = (gBranchLimit != 0);
+ break;
+
+ case 'c':
+ /* set stack chunk size */
+ gStackChunkSize = atoi(argv[++i]);
+ break;
+
+ case 'f':
+ if (++i == argc)
+ return usage();
+
+ Process(cx, obj, argv[i], JS_FALSE);
+
+ /*
+ * XXX: js -f foo.js should interpret foo.js and then
+ * drop into interactive mode, but that breaks the test
+ * harness. Just execute foo.js for now.
+ */
+ isInteractive = JS_FALSE;
+ break;
+
+ case 'e':
+ {
+ jsval rval;
+
+ if (++i == argc)
+ return usage();
+
+ /* Pass a filename of -e to imitate PERL */
+ JS_EvaluateScript(cx, obj, argv[i], strlen(argv[i]),
+ "-e", 1, &rval);
+
+ isInteractive = JS_FALSE;
+ break;
+
+ }
+ case 'C':
+ compileOnly = JS_TRUE;
+ isInteractive = JS_FALSE;
+ break;
+
+ case 'i':
+ isInteractive = forceTTY = JS_TRUE;
+ break;
+
+ case 'S':
+ if (++i == argc)
+ return usage();
+
+ /* Set maximum stack size. */
+ gMaxStackSize = atoi(argv[i]);
+ break;
+
+ case 'z':
+ obj = split_setup(cx);
+ if (!obj)
+ return gExitCode;
+ break;
+#ifdef MOZ_SHARK
+ case 'k':
+ JS_ConnectShark();
+ break;
+#endif
+ default:
+ return usage();
+ }
+ }
+
+ if (filename || isInteractive)
+ Process(cx, obj, filename, forceTTY);
+ return gExitCode;
+}
+
+static JSBool
+Version(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (argc > 0 && JSVAL_IS_INT(argv[0]))
+ *rval = INT_TO_JSVAL(JS_SetVersion(cx, (JSVersion) JSVAL_TO_INT(argv[0])));
+ else
+ *rval = INT_TO_JSVAL(JS_GetVersion(cx));
+ return JS_TRUE;
+}
+
+static JSBool
+Options(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uint32 optset, flag;
+ uintN i, j, found;
+ JSString *str;
+ const char *opt;
+ char *names;
+
+ optset = 0;
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ opt = JS_GetStringBytes(str);
+ for (j = 0; js_options[j].name; j++) {
+ if (strcmp(js_options[j].name, opt) == 0) {
+ optset |= js_options[j].flag;
+ break;
+ }
+ }
+ }
+ optset = JS_ToggleOptions(cx, optset);
+
+ names = NULL;
+ found = 0;
+ while (optset != 0) {
+ flag = optset;
+ optset &= optset - 1;
+ flag &= ~optset;
+ for (j = 0; js_options[j].name; j++) {
+ if (js_options[j].flag == flag) {
+ names = JS_sprintf_append(names, "%s%s",
+ names ? "," : "", js_options[j].name);
+ found++;
+ break;
+ }
+ }
+ }
+ if (!found)
+ names = strdup("");
+ if (!names) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ str = JS_NewString(cx, names, strlen(names));
+ if (!str) {
+ free(names);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+Load(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSString *str;
+ const char *filename;
+ JSScript *script;
+ JSBool ok;
+ uint32 oldopts;
+
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(str);
+ filename = JS_GetStringBytes(str);
+ errno = 0;
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+ script = JS_CompileFile(cx, obj, filename);
+ JS_SetOptions(cx, oldopts);
+ if (!script) {
+ ok = JS_FALSE;
+ } else {
+ ok = !compileOnly
+ ? JS_ExecuteScript(cx, obj, script, NULL)
+ : JS_TRUE;
+ JS_DestroyScript(cx, script);
+ }
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/*
+ * function readline()
+ * Provides a hook for scripts to read a line from stdin.
+ */
+static JSBool
+ReadLine(JSContext *cx, uintN argc, jsval *vp)
+{
+#define BUFSIZE 256
+ FILE *from;
+ char *buf, *tmp;
+ size_t bufsize, buflength, gotlength;
+ JSBool sawNewline;
+ JSString *str;
+
+ from = stdin;
+ buflength = 0;
+ bufsize = BUFSIZE;
+ buf = (char *) JS_malloc(cx, bufsize);
+ if (!buf)
+ return JS_FALSE;
+
+ sawNewline = JS_FALSE;
+ while ((gotlength =
+ js_fgets(buf + buflength, bufsize - buflength, from)) > 0) {
+ buflength += gotlength;
+
+ /* Are we done? */
+ if (buf[buflength - 1] == '\n') {
+ buf[buflength - 1] = '\0';
+ sawNewline = JS_TRUE;
+ break;
+ } else if (buflength < bufsize - 1) {
+ break;
+ }
+
+ /* Else, grow our buffer for another pass. */
+ bufsize *= 2;
+ if (bufsize > buflength) {
+ tmp = (char *) JS_realloc(cx, buf, bufsize);
+ } else {
+ JS_ReportOutOfMemory(cx);
+ tmp = NULL;
+ }
+
+ if (!tmp) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ buf = tmp;
+ }
+
+ /* Treat the empty string specially. */
+ if (buflength == 0) {
+ *vp = feof(from) ? JSVAL_NULL : JS_GetEmptyStringValue(cx);
+ JS_free(cx, buf);
+ return JS_TRUE;
+ }
+
+ /* Shrink the buffer to the real size. */
+ tmp = (char *) JS_realloc(cx, buf, buflength);
+ if (!tmp) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ buf = tmp;
+
+ /*
+ * Turn buf into a JSString. Note that buflength includes the trailing null
+ * character.
+ */
+ str = JS_NewString(cx, buf, sawNewline ? buflength - 1 : buflength);
+ if (!str) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static jsval JS_FASTCALL
+Print_tn(JSContext *cx, JSString *str)
+{
+ char *bytes = JS_EncodeString(cx, str);
+ if (!bytes)
+ return JSVAL_ERROR_COOKIE;
+ fprintf(gOutFile, "%s\n", bytes);
+ JS_free(cx, bytes);
+ fflush(gOutFile);
+ return JSVAL_VOID;
+}
+#endif
+
+static JSBool
+Print(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ uintN i;
+ JSString *str;
+ char *bytes;
+
+ argv = JS_ARGV(cx, vp);
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ bytes = JS_EncodeString(cx, str);
+ if (!bytes)
+ return JS_FALSE;
+ fprintf(gOutFile, "%s%s", i ? " " : "", bytes);
+ JS_free(cx, bytes);
+ }
+
+ fputc('\n', gOutFile);
+ fflush(gOutFile);
+
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+static JSBool
+Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+static JSBool
+Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+#ifdef LIVECONNECT
+ JSJ_SimpleShutdown();
+#endif
+
+ JS_ConvertArguments(cx, argc, argv,"/ i", &gExitCode);
+
+ gQuitting = JS_TRUE;
+ return JS_FALSE;
+}
+
+static JSBool
+GC(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSRuntime *rt;
+ uint32 preBytes;
+
+ rt = cx->runtime;
+ preBytes = rt->gcBytes;
+ JS_GC(cx);
+
+ fprintf(gOutFile, "before %lu, after %lu, break %08lx\n",
+ (unsigned long)preBytes, (unsigned long)rt->gcBytes,
+#ifdef XP_UNIX
+ (unsigned long)sbrk(0)
+#else
+ 0
+#endif
+ );
+#ifdef JS_GCMETER
+ js_DumpGCStats(rt, stdout);
+#endif
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+GCParameter(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ const char *paramName;
+ JSGCParamKey param;
+ uint32 value;
+
+ if (argc == 0) {
+ str = JS_ValueToString(cx, JSVAL_VOID);
+ JS_ASSERT(str);
+ } else {
+ str = JS_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+ }
+ paramName = JS_GetStringBytes(str);
+ if (!paramName)
+ return JS_FALSE;
+ if (strcmp(paramName, "maxBytes") == 0) {
+ param = JSGC_MAX_BYTES;
+ } else if (strcmp(paramName, "maxMallocBytes") == 0) {
+ param = JSGC_MAX_MALLOC_BYTES;
+ } else {
+ JS_ReportError(cx,
+ "the first argument argument must be either maxBytes "
+ "or maxMallocBytes");
+ return JS_FALSE;
+ }
+
+ if (!JS_ValueToECMAUint32(cx, argc < 2 ? JSVAL_VOID : vp[3], &value))
+ return JS_FALSE;
+ if (value == 0) {
+ JS_ReportError(cx,
+ "the second argument must be convertable to uint32 with "
+ "non-zero value");
+ return JS_FALSE;
+ }
+ JS_SetGCParameter(cx->runtime, param, value);
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+#ifdef JS_GC_ZEAL
+static JSBool
+GCZeal(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 zeal;
+
+ if (!JS_ValueToECMAUint32(cx, argc == 0 ? JSVAL_VOID : vp[2], &zeal))
+ return JS_FALSE;
+ JS_SetGCZeal(cx, (uint8)zeal);
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+#endif /* JS_GC_ZEAL */
+
+typedef struct JSCountHeapNode JSCountHeapNode;
+
+struct JSCountHeapNode {
+ void *thing;
+ int32 kind;
+ JSCountHeapNode *next;
+};
+
+typedef struct JSCountHeapTracer {
+ JSTracer base;
+ JSDHashTable visited;
+ JSBool ok;
+ JSCountHeapNode *traceList;
+ JSCountHeapNode *recycleList;
+} JSCountHeapTracer;
+
+static void
+CountHeapNotify(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSCountHeapTracer *countTracer;
+ JSDHashEntryStub *entry;
+ JSCountHeapNode *node;
+
+ JS_ASSERT(trc->callback == CountHeapNotify);
+ countTracer = (JSCountHeapTracer *)trc;
+ if (!countTracer->ok)
+ return;
+
+ entry = (JSDHashEntryStub *)
+ JS_DHashTableOperate(&countTracer->visited, thing, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(trc->context);
+ countTracer->ok = JS_FALSE;
+ return;
+ }
+ if (entry->key)
+ return;
+ entry->key = thing;
+
+ node = countTracer->recycleList;
+ if (node) {
+ countTracer->recycleList = node->next;
+ } else {
+ node = (JSCountHeapNode *) JS_malloc(trc->context, sizeof *node);
+ if (!node) {
+ countTracer->ok = JS_FALSE;
+ return;
+ }
+ }
+ node->thing = thing;
+ node->kind = kind;
+ node->next = countTracer->traceList;
+ countTracer->traceList = node;
+}
+
+static JSBool
+CountHeap(JSContext *cx, uintN argc, jsval *vp)
+{
+ void* startThing;
+ int32 startTraceKind;
+ jsval v;
+ int32 traceKind, i;
+ JSString *str;
+ char *bytes;
+ JSCountHeapTracer countTracer;
+ JSCountHeapNode *node;
+ size_t counter;
+
+ static const struct {
+ const char *name;
+ int32 kind;
+ } traceKindNames[] = {
+ { "all", -1 },
+ { "object", JSTRACE_OBJECT },
+ { "double", JSTRACE_DOUBLE },
+ { "string", JSTRACE_STRING },
+#if JS_HAS_XML_SUPPORT
+ { "xml", JSTRACE_XML },
+#endif
+ };
+
+ startThing = NULL;
+ startTraceKind = 0;
+ if (argc > 0) {
+ v = JS_ARGV(cx, vp)[0];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ startThing = JSVAL_TO_TRACEABLE(v);
+ startTraceKind = JSVAL_TRACE_KIND(v);
+ } else if (v != JSVAL_NULL) {
+ JS_ReportError(cx,
+ "the first argument is not null or a heap-allocated "
+ "thing");
+ return JS_FALSE;
+ }
+ }
+
+ traceKind = -1;
+ if (argc > 1) {
+ str = JS_ValueToString(cx, JS_ARGV(cx, vp)[1]);
+ if (!str)
+ return JS_FALSE;
+ bytes = JS_GetStringBytes(str);
+ if (!bytes)
+ return JS_FALSE;
+ for (i = 0; ;) {
+ if (strcmp(bytes, traceKindNames[i].name) == 0) {
+ traceKind = traceKindNames[i].kind;
+ break;
+ }
+ if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
+ JS_ReportError(cx, "trace kind name '%s' is unknown", bytes);
+ return JS_FALSE;
+ }
+ }
+ }
+
+ JS_TRACER_INIT(&countTracer.base, cx, CountHeapNotify);
+ if (!JS_DHashTableInit(&countTracer.visited, JS_DHashGetStubOps(),
+ NULL, sizeof(JSDHashEntryStub),
+ JS_DHASH_DEFAULT_CAPACITY(100))) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ countTracer.ok = JS_TRUE;
+ countTracer.traceList = NULL;
+ countTracer.recycleList = NULL;
+
+ if (!startThing) {
+ JS_TraceRuntime(&countTracer.base);
+ } else {
+ JS_SET_TRACING_NAME(&countTracer.base, "root");
+ JS_CallTracer(&countTracer.base, startThing, startTraceKind);
+ }
+
+ counter = 0;
+ while ((node = countTracer.traceList) != NULL) {
+ if (traceKind == -1 || node->kind == traceKind)
+ counter++;
+ countTracer.traceList = node->next;
+ node->next = countTracer.recycleList;
+ countTracer.recycleList = node;
+ JS_TraceChildren(&countTracer.base, node->thing, node->kind);
+ }
+ while ((node = countTracer.recycleList) != NULL) {
+ countTracer.recycleList = node->next;
+ JS_free(cx, node);
+ }
+ JS_DHashTableFinish(&countTracer.visited);
+
+ return countTracer.ok && JS_NewNumberValue(cx, (jsdouble) counter, vp);
+}
+
+static JSScript *
+ValueToScript(JSContext *cx, jsval v)
+{
+ JSScript *script;
+ JSFunction *fun;
+
+ if (!JSVAL_IS_PRIMITIVE(v) &&
+ JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass) {
+ script = (JSScript *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ } else {
+ fun = JS_ValueToFunction(cx, v);
+ if (!fun)
+ return NULL;
+ script = FUN_SCRIPT(fun);
+ }
+
+ if (!script) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_SCRIPTS_ONLY);
+ }
+
+ return script;
+}
+
+static JSBool
+GetTrapArgs(JSContext *cx, uintN argc, jsval *argv, JSScript **scriptp,
+ int32 *ip)
+{
+ jsval v;
+ uintN intarg;
+ JSScript *script;
+
+ *scriptp = cx->fp->down->script;
+ *ip = 0;
+ if (argc != 0) {
+ v = argv[0];
+ intarg = 0;
+ if (!JSVAL_IS_PRIMITIVE(v) &&
+ (JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass ||
+ JS_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_ScriptClass)) {
+ script = ValueToScript(cx, v);
+ if (!script)
+ return JS_FALSE;
+ *scriptp = script;
+ intarg++;
+ }
+ if (argc > intarg) {
+ if (!JS_ValueToInt32(cx, argv[intarg], ip))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSTrapStatus
+TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
+ void *closure)
+{
+ JSString *str;
+ JSStackFrame *caller;
+
+ str = (JSString *) closure;
+ caller = JS_GetScriptedCaller(cx, NULL);
+ if (!JS_EvaluateScript(cx, caller->scopeChain,
+ JS_GetStringBytes(str), JS_GetStringLength(str),
+ caller->script->filename, caller->script->lineno,
+ rval)) {
+ return JSTRAP_ERROR;
+ }
+ if (!JSVAL_IS_VOID(*rval))
+ return JSTRAP_RETURN;
+ return JSTRAP_CONTINUE;
+}
+
+static JSBool
+Trap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ JSScript *script;
+ int32 i;
+
+ if (argc == 0) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_TRAP_USAGE);
+ return JS_FALSE;
+ }
+ argc--;
+ str = JS_ValueToString(cx, argv[argc]);
+ if (!str)
+ return JS_FALSE;
+ argv[argc] = STRING_TO_JSVAL(str);
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ return JS_SetTrap(cx, script, script->code + i, TrapHandler, str);
+}
+
+static JSBool
+Untrap(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSScript *script;
+ int32 i;
+
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ JS_ClearTrap(cx, script, script->code + i, NULL, NULL);
+ return JS_TRUE;
+}
+
+static JSBool
+LineToPC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSScript *script;
+ int32 i;
+ uintN lineno;
+ jsbytecode *pc;
+
+ if (argc == 0) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_LINE2PC_USAGE);
+ return JS_FALSE;
+ }
+ script = cx->fp->down->script;
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ lineno = (i == 0) ? script->lineno : (uintN)i;
+ pc = JS_LineNumberToPC(cx, script, lineno);
+ if (!pc)
+ return JS_FALSE;
+ *rval = INT_TO_JSVAL(PTRDIFF(pc, script->code, jsbytecode));
+ return JS_TRUE;
+}
+
+static JSBool
+PCToLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSScript *script;
+ int32 i;
+ uintN lineno;
+
+ if (!GetTrapArgs(cx, argc, argv, &script, &i))
+ return JS_FALSE;
+ lineno = JS_PCToLineNumber(cx, script, script->code + i);
+ if (!lineno)
+ return JS_FALSE;
+ *rval = INT_TO_JSVAL(lineno);
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static void
+UpdateSwitchTableBounds(JSScript *script, uintN offset,
+ uintN *start, uintN *end)
+{
+ jsbytecode *pc;
+ JSOp op;
+ ptrdiff_t jmplen;
+ jsint low, high, n;
+
+ pc = script->code + offset;
+ op = (JSOp) *pc;
+ switch (op) {
+ case JSOP_TABLESWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto jump_table;
+ case JSOP_TABLESWITCH:
+ jmplen = JUMP_OFFSET_LEN;
+ jump_table:
+ pc += jmplen;
+ low = GET_JUMP_OFFSET(pc);
+ pc += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc);
+ pc += JUMP_OFFSET_LEN;
+ n = high - low + 1;
+ break;
+
+ case JSOP_LOOKUPSWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto lookup_table;
+ case JSOP_LOOKUPSWITCH:
+ jmplen = JUMP_OFFSET_LEN;
+ lookup_table:
+ pc += jmplen;
+ n = GET_INDEX(pc);
+ pc += INDEX_LEN;
+ jmplen += JUMP_OFFSET_LEN;
+ break;
+
+ default:
+ /* [condswitch] switch does not have any jump or lookup tables. */
+ JS_ASSERT(op == JSOP_CONDSWITCH);
+ return;
+ }
+
+ *start = (uintN)(pc - script->code);
+ *end = *start + (uintN)(n * jmplen);
+}
+
+static void
+SrcNotes(JSContext *cx, JSScript *script)
+{
+ uintN offset, delta, caseOff, switchTableStart, switchTableEnd;
+ jssrcnote *notes, *sn;
+ JSSrcNoteType type;
+ const char *name;
+ uint32 index;
+ JSAtom *atom;
+ JSString *str;
+
+ fprintf(gOutFile, "\nSource notes:\n");
+ offset = 0;
+ notes = SCRIPT_NOTES(script);
+ switchTableEnd = switchTableStart = 0;
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ delta = SN_DELTA(sn);
+ offset += delta;
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ name = js_SrcNoteSpec[type].name;
+ if (type == SRC_LABEL) {
+ /* Check if the source note is for a switch case. */
+ if (switchTableStart <= offset && offset < switchTableEnd) {
+ name = "case";
+ } else {
+ JS_ASSERT(script->code[offset] == JSOP_NOP);
+ }
+ }
+ fprintf(gOutFile, "%3u: %5u [%4u] %-8s",
+ (uintN) PTRDIFF(sn, notes, jssrcnote), offset, delta, name);
+ switch (type) {
+ case SRC_SETLINE:
+ fprintf(gOutFile, " lineno %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+ break;
+ case SRC_FOR:
+ fprintf(gOutFile, " cond %u update %u tail %u",
+ (uintN) js_GetSrcNoteOffset(sn, 0),
+ (uintN) js_GetSrcNoteOffset(sn, 1),
+ (uintN) js_GetSrcNoteOffset(sn, 2));
+ break;
+ case SRC_IF_ELSE:
+ fprintf(gOutFile, " else %u elseif %u",
+ (uintN) js_GetSrcNoteOffset(sn, 0),
+ (uintN) js_GetSrcNoteOffset(sn, 1));
+ break;
+ case SRC_COND:
+ case SRC_WHILE:
+ case SRC_PCBASE:
+ case SRC_PCDELTA:
+ case SRC_DECL:
+ case SRC_BRACE:
+ fprintf(gOutFile, " offset %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+ break;
+ case SRC_LABEL:
+ case SRC_LABELBRACE:
+ case SRC_BREAK2LABEL:
+ case SRC_CONT2LABEL:
+ index = js_GetSrcNoteOffset(sn, 0);
+ JS_GET_SCRIPT_ATOM(script, index, atom);
+ JS_ASSERT(ATOM_IS_STRING(atom));
+ str = ATOM_TO_STRING(atom);
+ fprintf(gOutFile, " atom %u (", index);
+ js_FileEscapedString(gOutFile, str, 0);
+ putc(')', gOutFile);
+ break;
+ case SRC_FUNCDEF: {
+ const char *bytes;
+ JSObject *obj;
+ JSFunction *fun;
+
+ index = js_GetSrcNoteOffset(sn, 0);
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
+ str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
+ bytes = str ? JS_GetStringBytes(str) : "N/A";
+ fprintf(gOutFile, " function %u (%s)", index, bytes);
+ break;
+ }
+ case SRC_SWITCH:
+ fprintf(gOutFile, " length %u", (uintN) js_GetSrcNoteOffset(sn, 0));
+ caseOff = (uintN) js_GetSrcNoteOffset(sn, 1);
+ if (caseOff)
+ fprintf(gOutFile, " first case offset %u", caseOff);
+ UpdateSwitchTableBounds(script, offset,
+ &switchTableStart, &switchTableEnd);
+ break;
+ case SRC_CATCH:
+ delta = (uintN) js_GetSrcNoteOffset(sn, 0);
+ if (delta) {
+ if (script->main[offset] == JSOP_LEAVEBLOCK)
+ fprintf(gOutFile, " stack depth %u", delta);
+ else
+ fprintf(gOutFile, " guard delta %u", delta);
+ }
+ break;
+ default:;
+ }
+ fputc('\n', gOutFile);
+ }
+}
+
+static JSBool
+Notes(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSScript *script;
+
+ for (i = 0; i < argc; i++) {
+ script = ValueToScript(cx, argv[i]);
+ if (!script)
+ continue;
+
+ SrcNotes(cx, script);
+ }
+ return JS_TRUE;
+}
+
+JS_STATIC_ASSERT(JSTRY_CATCH == 0);
+JS_STATIC_ASSERT(JSTRY_FINALLY == 1);
+JS_STATIC_ASSERT(JSTRY_ITER == 2);
+
+static const char* const TryNoteNames[] = { "catch", "finally", "iter" };
+
+static JSBool
+TryNotes(JSContext *cx, JSScript *script)
+{
+ JSTryNote *tn, *tnlimit;
+
+ if (script->trynotesOffset == 0)
+ return JS_TRUE;
+
+ tn = JS_SCRIPT_TRYNOTES(script)->vector;
+ tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
+ fprintf(gOutFile, "\nException table:\n"
+ "kind stack start end\n");
+ do {
+ JS_ASSERT(tn->kind < JS_ARRAY_LENGTH(TryNoteNames));
+ fprintf(gOutFile, " %-7s %6u %8u %8u\n",
+ TryNoteNames[tn->kind], tn->stackDepth,
+ tn->start, tn->start + tn->length);
+ } while (++tn != tnlimit);
+ return JS_TRUE;
+}
+
+static JSBool
+Disassemble(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool lines;
+ uintN i;
+ JSScript *script;
+
+ if (argc > 0 &&
+ JSVAL_IS_STRING(argv[0]) &&
+ !strcmp(JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), "-l")) {
+ lines = JS_TRUE;
+ argv++, argc--;
+ } else {
+ lines = JS_FALSE;
+ }
+ for (i = 0; i < argc; i++) {
+ script = ValueToScript(cx, argv[i]);
+ if (!script)
+ return JS_FALSE;
+ if (VALUE_IS_FUNCTION(cx, argv[i])) {
+ JSFunction *fun = JS_ValueToFunction(cx, argv[i]);
+ if (fun && (fun->flags & JSFUN_FLAGS_MASK)) {
+ uint16 flags = fun->flags;
+ fputs("flags:", stdout);
+
+#define SHOW_FLAG(flag) if (flags & JSFUN_##flag) fputs(" " #flag, stdout);
+
+ SHOW_FLAG(LAMBDA);
+ SHOW_FLAG(SETTER);
+ SHOW_FLAG(GETTER);
+ SHOW_FLAG(BOUND_METHOD);
+ SHOW_FLAG(HEAVYWEIGHT);
+ SHOW_FLAG(THISP_STRING);
+ SHOW_FLAG(THISP_NUMBER);
+ SHOW_FLAG(THISP_BOOLEAN);
+ SHOW_FLAG(EXPR_CLOSURE);
+ SHOW_FLAG(INTERPRETED);
+
+#undef SHOW_FLAG
+ putchar('\n');
+ }
+ }
+
+ if (!js_Disassemble(cx, script, lines, stdout))
+ return JS_FALSE;
+ SrcNotes(cx, script);
+ TryNotes(cx, script);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+DisassFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ const char *filename;
+ JSScript *script;
+ JSBool ok;
+ uint32 oldopts;
+
+ if (!argc)
+ return JS_TRUE;
+
+ str = JS_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+
+ filename = JS_GetStringBytes(str);
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
+ script = JS_CompileFile(cx, obj, filename);
+ JS_SetOptions(cx, oldopts);
+ if (!script)
+ return JS_FALSE;
+
+ obj = JS_NewScriptObject(cx, script);
+ if (!obj)
+ return JS_FALSE;
+
+ *rval = OBJECT_TO_JSVAL(obj); /* I like to root it, root it. */
+ ok = Disassemble(cx, obj, 1, rval, rval); /* gross, but works! */
+ *rval = JSVAL_VOID;
+
+ return ok;
+}
+
+static JSBool
+DisassWithSrc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+#define LINE_BUF_LEN 512
+ uintN i, len, line1, line2, bupline;
+ JSScript *script;
+ FILE *file;
+ char linebuf[LINE_BUF_LEN];
+ jsbytecode *pc, *end;
+ JSBool ok;
+ static char sep[] = ";-------------------------";
+
+ ok = JS_TRUE;
+ for (i = 0; ok && i < argc; i++) {
+ script = ValueToScript(cx, argv[i]);
+ if (!script)
+ return JS_FALSE;
+
+ if (!script->filename) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_FILE_SCRIPTS_ONLY);
+ return JS_FALSE;
+ }
+
+ file = fopen(script->filename, "r");
+ if (!file) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_CANT_OPEN, script->filename,
+ strerror(errno));
+ return JS_FALSE;
+ }
+
+ pc = script->code;
+ end = pc + script->length;
+
+ /* burn the leading lines */
+ line2 = JS_PCToLineNumber(cx, script, pc);
+ for (line1 = 0; line1 < line2 - 1; line1++)
+ fgets(linebuf, LINE_BUF_LEN, file);
+
+ bupline = 0;
+ while (pc < end) {
+ line2 = JS_PCToLineNumber(cx, script, pc);
+
+ if (line2 < line1) {
+ if (bupline != line2) {
+ bupline = line2;
+ fprintf(gOutFile, "%s %3u: BACKUP\n", sep, line2);
+ }
+ } else {
+ if (bupline && line1 == line2)
+ fprintf(gOutFile, "%s %3u: RESTORE\n", sep, line2);
+ bupline = 0;
+ while (line1 < line2) {
+ if (!fgets(linebuf, LINE_BUF_LEN, file)) {
+ JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
+ JSSMSG_UNEXPECTED_EOF,
+ script->filename);
+ ok = JS_FALSE;
+ goto bail;
+ }
+ line1++;
+ fprintf(gOutFile, "%s %3u: %s", sep, line1, linebuf);
+ }
+ }
+
+ len = js_Disassemble1(cx, script, pc,
+ PTRDIFF(pc, script->code, jsbytecode),
+ JS_TRUE, stdout);
+ if (!len) {
+ ok = JS_FALSE;
+ goto bail;
+ }
+ pc += len;
+ }
+
+ bail:
+ fclose(file);
+ }
+ return ok;
+#undef LINE_BUF_LEN
+}
+
+static JSBool
+Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool bval;
+ JSString *str;
+
+#if JS_THREADED_INTERP
+ JS_ReportError(cx, "tracing not supported in JS_THREADED_INTERP builds");
+ return JS_FALSE;
+#else
+ if (argc == 0) {
+ *rval = BOOLEAN_TO_JSVAL(cx->tracefp != 0);
+ return JS_TRUE;
+ }
+
+ switch (JS_TypeOfValue(cx, argv[0])) {
+ case JSTYPE_NUMBER:
+ bval = JSVAL_IS_INT(argv[0])
+ ? JSVAL_TO_INT(argv[0])
+ : (jsint) *JSVAL_TO_DOUBLE(argv[0]);
+ break;
+ case JSTYPE_BOOLEAN:
+ bval = JSVAL_TO_BOOLEAN(argv[0]);
+ break;
+ default:
+ str = JS_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ JS_ReportError(cx, "tracing: illegal argument %s",
+ JS_GetStringBytes(str));
+ return JS_FALSE;
+ }
+ cx->tracefp = bval ? stderr : NULL;
+ return JS_TRUE;
+#endif
+}
+
+static void
+DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
+{
+ uintN i;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+ jsval v;
+ JSString *str;
+
+ i = 0;
+ scope = OBJ_SCOPE(obj);
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
+ continue;
+ fprintf(fp, "%3u %p ", i, (void *)sprop);
+
+ v = ID_TO_VALUE(sprop->id);
+ if (JSID_IS_INT(sprop->id)) {
+ fprintf(fp, "[%ld]", (long)JSVAL_TO_INT(v));
+ } else {
+ if (JSID_IS_ATOM(sprop->id)) {
+ str = JSVAL_TO_STRING(v);
+ } else {
+ JS_ASSERT(JSID_IS_OBJECT(sprop->id));
+ str = js_ValueToString(cx, v);
+ fputs("object ", fp);
+ }
+ if (!str)
+ fputs("<error>", fp);
+ else
+ js_FileEscapedString(fp, str, '"');
+ }
+#define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp)
+ DUMP_ATTR(ENUMERATE);
+ DUMP_ATTR(READONLY);
+ DUMP_ATTR(PERMANENT);
+ DUMP_ATTR(GETTER);
+ DUMP_ATTR(SETTER);
+#undef DUMP_ATTR
+
+ fprintf(fp, " slot %lu flags %x shortid %d\n",
+ (unsigned long)sprop->slot, sprop->flags, sprop->shortid);
+ }
+}
+
+static JSBool
+DumpStats(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSString *str;
+ const char *bytes;
+ jsid id;
+ JSObject *obj2;
+ JSProperty *prop;
+ jsval value;
+
+ for (i = 0; i < argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(str);
+ bytes = JS_GetStringBytes(str);
+ if (strcmp(bytes, "arena") == 0) {
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(stdout);
+#endif
+ } else if (strcmp(bytes, "atom") == 0) {
+ js_DumpAtoms(cx, gOutFile);
+ } else if (strcmp(bytes, "global") == 0) {
+ DumpScope(cx, cx->globalObject, stdout);
+ } else {
+ if (!JS_ValueToId(cx, STRING_TO_JSVAL(str), &id))
+ return JS_FALSE;
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+ return JS_FALSE;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
+ return JS_FALSE;
+ }
+ if (!prop || !JSVAL_IS_OBJECT(value)) {
+ fprintf(gErrFile, "js: invalid stats argument %s\n",
+ bytes);
+ continue;
+ }
+ obj = JSVAL_TO_OBJECT(value);
+ if (obj)
+ DumpScope(cx, obj, stdout);
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+DumpHeap(JSContext *cx, uintN argc, jsval *vp)
+{
+ char *fileName;
+ jsval v;
+ void* startThing;
+ uint32 startTraceKind;
+ const char *badTraceArg;
+ void *thingToFind;
+ size_t maxDepth;
+ void *thingToIgnore;
+ FILE *dumpFile;
+ JSBool ok;
+
+ fileName = NULL;
+ if (argc > 0) {
+ v = JS_ARGV(cx, vp)[0];
+ if (v != JSVAL_NULL) {
+ JSString *str;
+
+ str = JS_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+ JS_ARGV(cx, vp)[0] = STRING_TO_JSVAL(str);
+ fileName = JS_GetStringBytes(str);
+ }
+ }
+
+ startThing = NULL;
+ startTraceKind = 0;
+ if (argc > 1) {
+ v = JS_ARGV(cx, vp)[1];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ startThing = JSVAL_TO_TRACEABLE(v);
+ startTraceKind = JSVAL_TRACE_KIND(v);
+ } else if (v != JSVAL_NULL) {
+ badTraceArg = "start";
+ goto not_traceable_arg;
+ }
+ }
+
+ thingToFind = NULL;
+ if (argc > 2) {
+ v = JS_ARGV(cx, vp)[2];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ thingToFind = JSVAL_TO_TRACEABLE(v);
+ } else if (v != JSVAL_NULL) {
+ badTraceArg = "toFind";
+ goto not_traceable_arg;
+ }
+ }
+
+ maxDepth = (size_t)-1;
+ if (argc > 3) {
+ v = JS_ARGV(cx, vp)[3];
+ if (v != JSVAL_NULL) {
+ uint32 depth;
+
+ if (!JS_ValueToECMAUint32(cx, v, &depth))
+ return JS_FALSE;
+ maxDepth = depth;
+ }
+ }
+
+ thingToIgnore = NULL;
+ if (argc > 4) {
+ v = JS_ARGV(cx, vp)[4];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ thingToIgnore = JSVAL_TO_TRACEABLE(v);
+ } else if (v != JSVAL_NULL) {
+ badTraceArg = "toIgnore";
+ goto not_traceable_arg;
+ }
+ }
+
+ if (!fileName) {
+ dumpFile = stdout;
+ } else {
+ dumpFile = fopen(fileName, "w");
+ if (!dumpFile) {
+ JS_ReportError(cx, "can't open %s: %s", fileName, strerror(errno));
+ return JS_FALSE;
+ }
+ }
+
+ ok = JS_DumpHeap(cx, dumpFile, startThing, startTraceKind, thingToFind,
+ maxDepth, thingToIgnore);
+ if (dumpFile != stdout)
+ fclose(dumpFile);
+ return ok;
+
+ not_traceable_arg:
+ JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing",
+ badTraceArg);
+ return JS_FALSE;
+}
+
+#endif /* DEBUG */
+
+#ifdef TEST_CVTARGS
+#include <ctype.h>
+
+static const char *
+EscapeWideString(jschar *w)
+{
+ static char enuf[80];
+ static char hex[] = "0123456789abcdef";
+ jschar u;
+ unsigned char b, c;
+ int i, j;
+
+ if (!w)
+ return "";
+ for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
+ u = w[j];
+ if (u == 0)
+ break;
+ b = (unsigned char)(u >> 8);
+ c = (unsigned char)(u);
+ if (b) {
+ if (i >= sizeof enuf - 6)
+ break;
+ enuf[i++] = '\\';
+ enuf[i++] = 'u';
+ enuf[i++] = hex[b >> 4];
+ enuf[i++] = hex[b & 15];
+ enuf[i++] = hex[c >> 4];
+ enuf[i] = hex[c & 15];
+ } else if (!isprint(c)) {
+ if (i >= sizeof enuf - 4)
+ break;
+ enuf[i++] = '\\';
+ enuf[i++] = 'x';
+ enuf[i++] = hex[c >> 4];
+ enuf[i] = hex[c & 15];
+ } else {
+ enuf[i] = (char)c;
+ }
+ }
+ enuf[i] = 0;
+ return enuf;
+}
+
+#include <stdarg.h>
+
+static JSBool
+ZZ_formatter(JSContext *cx, const char *format, JSBool fromJS, jsval **vpp,
+ va_list *app)
+{
+ jsval *vp;
+ va_list ap;
+ jsdouble re, im;
+
+ printf("entering ZZ_formatter");
+ vp = *vpp;
+ ap = *app;
+ if (fromJS) {
+ if (!JS_ValueToNumber(cx, vp[0], &re))
+ return JS_FALSE;
+ if (!JS_ValueToNumber(cx, vp[1], &im))
+ return JS_FALSE;
+ *va_arg(ap, jsdouble *) = re;
+ *va_arg(ap, jsdouble *) = im;
+ } else {
+ re = va_arg(ap, jsdouble);
+ im = va_arg(ap, jsdouble);
+ if (!JS_NewNumberValue(cx, re, &vp[0]))
+ return JS_FALSE;
+ if (!JS_NewNumberValue(cx, im, &vp[1]))
+ return JS_FALSE;
+ }
+ *vpp = vp + 2;
+ *app = ap;
+ printf("leaving ZZ_formatter");
+ return JS_TRUE;
+}
+
+static JSBool
+ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool b = JS_FALSE;
+ jschar c = 0;
+ int32 i = 0, j = 0;
+ uint32 u = 0;
+ jsdouble d = 0, I = 0, re = 0, im = 0;
+ char *s = NULL;
+ JSString *str = NULL;
+ jschar *w = NULL;
+ JSObject *obj2 = NULL;
+ JSFunction *fun = NULL;
+ jsval v = JSVAL_VOID;
+ JSBool ok;
+
+ if (!JS_AddArgumentFormatter(cx, "ZZ", ZZ_formatter))
+ return JS_FALSE;;
+ ok = JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofvZZ*",
+ &b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj2,
+ &fun, &v, &re, &im);
+ JS_RemoveArgumentFormatter(cx, "ZZ");
+ if (!ok)
+ return JS_FALSE;
+ fprintf(gOutFile,
+ "b %u, c %x (%c), i %ld, u %lu, j %ld\n",
+ b, c, (char)c, i, u, j);
+ fprintf(gOutFile,
+ "d %g, I %g, s %s, S %s, W %s, obj %s, fun %s\n"
+ "v %s, re %g, im %g\n",
+ d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
+ JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj2))),
+ fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "",
+ JS_GetStringBytes(JS_ValueToString(cx, v)), re, im);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+BuildDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ char version[20] = "\n";
+#if JS_VERSION < 150
+ sprintf(version, " for version %d\n", JS_VERSION);
+#endif
+ fprintf(gOutFile, "built on %s at %s%s", __DATE__, __TIME__, version);
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+Clear(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (argc != 0 && !JS_ValueToObject(cx, argv[0], &obj))
+ return JS_FALSE;
+ JS_ClearScope(cx, obj);
+ return JS_TRUE;
+}
+
+static JSBool
+Intern(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = JS_ValueToString(cx, argc == 0 ? JSVAL_VOID : vp[2]);
+ if (!str)
+ return JS_FALSE;
+ if (!JS_InternUCStringN(cx, JS_GetStringChars(str),
+ JS_GetStringLength(str))) {
+ return JS_FALSE;
+ }
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+Clone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFunction *fun;
+ JSObject *funobj, *parent, *clone;
+
+ fun = JS_ValueToFunction(cx, argv[0]);
+ if (!fun)
+ return JS_FALSE;
+ funobj = JS_GetFunctionObject(fun);
+ if (argc > 1) {
+ if (!JS_ValueToObject(cx, argv[1], &parent))
+ return JS_FALSE;
+ } else {
+ parent = JS_GetParent(cx, funobj);
+ }
+ clone = JS_CloneFunctionObject(cx, funobj, parent);
+ if (!clone)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(clone);
+ return JS_TRUE;
+}
+
+static JSBool
+Seal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSObject *target;
+ JSBool deep = JS_FALSE;
+
+ if (!JS_ConvertArguments(cx, argc, argv, "o/b", &target, &deep))
+ return JS_FALSE;
+ if (!target)
+ return JS_TRUE;
+ return JS_SealObject(cx, target, deep);
+}
+
+static JSBool
+GetPDA(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *vobj, *aobj, *pdobj;
+ JSBool ok;
+ JSPropertyDescArray pda;
+ JSPropertyDesc *pd;
+ uint32 i;
+ jsval v;
+
+ if (!JS_ValueToObject(cx, argc == 0 ? JSVAL_VOID : vp[2], &vobj))
+ return JS_FALSE;
+ if (!vobj)
+ return JS_TRUE;
+
+ aobj = JS_NewArrayObject(cx, 0, NULL);
+ if (!aobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(aobj);
+
+ ok = JS_GetPropertyDescArray(cx, vobj, &pda);
+ if (!ok)
+ return JS_FALSE;
+ pd = pda.array;
+ for (i = 0; i < pda.length; i++) {
+ pdobj = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!pdobj) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ /* Protect pdobj from GC by setting it as an element of aobj now */
+ v = OBJECT_TO_JSVAL(pdobj);
+ ok = JS_SetElement(cx, aobj, i, &v);
+ if (!ok)
+ break;
+
+ ok = JS_SetProperty(cx, pdobj, "id", &pd->id) &&
+ JS_SetProperty(cx, pdobj, "value", &pd->value) &&
+ (v = INT_TO_JSVAL(pd->flags),
+ JS_SetProperty(cx, pdobj, "flags", &v)) &&
+ (v = INT_TO_JSVAL(pd->slot),
+ JS_SetProperty(cx, pdobj, "slot", &v)) &&
+ JS_SetProperty(cx, pdobj, "alias", &pd->alias);
+ if (!ok)
+ break;
+ }
+ JS_PutPropertyDescArray(cx, &pda);
+ return ok;
+}
+
+static JSBool
+GetSLX(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSScript *script;
+
+ script = ValueToScript(cx, argc == 0 ? JSVAL_VOID : vp[2]);
+ if (!script)
+ return JS_FALSE;
+ *vp = INT_TO_JSVAL(js_GetScriptLineExtent(script));
+ return JS_TRUE;
+}
+
+static JSBool
+ToInt32(JSContext *cx, uintN argc, jsval *vp)
+{
+ int32 i;
+
+ if (!JS_ValueToInt32(cx, argc == 0 ? JSVAL_VOID : vp[2], &i))
+ return JS_FALSE;
+ return JS_NewNumberValue(cx, i, vp);
+}
+
+static JSBool
+StringsAreUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ *rval = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+StackQuota(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 n;
+
+ if (argc == 0)
+ return JS_NewNumberValue(cx, (double) gScriptStackQuota, vp);
+ if (!JS_ValueToECMAUint32(cx, JS_ARGV(cx, vp)[0], &n))
+ return JS_FALSE;
+ gScriptStackQuota = n;
+ JS_SetScriptStackQuota(cx, gScriptStackQuota);
+ JS_SET_RVAL(cx, vp, JSVAL_VOID);
+ return JS_TRUE;
+}
+
+static const char* badUTF8 = "...\xC0...";
+static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
+static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
+
+static JSBool
+TestUTF8(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ int32 mode = 1;
+ jschar chars[20];
+ size_t charsLength = 5;
+ char bytes[20];
+ size_t bytesLength = 20;
+ if (argc && !JS_ValueToInt32(cx, *argv, &mode))
+ return JS_FALSE;
+
+ /* The following throw errors if compiled with UTF-8. */
+ switch (mode) {
+ /* mode 1: malformed UTF-8 string. */
+ case 1:
+ JS_NewStringCopyZ(cx, badUTF8);
+ break;
+ /* mode 2: big UTF-8 character. */
+ case 2:
+ JS_NewStringCopyZ(cx, bigUTF8);
+ break;
+ /* mode 3: bad surrogate character. */
+ case 3:
+ JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength);
+ break;
+ /* mode 4: use a too small buffer. */
+ case 4:
+ JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
+ break;
+ default:
+ JS_ReportError(cx, "invalid mode parameter");
+ return JS_FALSE;
+ }
+ return !JS_IsExceptionPending (cx);
+}
+
+static JSBool
+ThrowError(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JS_ReportError(cx, "This is an error");
+ return JS_FALSE;
+}
+
+#define LAZY_STANDARD_CLASSES
+
+/* A class for easily testing the inner/outer object callbacks. */
+typedef struct ComplexObject {
+ JSBool isInner;
+ JSBool frozen;
+ JSObject *inner;
+ JSObject *outer;
+} ComplexObject;
+
+static JSObject *
+split_create_outer(JSContext *cx);
+
+static JSObject *
+split_create_inner(JSContext *cx, JSObject *outer);
+
+static ComplexObject *
+split_get_private(JSContext *cx, JSObject *obj);
+
+static JSBool
+split_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+ jsid asId;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ /* Make sure to define this property on the inner object. */
+ if (!JS_ValueToId(cx, *vp, &asId))
+ return JS_FALSE;
+ return OBJ_DEFINE_PROPERTY(cx, cpx->inner, asId, *vp, NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+split_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ if (JSVAL_IS_STRING(id)) {
+ JSString *str;
+
+ str = JSVAL_TO_STRING(id);
+ return JS_GetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
+ JS_GetStringLength(str), vp);
+ }
+ if (JSVAL_IS_INT(id))
+ return JS_GetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
+ return JS_TRUE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+split_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ if (JSVAL_IS_STRING(id)) {
+ JSString *str;
+
+ str = JSVAL_TO_STRING(id);
+ return JS_SetUCProperty(cx, cpx->inner, JS_GetStringChars(str),
+ JS_GetStringLength(str), vp);
+ }
+ if (JSVAL_IS_INT(id))
+ return JS_SetElement(cx, cpx->inner, JSVAL_TO_INT(id), vp);
+ return JS_TRUE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+split_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ ComplexObject *cpx;
+ jsid asId;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ /* Make sure to define this property on the inner object. */
+ if (!JS_ValueToId(cx, *vp, &asId))
+ return JS_FALSE;
+ return OBJ_DELETE_PROPERTY(cx, cpx->inner, asId, vp);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+split_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ ComplexObject *cpx;
+ JSObject *iterator;
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+
+ if (!cpx->isInner && cpx->inner)
+ obj = cpx->inner;
+
+ iterator = JS_NewPropertyIterator(cx, obj);
+ if (!iterator)
+ return JS_FALSE;
+
+ *statep = OBJECT_TO_JSVAL(iterator);
+ if (idp)
+ *idp = JSVAL_ZERO;
+ break;
+
+ case JSENUMERATE_NEXT:
+ iterator = (JSObject*)JSVAL_TO_OBJECT(*statep);
+ if (!JS_NextProperty(cx, iterator, idp))
+ return JS_FALSE;
+
+ if (!JSVAL_IS_VOID(*idp))
+ break;
+ /* Fall through. */
+
+ case JSENUMERATE_DESTROY:
+ /* Let GC at our iterator object. */
+ *statep = JSVAL_NULL;
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+split_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ ComplexObject *cpx;
+
+ cpx = split_get_private(cx, obj);
+ if (!cpx)
+ return JS_TRUE;
+ if (!cpx->isInner && cpx->inner) {
+ jsid asId;
+ JSProperty *prop;
+
+ if (!JS_ValueToId(cx, id, &asId))
+ return JS_FALSE;
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, cpx->inner, asId, objp, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, cpx->inner, prop);
+
+ return JS_TRUE;
+ }
+
+#ifdef LAZY_STANDARD_CLASSES
+ if (!(flags & JSRESOLVE_ASSIGNING)) {
+ JSBool resolved;
+
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+ return JS_FALSE;
+
+ if (resolved) {
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+#endif
+
+ /* XXX For additional realism, let's resolve some random property here. */
+ return JS_TRUE;
+}
+
+static void
+split_finalize(JSContext *cx, JSObject *obj)
+{
+ JS_free(cx, JS_GetPrivate(cx, obj));
+}
+
+static uint32
+split_mark(JSContext *cx, JSObject *obj, void *arg)
+{
+ ComplexObject *cpx;
+
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+
+ if (!cpx->isInner && cpx->inner) {
+ /* Mark the inner object. */
+ JS_MarkGCThing(cx, cpx->inner, "ComplexObject.inner", arg);
+ }
+
+ return 0;
+}
+
+static JSObject *
+split_outerObject(JSContext *cx, JSObject *obj)
+{
+ ComplexObject *cpx;
+
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+ return cpx->isInner ? cpx->outer : obj;
+}
+
+static JSObject *
+split_innerObject(JSContext *cx, JSObject *obj)
+{
+ ComplexObject *cpx;
+
+ cpx = (ComplexObject *) JS_GetPrivate(cx, obj);
+ if (cpx->frozen) {
+ JS_ASSERT(!cpx->isInner);
+ return obj;
+ }
+ return !cpx->isInner ? cpx->inner : obj;
+}
+
+static JSExtendedClass split_global_class = {
+ {"split_global",
+ JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE | JSCLASS_HAS_PRIVATE |
+ JSCLASS_GLOBAL_FLAGS | JSCLASS_IS_EXTENDED,
+ split_addProperty, split_delProperty,
+ split_getProperty, split_setProperty,
+ (JSEnumerateOp)split_enumerate,
+ (JSResolveOp)split_resolve,
+ JS_ConvertStub, split_finalize,
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ split_mark, NULL},
+ NULL, split_outerObject, split_innerObject,
+ NULL, NULL, NULL, NULL, NULL
+};
+
+JSObject *
+split_create_outer(JSContext *cx)
+{
+ ComplexObject *cpx;
+ JSObject *obj;
+
+ cpx = (ComplexObject *) JS_malloc(cx, sizeof *obj);
+ if (!cpx)
+ return NULL;
+ cpx->isInner = JS_FALSE;
+ cpx->frozen = JS_TRUE;
+ cpx->inner = NULL;
+ cpx->outer = NULL;
+
+ obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
+ if (!obj || !JS_SetParent(cx, obj, NULL)) {
+ JS_free(cx, cpx);
+ return NULL;
+ }
+
+ if (!JS_SetPrivate(cx, obj, cpx)) {
+ JS_free(cx, cpx);
+ return NULL;
+ }
+
+ return obj;
+}
+
+static JSObject *
+split_create_inner(JSContext *cx, JSObject *outer)
+{
+ ComplexObject *cpx, *outercpx;
+ JSObject *obj;
+
+ JS_ASSERT(JS_GET_CLASS(cx, outer) == &split_global_class.base);
+
+ cpx = (ComplexObject *) JS_malloc(cx, sizeof *cpx);
+ if (!cpx)
+ return NULL;
+ cpx->isInner = JS_TRUE;
+ cpx->frozen = JS_FALSE;
+ cpx->inner = NULL;
+ cpx->outer = outer;
+
+ obj = JS_NewObject(cx, &split_global_class.base, NULL, NULL);
+ if (!obj || !JS_SetParent(cx, obj, NULL) || !JS_SetPrivate(cx, obj, cpx)) {
+ JS_free(cx, cpx);
+ return NULL;
+ }
+
+ outercpx = (ComplexObject *) JS_GetPrivate(cx, outer);
+ outercpx->inner = obj;
+ outercpx->frozen = JS_FALSE;
+
+ return obj;
+}
+
+static ComplexObject *
+split_get_private(JSContext *cx, JSObject *obj)
+{
+ do {
+ if (JS_GET_CLASS(cx, obj) == &split_global_class.base)
+ return (ComplexObject *) JS_GetPrivate(cx, obj);
+ obj = JS_GetParent(cx, obj);
+ } while (obj);
+
+ return NULL;
+}
+
+static JSBool
+sandbox_enumerate(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+ JSBool b;
+
+ if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
+ return JS_FALSE;
+ return !b || JS_EnumerateStandardClasses(cx, obj);
+}
+
+static JSBool
+sandbox_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ jsval v;
+ JSBool b, resolved;
+
+ if (!JS_GetProperty(cx, obj, "lazy", &v) || !JS_ValueToBoolean(cx, v, &b))
+ return JS_FALSE;
+ if (b && (flags & JSRESOLVE_ASSIGNING) == 0) {
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+ return JS_FALSE;
+ if (resolved) {
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+ *objp = NULL;
+ return JS_TRUE;
+}
+
+static JSClass sandbox_class = {
+ "sandbox",
+ JSCLASS_NEW_RESOLVE,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ sandbox_enumerate, (JSResolveOp)sandbox_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ JSObject *sobj;
+ JSContext *scx;
+ const jschar *src;
+ size_t srclen;
+ JSBool lazy, ok;
+ jsval v;
+ JSStackFrame *fp;
+
+ sobj = NULL;
+ if (!JS_ConvertArguments(cx, argc, argv, "S / o", &str, &sobj))
+ return JS_FALSE;
+
+ scx = JS_NewContext(JS_GetRuntime(cx), gStackChunkSize);
+ if (!scx) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+#ifdef JS_THREADSAFE
+ JS_BeginRequest(scx);
+#endif
+ src = JS_GetStringChars(str);
+ srclen = JS_GetStringLength(str);
+ lazy = JS_FALSE;
+ if (srclen == 4 &&
+ src[0] == 'l' && src[1] == 'a' && src[2] == 'z' && src[3] == 'y') {
+ lazy = JS_TRUE;
+ srclen = 0;
+ }
+
+ if (!sobj) {
+ sobj = JS_NewObject(scx, &sandbox_class, NULL, NULL);
+ if (!sobj || (!lazy && !JS_InitStandardClasses(scx, sobj))) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ v = BOOLEAN_TO_JSVAL(lazy);
+ ok = JS_SetProperty(cx, sobj, "lazy", &v);
+ if (!ok)
+ goto out;
+ }
+
+ if (srclen == 0) {
+ *rval = OBJECT_TO_JSVAL(sobj);
+ ok = JS_TRUE;
+ } else {
+ fp = JS_GetScriptedCaller(cx, NULL);
+ JS_SetGlobalObject(scx, sobj);
+ JS_ToggleOptions(scx, JSOPTION_DONT_REPORT_UNCAUGHT);
+ ok = JS_EvaluateUCScript(scx, sobj, src, srclen,
+ fp->script->filename,
+ JS_PCToLineNumber(cx, fp->script,
+ fp->regs->pc),
+ rval);
+ if (!ok) {
+ if (JS_GetPendingException(scx, &v))
+ JS_SetPendingException(cx, v);
+ else
+ JS_ReportOutOfMemory(cx);
+ }
+ }
+
+out:
+#ifdef JS_THREADSAFE
+ JS_EndRequest(scx);
+#endif
+ JS_DestroyContext(scx);
+ return ok;
+}
+
+static int32 JS_FASTCALL
+ShapeOf_tn(JSObject *obj)
+{
+ if (!obj)
+ return 0;
+ if (!OBJ_IS_NATIVE(obj))
+ return -1;
+ return OBJ_SHAPE(obj);
+}
+
+static JSBool
+ShapeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v = JS_ARGV(cx, vp)[0];
+ if (!JSVAL_IS_OBJECT(v)) {
+ JS_ReportError(cx, "shapeOf: object expected");
+ return JS_FALSE;
+ }
+ return JS_NewNumberValue(cx, ShapeOf_tn(JSVAL_TO_OBJECT(v)), vp);
+}
+
+#ifdef JS_THREADSAFE
+
+static JSBool
+Sleep_fn(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble t_secs;
+ PRUint32 t_ticks;
+ jsrefcount rc;
+
+ if (!JS_ValueToNumber(cx, argc == 0 ? JSVAL_VOID : vp[2], &t_secs))
+ return JS_FALSE;
+
+ if (t_secs < 0 || JSDOUBLE_IS_NaN(t_secs))
+ t_secs = 0;
+
+ rc = JS_SuspendRequest(cx);
+ t_ticks = (PRUint32)(PR_TicksPerSecond() * t_secs);
+ if (PR_Sleep(t_ticks) == PR_SUCCESS)
+ *vp = JSVAL_TRUE;
+ else
+ *vp = JSVAL_FALSE;
+ JS_ResumeRequest(cx, rc);
+ return JS_TRUE;
+}
+
+typedef struct ScatterThreadData ScatterThreadData;
+typedef struct ScatterData ScatterData;
+
+typedef enum ScatterStatus {
+ SCATTER_WAIT,
+ SCATTER_GO,
+ SCATTER_CANCEL
+} ScatterStatus;
+
+struct ScatterData {
+ ScatterThreadData *threads;
+ jsval *results;
+ PRLock *lock;
+ PRCondVar *cvar;
+ ScatterStatus status;
+};
+
+struct ScatterThreadData {
+ jsint index;
+ ScatterData *shared;
+ PRThread *thr;
+ JSContext *cx;
+ jsval fn;
+};
+
+static void
+DoScatteredWork(JSContext *cx, ScatterThreadData *td)
+{
+ jsval *rval = &td->shared->results[td->index];
+
+ if (!JS_CallFunctionValue(cx, NULL, td->fn, 0, NULL, rval)) {
+ *rval = JSVAL_VOID;
+ JS_GetPendingException(cx, rval);
+ JS_ClearPendingException(cx);
+ }
+}
+
+static void
+RunScatterThread(void *arg)
+{
+ ScatterThreadData *td;
+ ScatterStatus st;
+ JSContext *cx;
+
+ td = (ScatterThreadData *)arg;
+ cx = td->cx;
+
+ /* Wait for go signal. */
+ PR_Lock(td->shared->lock);
+ while ((st = td->shared->status) == SCATTER_WAIT)
+ PR_WaitCondVar(td->shared->cvar, PR_INTERVAL_NO_TIMEOUT);
+ PR_Unlock(td->shared->lock);
+
+ if (st == SCATTER_CANCEL)
+ return;
+
+ /* We are go. */
+ JS_SetContextThread(cx);
+ JS_SetThreadStackLimit(cx, 0);
+ JS_BeginRequest(cx);
+ DoScatteredWork(cx, td);
+ JS_EndRequest(cx);
+ JS_ClearContextThread(cx);
+}
+
+/*
+ * scatter(fnArray) - Call each function in `fnArray` without arguments, each
+ * in a different thread. When all threads have finished, return an array: the
+ * return values. Errors are not propagated; if any of the function calls
+ * fails, the corresponding element in the results array gets the exception
+ * object, if any, else (undefined).
+ */
+static JSBool
+Scatter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsuint i;
+ jsuint n; /* number of threads */
+ JSObject *inArr;
+ JSObject *arr;
+ ScatterData sd;
+ JSBool ok;
+ jsrefcount rc;
+
+ if (!gEnableBranchCallback) {
+ /* Enable the branch callback, for periodic scope-sharing. */
+ gEnableBranchCallback = JS_TRUE;
+ JS_SetBranchCallback(cx, my_BranchCallback);
+ JS_ToggleOptions(cx, JSOPTION_NATIVE_BRANCH_CALLBACK);
+ }
+
+ sd.lock = NULL;
+ sd.cvar = NULL;
+ sd.results = NULL;
+ sd.threads = NULL;
+ sd.status = SCATTER_WAIT;
+
+ if (argc == 0 || JSVAL_IS_PRIMITIVE(JS_ARGV(cx, vp)[0])) {
+ JS_ReportError(cx, "the first argument must be an object");
+ goto fail;
+ }
+
+ inArr = JSVAL_TO_OBJECT(JS_ARGV(cx, vp)[0]);
+ ok = JS_GetArrayLength(cx, inArr, &n);
+ if (!ok)
+ goto out;
+ if (n == 0)
+ goto success;
+
+ sd.lock = PR_NewLock();
+ if (!sd.lock)
+ goto fail;
+
+ sd.cvar = PR_NewCondVar(sd.lock);
+ if (!sd.cvar)
+ goto fail;
+
+ sd.results = (jsval *) malloc(n * sizeof(jsval));
+ if (!sd.results)
+ goto fail;
+ for (i = 0; i < n; i++) {
+ sd.results[i] = JSVAL_VOID;
+ ok = JS_AddRoot(cx, &sd.results[i]);
+ if (!ok) {
+ while (i-- > 0)
+ JS_RemoveRoot(cx, &sd.results[i]);
+ free(sd.results);
+ sd.results = NULL;
+ goto fail;
+ }
+ }
+
+ sd.threads = (ScatterThreadData *) malloc(n * sizeof(ScatterThreadData));
+ if (!sd.threads)
+ goto fail;
+ for (i = 0; i < n; i++) {
+ sd.threads[i].index = i;
+ sd.threads[i].shared = &sd;
+ sd.threads[i].thr = NULL;
+ sd.threads[i].cx = NULL;
+ sd.threads[i].fn = JSVAL_NULL;
+
+ ok = JS_AddRoot(cx, &sd.threads[i].fn);
+ if (ok && !JS_GetElement(cx, inArr, (jsint) i, &sd.threads[i].fn)) {
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
+ ok = JS_FALSE;
+ }
+ if (!ok) {
+ while (i-- > 0)
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
+ free(sd.threads);
+ sd.threads = NULL;
+ goto fail;
+ }
+ }
+
+ for (i = 1; i < n; i++) {
+ JSContext *newcx = JS_NewContext(JS_GetRuntime(cx), 8192);
+ if (!newcx)
+ goto fail;
+ JS_SetGlobalObject(newcx, JS_GetGlobalObject(cx));
+ JS_ClearContextThread(newcx);
+ sd.threads[i].cx = newcx;
+ }
+
+ for (i = 1; i < n; i++) {
+ PRThread *t = PR_CreateThread(PR_USER_THREAD,
+ RunScatterThread,
+ &sd.threads[i],
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0);
+ if (!t) {
+ /* Failed to start thread. */
+ PR_Lock(sd.lock);
+ sd.status = SCATTER_CANCEL;
+ PR_NotifyAllCondVar(sd.cvar);
+ PR_Unlock(sd.lock);
+ while (i-- > 1)
+ PR_JoinThread(sd.threads[i].thr);
+ goto fail;
+ }
+
+ sd.threads[i].thr = t;
+ }
+ PR_Lock(sd.lock);
+ sd.status = SCATTER_GO;
+ PR_NotifyAllCondVar(sd.cvar);
+ PR_Unlock(sd.lock);
+
+ DoScatteredWork(cx, &sd.threads[0]);
+
+ rc = JS_SuspendRequest(cx);
+ for (i = 1; i < n; i++) {
+ PR_JoinThread(sd.threads[i].thr);
+ }
+ JS_ResumeRequest(cx, rc);
+
+success:
+ arr = JS_NewArrayObject(cx, n, sd.results);
+ if (!arr)
+ goto fail;
+ *vp = OBJECT_TO_JSVAL(arr);
+ ok = JS_TRUE;
+
+out:
+ if (sd.threads) {
+ JSContext *acx;
+
+ for (i = 0; i < n; i++) {
+ JS_RemoveRoot(cx, &sd.threads[i].fn);
+ acx = sd.threads[i].cx;
+ if (acx) {
+ JS_SetContextThread(acx);
+ JS_DestroyContext(acx);
+ }
+ }
+ free(sd.threads);
+ }
+ if (sd.results) {
+ for (i = 0; i < n; i++)
+ JS_RemoveRoot(cx, &sd.results[i]);
+ free(sd.results);
+ }
+ if (sd.cvar)
+ PR_DestroyCondVar(sd.cvar);
+ if (sd.lock)
+ PR_DestroyLock(sd.lock);
+
+ return ok;
+
+fail:
+ ok = JS_FALSE;
+ goto out;
+}
+
+#endif
+
+JS_DEFINE_TRCINFO_1(Print, (2, (static, JSVAL_FAIL, Print_tn, CONTEXT, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(ShapeOf, (1, (static, INT32, ShapeOf_tn, OBJECT, 0, 0)))
+
+/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
+static JSFunctionSpec shell_functions[] = {
+ JS_FS("version", Version, 0,0,0),
+ JS_FS("options", Options, 0,0,0),
+ JS_FS("load", Load, 1,0,0),
+ JS_FN("readline", ReadLine, 0,0),
+ JS_TN("print", Print, 0,0, Print_trcinfo),
+ JS_FS("help", Help, 0,0,0),
+ JS_FS("quit", Quit, 0,0,0),
+ JS_FN("gc", GC, 0,0),
+ JS_FN("gcparam", GCParameter, 2,0),
+ JS_FN("countHeap", CountHeap, 0,0),
+#ifdef JS_GC_ZEAL
+ JS_FN("gczeal", GCZeal, 1,0),
+#endif
+ JS_FS("trap", Trap, 3,0,0),
+ JS_FS("untrap", Untrap, 2,0,0),
+ JS_FS("line2pc", LineToPC, 0,0,0),
+ JS_FS("pc2line", PCToLine, 0,0,0),
+ JS_FN("stackQuota", StackQuota, 0,0),
+ JS_FS("stringsAreUTF8", StringsAreUTF8, 0,0,0),
+ JS_FS("testUTF8", TestUTF8, 1,0,0),
+ JS_FS("throwError", ThrowError, 0,0,0),
+#ifdef DEBUG
+ JS_FS("dis", Disassemble, 1,0,0),
+ JS_FS("disfile", DisassFile, 1,0,0),
+ JS_FS("dissrc", DisassWithSrc, 1,0,0),
+ JS_FN("dumpHeap", DumpHeap, 0,0),
+ JS_FS("notes", Notes, 1,0,0),
+ JS_FS("tracing", Tracing, 0,0,0),
+ JS_FS("stats", DumpStats, 1,0,0),
+#endif
+#ifdef TEST_CVTARGS
+ JS_FS("cvtargs", ConvertArgs, 0,0,12),
+#endif
+ JS_FN("build", BuildDate, 0,0),
+ JS_FS("clear", Clear, 0,0,0),
+ JS_FN("intern", Intern, 1,0),
+ JS_FS("clone", Clone, 1,0,0),
+ JS_FS("seal", Seal, 1,0,1),
+ JS_FN("getpda", GetPDA, 1,0),
+ JS_FN("getslx", GetSLX, 1,0),
+ JS_FN("toint32", ToInt32, 1,0),
+ JS_FS("evalcx", EvalInContext, 1,0,0),
+ JS_TN("shapeOf", ShapeOf, 1,0, ShapeOf_trcinfo),
+#ifdef MOZ_SHARK
+ JS_FS("startShark", js_StartShark, 0,0,0),
+ JS_FS("stopShark", js_StopShark, 0,0,0),
+ JS_FS("connectShark", js_ConnectShark, 0,0,0),
+ JS_FS("disconnectShark", js_DisconnectShark, 0,0,0),
+#endif
+#ifdef MOZ_CALLGRIND
+ JS_FS("startCallgrind", js_StartCallgrind, 0,0,0),
+ JS_FS("stopCallgrind", js_StopCallgrind, 0,0,0),
+ JS_FS("dumpCallgrind", js_DumpCallgrind, 1,0,0),
+#endif
+#ifdef MOZ_VTUNE
+ JS_FS("startVtune", js_StartVtune, 1,0,0),
+ JS_FS("stopVtune", js_StopVtune, 0,0,0),
+ JS_FS("pauseVtune", js_PauseVtune, 0,0,0),
+ JS_FS("resumeVtune", js_ResumeVtune, 0,0,0),
+#endif
+#ifdef DEBUG_ARRAYS
+ JS_FS("arrayInfo", js_ArrayInfo, 1,0,0),
+#endif
+#ifdef JS_THREADSAFE
+ JS_FN("sleep", Sleep_fn, 1,0),
+ JS_FN("scatter", Scatter, 1,0),
+#endif
+ JS_FS_END
+};
+
+static const char shell_help_header[] =
+"Command Description\n"
+"======= ===========\n";
+
+static const char *const shell_help_messages[] = {
+"version([number]) Get or set JavaScript version number",
+"options([option ...]) Get or toggle JavaScript options",
+"load(['foo.js' ...]) Load files named by string arguments",
+"readline() Read a single line from stdin",
+"print([exp ...]) Evaluate and print expressions",
+"help([name ...]) Display usage and help messages",
+"quit() Quit the shell",
+"gc() Run the garbage collector",
+"gcparam(name, value)\n"
+" Wrapper for JS_SetGCParameter. The name must be either 'maxBytes' or\n"
+" 'maxMallocBytes' and the value must be convertable to a positive uint32",
+"countHeap([start[, kind]])\n"
+" Count the number of live GC things in the heap or things reachable from\n"
+" start when it is given and is not null. kind is either 'all' (default) to\n"
+" count all things or one of 'object', 'double', 'string', 'function',\n"
+" 'qname', 'namespace', 'xml' to count only things of that kind",
+#ifdef JS_GC_ZEAL
+"gczeal(level) How zealous the garbage collector should be",
+#endif
+"trap([fun, [pc,]] exp) Trap bytecode execution",
+"untrap(fun[, pc]) Remove a trap",
+"line2pc([fun,] line) Map line number to PC",
+"pc2line(fun[, pc]) Map PC to line number",
+"stackQuota([number]) Query/set script stack quota",
+"stringsAreUTF8() Check if strings are UTF-8 encoded",
+"testUTF8(mode) Perform UTF-8 tests (modes are 1 to 4)",
+"throwError() Throw an error from JS_ReportError",
+#ifdef DEBUG
+"dis([fun]) Disassemble functions into bytecodes",
+"disfile('foo.js') Disassemble script file into bytecodes",
+"dissrc([fun]) Disassemble functions with source lines",
+"dumpHeap([fileName[, start[, toFind[, maxDepth[, toIgnore]]]]])\n"
+" Interface to JS_DumpHeap with output sent to file",
+"notes([fun]) Show source notes for functions",
+"tracing([toggle]) Turn tracing on or off",
+"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
+#endif
+#ifdef TEST_CVTARGS
+"cvtargs(arg1..., arg12) Test argument formatter",
+#endif
+"build() Show build date and time",
+"clear([obj]) Clear properties of object",
+"intern(str) Internalize str in the atom table",
+"clone(fun[, scope]) Clone function object",
+"seal(obj[, deep]) Seal object, or object graph if deep",
+"getpda(obj) Get the property descriptors for obj",
+"getslx(obj) Get script line extent",
+"toint32(n) Testing hook for JS_ValueToInt32",
+"evalcx(s[, o])\n"
+" Evaluate s in optional sandbox object o\n"
+" if (s == '' && !o) return new o with eager standard classes\n"
+" if (s == 'lazy' && !o) return new o with lazy standard classes",
+"shapeOf(obj) Get the shape of obj (an implementation detail)",
+#ifdef MOZ_SHARK
+"startShark() Start a Shark session.\n"
+" Shark must be running with programatic sampling.",
+"stopShark() Stop a running Shark session.",
+"connectShark() Connect to Shark.\n"
+" The -k switch does this automatically.",
+"disconnectShark() Disconnect from Shark.",
+#endif
+#ifdef MOZ_CALLGRIND
+"startCallgrind() Start callgrind instrumentation.\n",
+"stopCallgrind() Stop callgrind instumentation.",
+"dumpCallgrind([name]) Dump callgrind counters.\n",
+#endif
+#ifdef MOZ_VTUNE
+"startVtune([filename]) Start vtune instrumentation.\n",
+"stopVtune() Stop vtune instumentation.",
+"pauseVtune() Pause vtune collection.\n",
+"resumeVtune() Resume vtune collection.\n",
+#endif
+#ifdef DEBUG_ARRAYS
+"arrayInfo(a1, a2, ...) Report statistics about arrays.",
+#endif
+#ifdef JS_THREADSAFE
+"sleep(dt) Sleep for dt seconds",
+"scatter(fns) Call functions concurrently (ignoring errors)",
+#endif
+};
+
+/* Help messages must match shell functions. */
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
+ JS_ARRAY_LENGTH(shell_functions));
+
+#ifdef DEBUG
+static void
+CheckHelpMessages()
+{
+ const char *const *m;
+ const char *lp;
+
+ /* Each message must begin with "function_name(" prefix. */
+ for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
+ lp = strchr(*m, '(');
+ JS_ASSERT(lp);
+ JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
+ *m, lp - *m) == 0);
+ }
+}
+#else
+# define CheckHelpMessages() ((void) 0)
+#endif
+
+static JSBool
+Help(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i, j;
+ int did_header, did_something;
+ JSType type;
+ JSFunction *fun;
+ JSString *str;
+ const char *bytes;
+
+ fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
+ if (argc == 0) {
+ fputs(shell_help_header, gOutFile);
+ for (i = 0; shell_functions[i].name; i++)
+ fprintf(gOutFile, "%s\n", shell_help_messages[i]);
+ } else {
+ did_header = 0;
+ for (i = 0; i < argc; i++) {
+ did_something = 0;
+ type = JS_TypeOfValue(cx, argv[i]);
+ if (type == JSTYPE_FUNCTION) {
+ fun = JS_ValueToFunction(cx, argv[i]);
+ str = fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
+ } else if (type == JSTYPE_STRING) {
+ str = JSVAL_TO_STRING(argv[i]);
+ } else {
+ str = NULL;
+ }
+ if (str) {
+ bytes = JS_GetStringBytes(str);
+ for (j = 0; shell_functions[j].name; j++) {
+ if (!strcmp(bytes, shell_functions[j].name)) {
+ if (!did_header) {
+ did_header = 1;
+ fputs(shell_help_header, gOutFile);
+ }
+ did_something = 1;
+ fprintf(gOutFile, "%s\n", shell_help_messages[j]);
+ break;
+ }
+ }
+ }
+ if (!did_something) {
+ str = JS_ValueToString(cx, argv[i]);
+ if (!str)
+ return JS_FALSE;
+ fprintf(gErrFile, "Sorry, no help for %s\n",
+ JS_GetStringBytes(str));
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSObject *
+split_setup(JSContext *cx)
+{
+ JSObject *outer, *inner, *arguments;
+
+ outer = split_create_outer(cx);
+ if (!outer)
+ return NULL;
+ JS_SetGlobalObject(cx, outer);
+
+ inner = split_create_inner(cx, outer);
+ if (!inner)
+ return NULL;
+
+ if (!JS_DefineFunctions(cx, inner, shell_functions))
+ return NULL;
+ JS_ClearScope(cx, outer);
+
+ /* Create a dummy arguments object. */
+ arguments = JS_NewArrayObject(cx, 0, NULL);
+ if (!arguments ||
+ !JS_DefineProperty(cx, inner, "arguments", OBJECT_TO_JSVAL(arguments),
+ NULL, NULL, 0)) {
+ return NULL;
+ }
+
+#ifndef LAZY_STANDARD_CLASSES
+ if (!JS_InitStandardClasses(cx, inner))
+ return NULL;
+#endif
+
+ return inner;
+}
+
+/*
+ * Define a JS object called "it". Give it class operations that printf why
+ * they're being called for tutorial purposes.
+ */
+enum its_tinyid {
+ ITS_COLOR, ITS_HEIGHT, ITS_WIDTH, ITS_FUNNY, ITS_ARRAY, ITS_RDONLY
+};
+
+static JSPropertySpec its_props[] = {
+ {"color", ITS_COLOR, JSPROP_ENUMERATE, NULL, NULL},
+ {"height", ITS_HEIGHT, JSPROP_ENUMERATE, NULL, NULL},
+ {"width", ITS_WIDTH, JSPROP_ENUMERATE, NULL, NULL},
+ {"funny", ITS_FUNNY, JSPROP_ENUMERATE, NULL, NULL},
+ {"array", ITS_ARRAY, JSPROP_ENUMERATE, NULL, NULL},
+ {"rdonly", ITS_RDONLY, JSPROP_READONLY, NULL, NULL},
+ {NULL,0,0,NULL,NULL}
+};
+
+static JSBool
+its_item(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ *rval = OBJECT_TO_JSVAL(obj);
+ if (argc != 0)
+ JS_SetCallReturnValue2(cx, argv[0]);
+ return JS_TRUE;
+}
+
+static JSBool
+its_bindMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ char *name;
+ JSObject *method;
+
+ if (!JS_ConvertArguments(cx, argc, argv, "so", &name, &method))
+ return JS_FALSE;
+
+ *rval = OBJECT_TO_JSVAL(method);
+
+ if (JS_TypeOfValue(cx, *rval) != JSTYPE_FUNCTION) {
+ JSString *valstr = JS_ValueToString(cx, *rval);
+ if (valstr) {
+ JS_ReportError(cx, "can't bind method %s to non-callable object %s",
+ name, JS_GetStringBytes(valstr));
+ }
+ return JS_FALSE;
+ }
+
+ if (!JS_DefineProperty(cx, obj, name, *rval, NULL, NULL, JSPROP_ENUMERATE))
+ return JS_FALSE;
+
+ return JS_SetParent(cx, method, obj);
+}
+
+static JSFunctionSpec its_methods[] = {
+ {"item", its_item, 0,0,0},
+ {"bindMethod", its_bindMethod, 2,0,0},
+ {NULL,NULL,0,0,0}
+};
+
+#ifdef JSD_LOWLEVEL_SOURCE
+/*
+ * This facilitates sending source to JSD (the debugger system) in the shell
+ * where the source is loaded using the JSFILE hack in jsscan. The function
+ * below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
+ * A more normal embedding (e.g. mozilla) loads source itself and can send
+ * source directly to JSD without using this hook scheme.
+ */
+static void
+SendSourceToJSDebugger(const char *filename, uintN lineno,
+ jschar *str, size_t length,
+ void **listenerTSData, JSDContext* jsdc)
+{
+ JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
+
+ if (!jsdsrc) {
+ if (!filename)
+ filename = "typein";
+ if (1 == lineno) {
+ jsdsrc = JSD_NewSourceText(jsdc, filename);
+ } else {
+ jsdsrc = JSD_FindSourceForURL(jsdc, filename);
+ if (jsdsrc && JSD_SOURCE_PARTIAL !=
+ JSD_GetSourceStatus(jsdc, jsdsrc)) {
+ jsdsrc = NULL;
+ }
+ }
+ }
+ if (jsdsrc) {
+ jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
+ JSD_SOURCE_PARTIAL);
+ }
+ *listenerTSData = jsdsrc;
+}
+#endif /* JSD_LOWLEVEL_SOURCE */
+
+static JSBool its_noisy; /* whether to be noisy when finalizing it */
+static JSBool its_enum_fail;/* whether to fail when enumerating it */
+
+static JSBool
+its_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "adding its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " initial value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "deleting its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " current value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "getting its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " current value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ char *str;
+ if (its_noisy) {
+ fprintf(gOutFile, "setting its property %s,",
+ JS_GetStringBytes(JS_ValueToString(cx, id)));
+ fprintf(gOutFile, " new value %s\n",
+ JS_GetStringBytes(JS_ValueToString(cx, *vp)));
+ }
+
+ if (!JSVAL_IS_STRING(id))
+ return JS_TRUE;
+
+ str = JS_GetStringBytes(JSVAL_TO_STRING(id));
+ if (!strcmp(str, "noisy"))
+ return JS_ValueToBoolean(cx, *vp, &its_noisy);
+ else if (!strcmp(str, "enum_fail"))
+ return JS_ValueToBoolean(cx, *vp, &its_enum_fail);
+
+ return JS_TRUE;
+}
+
+/*
+ * Its enumerator, implemented using the "new" enumerate API,
+ * see class flags.
+ */
+static JSBool
+its_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSObject *iterator;
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (its_noisy)
+ fprintf(gOutFile, "enumerate its properties\n");
+
+ iterator = JS_NewPropertyIterator(cx, obj);
+ if (!iterator)
+ return JS_FALSE;
+
+ *statep = OBJECT_TO_JSVAL(iterator);
+ if (idp)
+ *idp = JSVAL_ZERO;
+ break;
+
+ case JSENUMERATE_NEXT:
+ if (its_enum_fail) {
+ JS_ReportError(cx, "its enumeration failed");
+ return JS_FALSE;
+ }
+
+ iterator = (JSObject *) JSVAL_TO_OBJECT(*statep);
+ if (!JS_NextProperty(cx, iterator, idp))
+ return JS_FALSE;
+
+ if (!JSVAL_IS_VOID(*idp))
+ break;
+ /* Fall through. */
+
+ case JSENUMERATE_DESTROY:
+ /* Allow our iterator object to be GC'd. */
+ *statep = JSVAL_NULL;
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+its_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ if (its_noisy) {
+ fprintf(gOutFile, "resolving its property %s, flags {%s,%s,%s}\n",
+ JS_GetStringBytes(JS_ValueToString(cx, id)),
+ (flags & JSRESOLVE_QUALIFIED) ? "qualified" : "",
+ (flags & JSRESOLVE_ASSIGNING) ? "assigning" : "",
+ (flags & JSRESOLVE_DETECTING) ? "detecting" : "");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+its_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ if (its_noisy)
+ fprintf(gOutFile, "converting it to %s type\n", JS_GetTypeName(cx, type));
+ return JS_TRUE;
+}
+
+static void
+its_finalize(JSContext *cx, JSObject *obj)
+{
+ if (its_noisy)
+ fprintf(gOutFile, "finalizing it\n");
+}
+
+static JSClass its_class = {
+ "It", JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
+ its_addProperty, its_delProperty, its_getProperty, its_setProperty,
+ (JSEnumerateOp)its_enumerate, (JSResolveOp)its_resolve,
+ its_convert, its_finalize,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSErrorFormatString jsShell_ErrorFormatString[JSErr_Limit] = {
+#define MSG_DEF(name, number, count, exception, format) \
+ { format, count, JSEXN_ERR } ,
+#include "jsshell.msg"
+#undef MSG_DEF
+};
+
+static const JSErrorFormatString *
+my_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
+{
+ if ((errorNumber > 0) && (errorNumber < JSShellErr_Limit))
+ return &jsShell_ErrorFormatString[errorNumber];
+ return NULL;
+}
+
+static void
+my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+{
+ int i, j, k, n;
+ char *prefix, *tmp;
+ const char *ctmp;
+
+ if (!report) {
+ fprintf(gErrFile, "%s\n", message);
+ return;
+ }
+
+ /* Conditionally ignore reported warnings. */
+ if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
+ return;
+
+ prefix = NULL;
+ if (report->filename)
+ prefix = JS_smprintf("%s:", report->filename);
+ if (report->lineno) {
+ tmp = prefix;
+ prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
+ JS_free(cx, tmp);
+ }
+ if (JSREPORT_IS_WARNING(report->flags)) {
+ tmp = prefix;
+ prefix = JS_smprintf("%s%swarning: ",
+ tmp ? tmp : "",
+ JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
+ JS_free(cx, tmp);
+ }
+
+ /* embedded newlines -- argh! */
+ while ((ctmp = strchr(message, '\n')) != 0) {
+ ctmp++;
+ if (prefix)
+ fputs(prefix, gErrFile);
+ fwrite(message, 1, ctmp - message, gErrFile);
+ message = ctmp;
+ }
+
+ /* If there were no filename or lineno, the prefix might be empty */
+ if (prefix)
+ fputs(prefix, gErrFile);
+ fputs(message, gErrFile);
+
+ if (!report->linebuf) {
+ fputc('\n', gErrFile);
+ goto out;
+ }
+
+ /* report->linebuf usually ends with a newline. */
+ n = strlen(report->linebuf);
+ fprintf(gErrFile, ":\n%s%s%s%s",
+ prefix,
+ report->linebuf,
+ (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
+ prefix);
+ n = PTRDIFF(report->tokenptr, report->linebuf, char);
+ for (i = j = 0; i < n; i++) {
+ if (report->linebuf[i] == '\t') {
+ for (k = (j + 8) & ~7; j < k; j++) {
+ fputc('.', gErrFile);
+ }
+ continue;
+ }
+ fputc('.', gErrFile);
+ j++;
+ }
+ fputs("^\n", gErrFile);
+ out:
+ if (!JSREPORT_IS_WARNING(report->flags)) {
+ if (report->errorNumber == JSMSG_OUT_OF_MEMORY) {
+ gExitCode = EXITCODE_OUT_OF_MEMORY;
+ } else {
+ gExitCode = EXITCODE_RUNTIME_ERROR;
+ }
+ }
+ JS_free(cx, prefix);
+}
+
+#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
+static JSBool
+Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFunction *fun;
+ const char *name, **nargv;
+ uintN i, nargc;
+ JSString *str;
+ pid_t pid;
+ int status;
+
+ fun = JS_ValueToFunction(cx, argv[-2]);
+ if (!fun)
+ return JS_FALSE;
+ if (!fun->atom)
+ return JS_TRUE;
+ name = JS_GetStringBytes(ATOM_TO_STRING(fun->atom));
+ nargc = 1 + argc;
+ nargv = JS_malloc(cx, (nargc + 1) * sizeof(char *));
+ if (!nargv)
+ return JS_FALSE;
+ nargv[0] = name;
+ for (i = 1; i < nargc; i++) {
+ str = JS_ValueToString(cx, argv[i-1]);
+ if (!str) {
+ JS_free(cx, nargv);
+ return JS_FALSE;
+ }
+ nargv[i] = JS_GetStringBytes(str);
+ }
+ nargv[nargc] = 0;
+ pid = fork();
+ switch (pid) {
+ case -1:
+ perror("js");
+ break;
+ case 0:
+ (void) execvp(name, (char **)nargv);
+ perror("js");
+ exit(127);
+ default:
+ while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
+ continue;
+ break;
+ }
+ JS_free(cx, nargv);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+global_enumerate(JSContext *cx, JSObject *obj)
+{
+#ifdef LAZY_STANDARD_CLASSES
+ return JS_EnumerateStandardClasses(cx, obj);
+#else
+ return JS_TRUE;
+#endif
+}
+
+static JSBool
+global_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+#ifdef LAZY_STANDARD_CLASSES
+ if ((flags & JSRESOLVE_ASSIGNING) == 0) {
+ JSBool resolved;
+
+ if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
+ return JS_FALSE;
+ if (resolved) {
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+#endif
+
+#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
+ if ((flags & (JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING)) == 0) {
+ /*
+ * Do this expensive hack only for unoptimized Unix builds, which are
+ * not used for benchmarking.
+ */
+ char *path, *comp, *full;
+ const char *name;
+ JSBool ok, found;
+ JSFunction *fun;
+
+ if (!JSVAL_IS_STRING(id))
+ return JS_TRUE;
+ path = getenv("PATH");
+ if (!path)
+ return JS_TRUE;
+ path = JS_strdup(cx, path);
+ if (!path)
+ return JS_FALSE;
+ name = JS_GetStringBytes(JSVAL_TO_STRING(id));
+ ok = JS_TRUE;
+ for (comp = strtok(path, ":"); comp; comp = strtok(NULL, ":")) {
+ if (*comp != '\0') {
+ full = JS_smprintf("%s/%s", comp, name);
+ if (!full) {
+ JS_ReportOutOfMemory(cx);
+ ok = JS_FALSE;
+ break;
+ }
+ } else {
+ full = (char *)name;
+ }
+ found = (access(full, X_OK) == 0);
+ if (*comp != '\0')
+ free(full);
+ if (found) {
+ fun = JS_DefineFunction(cx, obj, name, Exec, 0,
+ JSPROP_ENUMERATE);
+ ok = (fun != NULL);
+ if (ok)
+ *objp = obj;
+ break;
+ }
+ }
+ JS_free(cx, path);
+ return ok;
+ }
+#else
+ return JS_TRUE;
+#endif
+}
+
+JSClass global_class = {
+ "global", JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ global_enumerate, (JSResolveOp) global_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+env_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+/* XXX porting may be easy, but these don't seem to supply setenv by default */
+#if !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS
+ JSString *idstr, *valstr;
+ const char *name, *value;
+ int rv;
+
+ idstr = JS_ValueToString(cx, id);
+ valstr = JS_ValueToString(cx, *vp);
+ if (!idstr || !valstr)
+ return JS_FALSE;
+ name = JS_GetStringBytes(idstr);
+ value = JS_GetStringBytes(valstr);
+#if defined XP_WIN || defined HPUX || defined OSF1 || defined IRIX
+ {
+ char *waste = JS_smprintf("%s=%s", name, value);
+ if (!waste) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ rv = putenv(waste);
+#ifdef XP_WIN
+ /*
+ * HPUX9 at least still has the bad old non-copying putenv.
+ *
+ * Per mail from <s.shanmuganathan@digital.com>, OSF1 also has a putenv
+ * that will crash if you pass it an auto char array (so it must place
+ * its argument directly in the char *environ[] array).
+ */
+ free(waste);
+#endif
+ }
+#else
+ rv = setenv(name, value, 1);
+#endif
+ if (rv < 0) {
+ JS_ReportError(cx, "can't set envariable %s to %s", name, value);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(valstr);
+#endif /* !defined XP_BEOS && !defined XP_OS2 && !defined SOLARIS */
+ return JS_TRUE;
+}
+
+static JSBool
+env_enumerate(JSContext *cx, JSObject *obj)
+{
+ static JSBool reflected;
+ char **evp, *name, *value;
+ JSString *valstr;
+ JSBool ok;
+
+ if (reflected)
+ return JS_TRUE;
+
+ for (evp = (char **)JS_GetPrivate(cx, obj); (name = *evp) != NULL; evp++) {
+ value = strchr(name, '=');
+ if (!value)
+ continue;
+ *value++ = '\0';
+ valstr = JS_NewStringCopyZ(cx, value);
+ if (!valstr) {
+ ok = JS_FALSE;
+ } else {
+ ok = JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
+ NULL, NULL, JSPROP_ENUMERATE);
+ }
+ value[-1] = '=';
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ reflected = JS_TRUE;
+ return JS_TRUE;
+}
+
+static JSBool
+env_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSString *idstr, *valstr;
+ const char *name, *value;
+
+ if (flags & JSRESOLVE_ASSIGNING)
+ return JS_TRUE;
+
+ idstr = JS_ValueToString(cx, id);
+ if (!idstr)
+ return JS_FALSE;
+ name = JS_GetStringBytes(idstr);
+ value = getenv(name);
+ if (value) {
+ valstr = JS_NewStringCopyZ(cx, value);
+ if (!valstr)
+ return JS_FALSE;
+ if (!JS_DefineProperty(cx, obj, name, STRING_TO_JSVAL(valstr),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ return JS_TRUE;
+}
+
+static JSClass env_class = {
+ "environment", JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, env_setProperty,
+ env_enumerate, (JSResolveOp) env_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#ifdef NARCISSUS
+
+static JSBool
+defineProperty(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ jsval value;
+ JSBool dontDelete, readOnly, dontEnum;
+ const jschar *chars;
+ size_t length;
+ uintN attrs;
+
+ dontDelete = readOnly = dontEnum = JS_FALSE;
+ if (!JS_ConvertArguments(cx, argc, argv, "Sv/bbb",
+ &str, &value, &dontDelete, &readOnly, &dontEnum)) {
+ return JS_FALSE;
+ }
+ chars = JS_GetStringChars(str);
+ length = JS_GetStringLength(str);
+ attrs = dontEnum ? 0 : JSPROP_ENUMERATE;
+ if (dontDelete)
+ attrs |= JSPROP_PERMANENT;
+ if (readOnly)
+ attrs |= JSPROP_READONLY;
+ return JS_DefineUCProperty(cx, obj, chars, length, value, NULL, NULL,
+ attrs);
+}
+
+static JSBool
+Evaluate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ /* function evaluate(source, filename, lineno) { ... } */
+ JSString *source;
+ const char *filename = "";
+ jsuint lineno = 0;
+ uint32 oldopts;
+ JSBool ok;
+
+ if (argc == 0) {
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ if (!JS_ConvertArguments(cx, argc, argv, "S/su",
+ &source, &filename, &lineno)) {
+ return JS_FALSE;
+ }
+
+ oldopts = JS_GetOptions(cx);
+ JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
+ ok = JS_EvaluateUCScript(cx, obj, JS_GetStringChars(source),
+ JS_GetStringLength(source), filename,
+ lineno, rval);
+ JS_SetOptions(cx, oldopts);
+
+ return ok;
+}
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/*
+ * Returns a JS_malloc'd string (that the caller needs to JS_free)
+ * containing the directory (non-leaf) part of |from| prepended to |leaf|.
+ * If |from| is empty or a leaf, MakeAbsolutePathname returns a copy of leaf.
+ * Returns NULL to indicate an error.
+ */
+static char *
+MakeAbsolutePathname(JSContext *cx, const char *from, const char *leaf)
+{
+ size_t dirlen;
+ char *dir;
+ const char *slash = NULL, *cp;
+
+ cp = from;
+ while (*cp) {
+ if (*cp == '/'
+#ifdef XP_WIN
+ || *cp == '\\'
+#endif
+ ) {
+ slash = cp;
+ }
+
+ ++cp;
+ }
+
+ if (!slash) {
+ /* We were given a leaf or |from| was empty. */
+ return JS_strdup(cx, leaf);
+ }
+
+ /* Else, we were given a real pathname, return that + the leaf. */
+ dirlen = slash - from + 1;
+ dir = (char*) JS_malloc(cx, dirlen + strlen(leaf) + 1);
+ if (!dir)
+ return NULL;
+
+ strncpy(dir, from, dirlen);
+ strcpy(dir + dirlen, leaf); /* Note: we can't use strcat here. */
+
+ return dir;
+}
+
+static JSBool
+snarf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ const char *filename;
+ char *pathname;
+ JSStackFrame *fp;
+ JSBool ok;
+ off_t cc, len;
+ char *buf;
+ FILE *file;
+
+ str = JS_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ filename = JS_GetStringBytes(str);
+
+ /* Get the currently executing script's name. */
+ fp = JS_GetScriptedCaller(cx, NULL);
+ JS_ASSERT(fp && fp->script->filename);
+ pathname = MakeAbsolutePathname(cx, fp->script->filename, filename);
+ if (!pathname)
+ return JS_FALSE;
+
+ ok = JS_FALSE;
+ len = 0;
+ buf = NULL;
+ file = fopen(pathname, "rb");
+ if (!file) {
+ JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
+ } else {
+ if (fseek(file, 0, SEEK_END) == EOF) {
+ JS_ReportError(cx, "can't seek end of %s", pathname);
+ } else {
+ len = ftell(file);
+ if (len == -1 || fseek(file, 0, SEEK_SET) == EOF) {
+ JS_ReportError(cx, "can't seek start of %s", pathname);
+ } else {
+ buf = (char*) JS_malloc(cx, len + 1);
+ if (buf) {
+ cc = fread(buf, 1, len, file);
+ if (cc != len) {
+ JS_free(cx, buf);
+ JS_ReportError(cx, "can't read %s: %s", pathname,
+ (cc < 0) ? strerror(errno)
+ : "short read");
+ } else {
+ len = (size_t)cc;
+ ok = JS_TRUE;
+ }
+ }
+ }
+ }
+ fclose(file);
+ }
+ JS_free(cx, pathname);
+ if (!ok) {
+ JS_free(cx, buf);
+ return ok;
+ }
+
+ buf[len] = '\0';
+ str = JS_NewString(cx, buf, len);
+ if (!str) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#endif /* NARCISSUS */
+
+static JSBool
+ContextCallback(JSContext *cx, uintN contextOp)
+{
+ if (contextOp == JSCONTEXT_NEW) {
+ JS_SetErrorReporter(cx, my_ErrorReporter);
+ JS_SetVersion(cx, JSVERSION_LATEST);
+ SetContextOptions(cx);
+ }
+ return JS_TRUE;
+}
+
+int
+main(int argc, char **argv, char **envp)
+{
+ int stackDummy;
+ JSRuntime *rt;
+ JSContext *cx;
+ JSObject *glob, *it, *envobj;
+ int result;
+#ifdef LIVECONNECT
+ JavaVM *java_vm = NULL;
+#endif
+#ifdef JSDEBUGGER
+ JSDContext *jsdc;
+#ifdef JSDEBUGGER_JAVA_UI
+ JNIEnv *java_env;
+ JSDJContext *jsdjc;
+#endif
+#ifdef JSDEBUGGER_C_UI
+ JSBool jsdbc;
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+ CheckHelpMessages();
+ setlocale(LC_ALL, "");
+
+ gStackBase = (jsuword)&stackDummy;
+
+#ifdef XP_OS2
+ /* these streams are normally line buffered on OS/2 and need a \n, *
+ * so we need to unbuffer then to get a reasonable prompt */
+ setbuf(stdout,0);
+ setbuf(stderr,0);
+#endif
+
+ gErrFile = stderr;
+ gOutFile = stdout;
+
+ argc--;
+ argv++;
+
+ rt = JS_NewRuntime(64L * 1024L * 1024L);
+ if (!rt)
+ return 1;
+ JS_SetContextCallback(rt, ContextCallback);
+
+ cx = JS_NewContext(rt, gStackChunkSize);
+ if (!cx)
+ return 1;
+
+#ifdef JS_THREADSAFE
+ JS_BeginRequest(cx);
+#endif
+
+ glob = JS_NewObject(cx, &global_class, NULL, NULL);
+ if (!glob)
+ return 1;
+#ifdef LAZY_STANDARD_CLASSES
+ JS_SetGlobalObject(cx, glob);
+#else
+ if (!JS_InitStandardClasses(cx, glob))
+ return 1;
+#endif
+ if (!JS_DefineFunctions(cx, glob, shell_functions))
+ return 1;
+
+ it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
+ if (!it)
+ return 1;
+ if (!JS_DefineProperties(cx, it, its_props))
+ return 1;
+ if (!JS_DefineFunctions(cx, it, its_methods))
+ return 1;
+
+#ifdef JSDEBUGGER
+ /*
+ * XXX A command line option to enable debugging (or not) would be good
+ */
+ jsdc = JSD_DebuggerOnForUser(rt, NULL, NULL);
+ if (!jsdc)
+ return 1;
+ JSD_JSContextInUse(jsdc, cx);
+#ifdef JSD_LOWLEVEL_SOURCE
+ JS_SetSourceHandler(rt, SendSourceToJSDebugger, jsdc);
+#endif /* JSD_LOWLEVEL_SOURCE */
+#ifdef JSDEBUGGER_JAVA_UI
+ jsdjc = JSDJ_CreateContext();
+ if (! jsdjc)
+ return 1;
+ JSDJ_SetJSDContext(jsdjc, jsdc);
+ java_env = JSDJ_CreateJavaVMAndStartDebugger(jsdjc);
+#ifdef LIVECONNECT
+ if (java_env)
+ (*java_env)->GetJavaVM(java_env, &java_vm);
+#endif
+ /*
+ * XXX This would be the place to wait for the debugger to start.
+ * Waiting would be nice in general, but especially when a js file
+ * is passed on the cmd line.
+ */
+#endif /* JSDEBUGGER_JAVA_UI */
+#ifdef JSDEBUGGER_C_UI
+ jsdbc = JSDB_InitDebugger(rt, jsdc, 0);
+#endif /* JSDEBUGGER_C_UI */
+#endif /* JSDEBUGGER */
+
+#ifdef LIVECONNECT
+ if (!JSJ_SimpleInit(cx, glob, java_vm, getenv("CLASSPATH")))
+ return 1;
+#endif
+
+ envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
+ if (!envobj || !JS_SetPrivate(cx, envobj, envp))
+ return 1;
+
+#ifdef NARCISSUS
+ {
+ jsval v;
+ static const char Object_prototype[] = "Object.prototype";
+
+ if (!JS_DefineFunction(cx, glob, "snarf", snarf, 1, 0))
+ return 1;
+ if (!JS_DefineFunction(cx, glob, "evaluate", Evaluate, 3, 0))
+ return 1;
+
+ if (!JS_EvaluateScript(cx, glob,
+ Object_prototype, sizeof Object_prototype - 1,
+ NULL, 0, &v)) {
+ return 1;
+ }
+ if (!JS_DefineFunction(cx, JSVAL_TO_OBJECT(v), "__defineProperty__",
+ defineProperty, 5, 0)) {
+ return 1;
+ }
+ }
+#endif
+
+ result = ProcessArgs(cx, glob, argv, argc);
+
+#ifdef JSDEBUGGER
+ if (jsdc) {
+#ifdef JSDEBUGGER_C_UI
+ if (jsdbc)
+ JSDB_TermDebugger(jsdc);
+#endif /* JSDEBUGGER_C_UI */
+ JSD_DebuggerOff(jsdc);
+ }
+#endif /* JSDEBUGGER */
+
+#ifdef JS_THREADSAFE
+ JS_EndRequest(cx);
+#endif
+
+ JS_DestroyContext(cx);
+ JS_DestroyRuntime(rt);
+ JS_ShutDown();
+ return result;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js.mdp b/tools/node_modules/expresso/deps/jscoverage/js/js.mdp
new file mode 100644
index 0000000..8da64fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js.mdp
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js.msg b/tools/node_modules/expresso/deps/jscoverage/js/js.msg
new file mode 100644
index 0000000..f3a711b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js.msg
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This is the JavaScript error message file.
+ *
+ * The format for each JS error message is:
+ *
+ * MSG_DEF(<SYMBOLIC_NAME>, <ERROR_NUMBER>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
+ * <FORMAT_STRING>)
+ *
+ * where ;
+ * <SYMBOLIC_NAME> is a legal C identifer that will be used in the
+ * JS engine source.
+ *
+ * <ERROR_NUMBER> is an unique integral value identifying this error.
+ *
+ * <ARGUMENT_COUNT> is an integer literal specifying the total number of
+ * replaceable arguments in the following format string.
+ *
+ * <EXCEPTION_NAME> is an exception index from the enum in jsexn.c;
+ * JSEXN_NONE for none. The given exception index will be raised by the
+ * engine when the corresponding error occurs.
+ *
+ * <FORMAT_STRING> is a string literal, optionally containing sequences
+ * {X} where X is an integer representing the argument number that will
+ * be replaced with a string value when the error is reported.
+ *
+ * e.g.
+ *
+ * MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2,
+ * "{0} is not a member of the {1} family")
+ *
+ * can be used:
+ *
+ * JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
+ *
+ * to report:
+ *
+ * "Rhino is not a member of the Monkey family"
+ *
+ * Before adding a new MSG_DEF at the end, look for JSMSG_UNUSED<n> free
+ * index placeholders in the middle of the list.
+ */
+
+MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined")
+MSG_DEF(JSMSG_INACTIVE, 2, 0, JSEXN_INTERNALERR, "nothing active on context")
+MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}")
+MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_INTERNALERR, "invalid format character {0}")
+MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_TYPEERR, "unknown type {0}")
+MSG_DEF(JSMSG_ALLOC_OVERFLOW, 6, 0, JSEXN_INTERNALERR, "allocation size overflow")
+MSG_DEF(JSMSG_CANT_UNLOCK, 7, 0, JSEXN_INTERNALERR, "can't unlock memory")
+MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}")
+MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_TYPEERR, "{0} has no constructor")
+MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_TYPEERR, "can't alias {0} to {1} in class {2}")
+MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 11, 1, JSEXN_TYPEERR, "{0} is not a scripted function")
+MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument")
+MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}")
+MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals")
+MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}")
+MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}")
+MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_INTERNALERR, "{0} too large")
+MSG_DEF(JSMSG_TOO_MANY_LOCAL_ROOTS, 18, 0, JSEXN_ERR, "out of local root space")
+MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_ERR, "{0} is read-only")
+MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter")
+MSG_DEF(JSMSG_BAD_ITERATOR, 21, 3, JSEXN_TYPEERR, "{0} has invalid {1} value {2}")
+MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_TYPEERR, "{0} is not a function")
+MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_TYPEERR, "{0} is not a constructor")
+MSG_DEF(JSMSG_SCRIPT_STACK_QUOTA, 24, 0, JSEXN_INTERNALERR, "script stack space quota is exhausted")
+MSG_DEF(JSMSG_TOO_DEEP, 25, 1, JSEXN_INTERNALERR, "{0} nested too deeply")
+MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_INTERNALERR, "too much recursion")
+MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}")
+MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_TYPEERR, "invalid new expression result {0}")
+MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_ERR, "invalid sharp variable definition #{0}=")
+MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_ERR, "invalid sharp variable use #{0}#")
+MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}")
+MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
+MSG_DEF(JSMSG_BAD_RADIX, 33, 1, JSEXN_ERR, "illegal radix {0}")
+MSG_DEF(JSMSG_PAREN_BEFORE_LET, 34, 0, JSEXN_SYNTAXERR, "missing ( before let head")
+MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_ERR, "can't convert {0} to an integer")
+MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_ERR, "cyclic {0} value")
+MSG_DEF(JSMSG_COMPILE_EXECED_SCRIPT, 37, 0, JSEXN_TYPEERR, "cannot compile over a script that is currently executing")
+MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_TYPEERR, "can't convert {0} to {1}")
+MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TYPEERR, "{0} has no properties")
+MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_TYPEERR, "can't find class id {0}")
+MSG_DEF(JSMSG_CANT_XDR_CLASS, 41, 1, JSEXN_TYPEERR, "can't XDR class {0}")
+MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
+MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}")
+MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments")
+MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments")
+MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 1, JSEXN_SYNTAXERR, "invalid quantifier {0}")
+MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}")
+MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}")
+MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum")
+MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 50, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration")
+MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 51, 0, JSEXN_SYNTAXERR, "invalid destructuring assignment operator")
+MSG_DEF(JSMSG_PAREN_AFTER_LET, 52, 0, JSEXN_SYNTAXERR, "missing ) after let head")
+MSG_DEF(JSMSG_CURLY_AFTER_LET, 53, 0, JSEXN_SYNTAXERR, "missing } after let block")
+MSG_DEF(JSMSG_MISSING_PAREN, 54, 0, JSEXN_SYNTAXERR, "unterminated parenthetical")
+MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_SYNTAXERR, "unterminated character class {0}")
+MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression")
+MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class")
+MSG_DEF(JSMSG_BAD_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
+MSG_DEF(JSMSG_NO_INPUT, 59, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}")
+MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
+MSG_DEF(JSMSG_BAD_STRING_MASK, 61, 1, JSEXN_ERR, "invalid string escape mask {0}")
+MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
+MSG_DEF(JSMSG_END_OF_DATA, 63, 0, JSEXN_INTERNALERR, "unexpected end of data")
+MSG_DEF(JSMSG_SEEK_BEYOND_START, 64, 0, JSEXN_INTERNALERR, "illegal seek beyond start")
+MSG_DEF(JSMSG_SEEK_BEYOND_END, 65, 0, JSEXN_INTERNALERR, "illegal seek beyond end")
+MSG_DEF(JSMSG_END_SEEK, 66, 0, JSEXN_INTERNALERR, "illegal end-based seek")
+MSG_DEF(JSMSG_WHITHER_WHENCE, 67, 1, JSEXN_INTERNALERR, "unknown seek whence: {0}")
+MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
+MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
+MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
+MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
+MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body")
+MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body")
+MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition")
+MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition")
+MSG_DEF(JSMSG_UNUSED76, 76, 0, JSEXN_NONE, "unused76")
+MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator")
+MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression")
+MSG_DEF(JSMSG_UNUSED79, 79, 0, JSEXN_NONE, "unused79")
+MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
+MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
+MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body")
+MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label")
+MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
+MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for")
+MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
+MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
+MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
+MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block")
+MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block")
+MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch")
+MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch")
+MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch")
+MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block")
+MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block")
+MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block")
+MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block")
+MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try")
+MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
+MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
+MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement")
+MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name")
+MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression")
+MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list")
+MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list")
+MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id")
+MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list")
+MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
+MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement")
+MSG_DEF(JSMSG_NO_RETURN_VALUE, 110, 1, JSEXN_TYPEERR, "function {0} does not always return a value")
+MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_TYPEERR, "duplicate formal argument {0}")
+MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 1, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?{0}")
+MSG_DEF(JSMSG_UNUSED113, 113, 0, JSEXN_NONE, "unused113")
+MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default")
+MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases")
+MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement")
+MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
+MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_SYNTAXERR, "catch after unconditional catch")
+MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try")
+MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try")
+MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found")
+MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch")
+MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "continue must be inside loop")
+MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 124, 1, JSEXN_SYNTAXERR, "{0} not in function")
+MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label")
+MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label")
+MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_TYPEERR, "variable {0} redeclares argument")
+MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization")
+MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side")
+MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
+MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id")
+MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
+MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
+MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition")
+MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object")
+MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent")
+MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory")
+MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal")
+MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
+MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment")
+MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
+MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 142, 0, JSEXN_SYNTAXERR, "invalid flag after regular expression")
+MSG_DEF(JSMSG_SHARPVAR_TOO_BIG, 143, 0, JSEXN_SYNTAXERR, "overlarge sharp variable number")
+MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character")
+MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
+MSG_DEF(JSMSG_BAD_INDIRECT_CALL, 146, 1, JSEXN_EVALERR, "function {0} must be called directly, and not by way of a function of another name")
+MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_INTERNALERR, "uncaught exception: {0}")
+MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference")
+MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses")
+MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range")
+MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_SYNTAXERR, "invalid {0} usage")
+MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length")
+MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}")
+MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array")
+MSG_DEF(JSMSG_REDECLARED_VAR, 155, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}")
+MSG_DEF(JSMSG_UNDECLARED_VAR, 156, 1, JSEXN_TYPEERR, "assignment to undeclared variable {0}")
+MSG_DEF(JSMSG_ANON_NO_RETURN_VALUE, 157, 0, JSEXN_TYPEERR, "anonymous function does not always return a value")
+MSG_DEF(JSMSG_DEPRECATED_USAGE, 158, 1, JSEXN_REFERENCEERR, "deprecated {0} usage")
+MSG_DEF(JSMSG_BAD_URI, 159, 0, JSEXN_URIERR, "malformed URI sequence")
+MSG_DEF(JSMSG_GETTER_ONLY, 160, 0, JSEXN_TYPEERR, "setting a property that has only a getter")
+MSG_DEF(JSMSG_TRAILING_COMMA, 161, 0, JSEXN_SYNTAXERR, "trailing comma is not legal in ECMA-262 object initializers")
+MSG_DEF(JSMSG_UNDEFINED_PROP, 162, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}")
+MSG_DEF(JSMSG_USELESS_EXPR, 163, 0, JSEXN_TYPEERR, "useless expression")
+MSG_DEF(JSMSG_REDECLARED_PARAM, 164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
+MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
+MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 166, 0, JSEXN_RANGEERR, "reserved slot index out of range")
+MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals")
+MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 168, 1, JSEXN_ERR, "can't seal {0} objects")
+MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 169, 0, JSEXN_SYNTAXERR, "too many catch variables")
+MSG_DEF(JSMSG_BAD_XML_MARKUP, 170, 0, JSEXN_SYNTAXERR, "invalid XML markup")
+MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML character")
+MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace")
+MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name")
+MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression")
+MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 1, JSEXN_TYPEERR, "already executing generator {0}")
+MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression")
+MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}")
+MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}")
+MSG_DEF(JSMSG_BAD_XML_NAME, 179, 1, JSEXN_TYPEERR, "invalid XML name {0}")
+MSG_DEF(JSMSG_BAD_XML_CONVERSION, 180, 1, JSEXN_TYPEERR, "can't convert {0} to XML")
+MSG_DEF(JSMSG_BAD_XMLLIST_CONVERSION, 181, 1, JSEXN_TYPEERR, "can't convert {0} to XMLList")
+MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator")
+MSG_DEF(JSMSG_NO_ASSIGN_IN_XML_ATTR, 183, 0, JSEXN_SYNTAXERR, "missing = in XML attribute")
+MSG_DEF(JSMSG_BAD_XML_ATTR_VALUE, 184, 0, JSEXN_SYNTAXERR, "invalid XML attribute value")
+MSG_DEF(JSMSG_XML_TAG_NAME_MISMATCH, 185, 1, JSEXN_SYNTAXERR, "XML tag name mismatch (expected {0})")
+MSG_DEF(JSMSG_BAD_XML_TAG_SYNTAX, 186, 0, JSEXN_SYNTAXERR, "invalid XML tag syntax")
+MSG_DEF(JSMSG_BAD_XML_LIST_SYNTAX, 187, 0, JSEXN_SYNTAXERR, "invalid XML list syntax")
+MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
+MSG_DEF(JSMSG_CANT_SET_XML_ATTRS, 189, 0, JSEXN_INTERNALERR, "can't set XML property attributes")
+MSG_DEF(JSMSG_END_OF_XML_SOURCE, 190, 0, JSEXN_SYNTAXERR, "unexpected end of XML source")
+MSG_DEF(JSMSG_END_OF_XML_ENTITY, 191, 0, JSEXN_SYNTAXERR, "unexpected end of XML entity")
+MSG_DEF(JSMSG_BAD_XML_QNAME, 192, 0, JSEXN_SYNTAXERR, "invalid XML qualified name")
+MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop")
+MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList")
+MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}")
+MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}")
+MSG_DEF(JSMSG_UNDEFINED_XML_NAME, 197, 1, JSEXN_REFERENCEERR, "reference to undefined XML name {0}")
+MSG_DEF(JSMSG_DUPLICATE_XML_ATTR, 198, 1, JSEXN_TYPEERR, "duplicate XML attribute {0}")
+MSG_DEF(JSMSG_TOO_MANY_LOCALS, 199, 0, JSEXN_SYNTAXERR, "too many local variables")
+MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 200, 0, JSEXN_INTERNALERR, "array initialiser too large")
+MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 201, 0, JSEXN_INTERNALERR, "regular expression too complex")
+MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 202, 0, JSEXN_INTERNALERR, "buffer too small")
+MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 203, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
+MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
+MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
+MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was called")
+MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
+MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
+MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
+MSG_DEF(JSMSG_NAME_AFTER_FOR_PAREN, 210, 0, JSEXN_SYNTAXERR, "missing name after for (")
+MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing in after for")
+MSG_DEF(JSMSG_BAD_ITERATOR_RETURN, 212, 2, JSEXN_TYPEERR, "{0}.{1} returned a primitive value")
+MSG_DEF(JSMSG_KEYWORD_NOT_NS, 213, 0, JSEXN_SYNTAXERR, "keyword is used as namespace")
+MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
+MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized")
+MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
+MSG_DEF(JSMSG_NON_XML_FILTER, 217, 1, JSEXN_TYPEERR, "XML filter is applied to non-XML value {0}")
+MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 218, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
+MSG_DEF(JSMSG_NON_LIST_XML_METHOD, 219, 2, JSEXN_TYPEERR, "cannot call {0} method on an XML list with {1} elements")
+MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_SYNTAXERR, "invalid delete operand")
+MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
+MSG_DEF(JSMSG_NULL_OR_UNDEFINED, 222, 2, JSEXN_TYPEERR, "{0} is {1}")
+MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
+MSG_DEF(JSMSG_BAD_OBJECT_INIT, 224, 0, JSEXN_SYNTAXERR, "invalid object initializer")
+MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 225, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties")
+MSG_DEF(JSMSG_EVAL_ARITY, 226, 0, JSEXN_TYPEERR, "eval accepts only one parameter")
+MSG_DEF(JSMSG_MISSING_FUN_ARG, 227, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/js3240.rc b/tools/node_modules/expresso/deps/jscoverage/js/js3240.rc
new file mode 100644
index 0000000..1a9f62c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/js3240.rc
@@ -0,0 +1,79 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winver.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 4,0,0,0
+ PRODUCTVERSION 4,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x10004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "Netscape Communications Corporation\0"
+ VALUE "FileDescription", "Netscape 32-bit JavaScript Module\0"
+ VALUE "FileVersion", "4.0\0"
+ VALUE "InternalName", "JS3240\0"
+ VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0"
+ VALUE "LegalTrademarks", "Netscape, Mozilla\0"
+ VALUE "OriginalFilename", "js3240.dll\0"
+ VALUE "ProductName", "NETSCAPE\0"
+ VALUE "ProductVersion", "4.0\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""winver.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+///////////////////////////////////////////////////////////////////////////// \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def b/tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def
new file mode 100644
index 0000000..8f27d64
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsOS240.def
@@ -0,0 +1,654 @@
+; ***** BEGIN LICENSE BLOCK *****
+; Version: MPL 1.1/GPL 2.0/LGPL 2.1
+;
+; The contents of this file are subject to the Mozilla Public License Version
+; 1.1 (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.mozilla.org/MPL/
+;
+; Software distributed under the License is distributed on an "AS IS" basis,
+; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+; for the specific language governing rights and limitations under the
+; License.
+;
+; The Original Code is Mozilla Communicator client code, released
+; March 31, 1998.
+;
+; The Initial Developer of the Original Code is
+; Netscape Communications Corporation.
+; Portions created by the Initial Developer are Copyright (C) 1998
+; the Initial Developer. All Rights Reserved.
+;
+; Contributor(s):
+;
+; Alternatively, the contents of this file may be used under the terms of
+; either of the GNU General Public License Version 2 or later (the "GPL"),
+; or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+; in which case the provisions of the GPL or the LGPL are applicable instead
+; of those above. If you wish to allow use of your version of this file only
+; under the terms of either the GPL or the LGPL, and not to allow others to
+; use your version of this file under the terms of the MPL, indicate your
+; decision by deleting the provisions above and replace them with the notice
+; and other provisions required by the GPL or the LGPL. If you do not delete
+; the provisions above, a recipient may use your version of this file under
+; the terms of any one of the MPL, the GPL or the LGPL.
+;
+; ***** END LICENSE BLOCK *****
+
+LIBRARY JS3240 INITINSTANCE TERMINSTANCE
+PROTMODE
+
+DESCRIPTION 'Netscape OS/2 JavaScript Library'
+
+
+CODE LOADONCALL MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE NONSHARED
+
+
+EXPORTS
+;====================== win16 exports these at least... ===========
+; JS_Init = JS_Init @2
+; JS_Finish = JS_Finish @3
+; JS_GetNaNValue
+; JS_GetNegativeInfinityValue
+; JS_GetPositiveInfinityValue
+; JS_GetEmptyStringValue
+; JS_ConvertValue
+; JS_ValueToObject
+; JS_ValueToFunction
+; JS_ValueToString
+; JS_ValueToNumber
+; JS_ValueToBoolean
+; JS_TypeOfValue
+; JS_GetTypeName
+; JS_Lock
+; JS_Unlock
+; JS_NewContext
+; JS_DestroyContext
+; JS_ContextIterator
+; JS_GetGlobalObject
+; JS_SetGlobalObject
+; JS_InitStandardClasses
+;; JS_GetStaticLink
+; JS_malloc
+; JS_realloc
+; JS_free
+; JS_strdup
+; JS_NewDouble
+; JS_NewDoubleValue
+; JS_AddRoot
+; JS_RemoveRoot
+; JS_LockGCThing
+; JS_UnlockGCThing
+; JS_GC
+; JS_PropertyStub
+; JS_EnumerateStub
+; JS_ResolveStub
+; JS_ConvertStub
+; JS_FinalizeStub
+; JS_InitClass
+; JS_GetClass
+; JS_InstanceOf
+; JS_GetPrivate
+; JS_SetPrivate
+; JS_GetInstancePrivate
+; JS_GetPrototype
+; JS_GetParent
+; JS_SetParent
+; JS_GetConstructor
+; JS_NewObject
+; JS_DefineObject
+; JS_DefineConstDoubles
+; JS_DefineProperties
+; JS_DefineProperty
+; JS_DefinePropertyWithTinyId
+; JS_AliasProperty
+; JS_LookupProperty
+; JS_GetProperty
+; JS_SetProperty
+; JS_DeleteProperty
+; JS_NewArrayObject
+; JS_DefineElement
+; JS_AliasElement
+; JS_LookupElement
+; JS_GetElement
+; JS_SetElement
+; JS_DeleteElement
+; JS_ClearScope
+; JS_NewFunction
+; JS_GetFunctionObject
+; JS_GetFunctionName
+; JS_DefineFunctions
+; JS_DefineFunction
+; JS_CompileScript
+; JS_DestroyScript
+; JS_CompileFunction
+; JS_DecompileScript
+; JS_DecompileFunction
+; JS_DecompileFunctionBody
+; JS_ExecuteScript
+; JS_EvaluateScript
+; JS_CallFunction
+; JS_CallFunctionName
+; JS_CallFunctionValue
+; JS_SetBranchCallback
+; JS_IsRunning
+; JS_IsConstructing
+; JS_SetCallReturnValue2
+; JS_NewString
+; JS_NewStringCopyN
+; JS_NewStringCopyZ
+; JS_InternString
+; JS_GetStringBytes
+; JS_GetStringLength
+; JS_CompareStrings
+; JS_ReportError
+; JS_ReportOutOfMemory
+; JS_SetErrorReporter
+; JS_NewRegExpObject
+; JS_SetRegExpInput
+; JS_ClearRegExpStatics
+;=================================================
+
+
+;00001:jsstr (OFFSET:0x00002e17, SIZE:0x0000ae17):
+; - Public Definitions:
+; js_EmptySubString
+; js_CompareStrings
+; js_HashString
+; js_ValueToString
+; js_StringToObject
+; js_FinalizeString
+; js_NewStringCopyZ
+; js_NewString
+; js_InitStringClass
+; js_NewStringCopyN
+; js_BoyerMooreHorspool
+;
+;
+;00002:jsscript (OFFSET:0x0000dc2e, SIZE:0x00003abb):
+; - Public Definitions:
+; js_LineNumberToPC
+; js_PCToLineNumber
+; js_GetSrcNote
+; js_DestroyScript
+; js_NewScript
+;
+;
+;00003:jsscope (OFFSET:0x000116e9, SIZE:0x00004f82):
+; - Public Definitions:
+; js_hash_scope_ops
+; js_list_scope_ops
+; js_DestroyProperty
+; js_NewProperty
+; js_IdToValue
+; js_HashValue
+; js_DestroyScope
+; js_MutateScope
+; js_DropScope
+; js_HoldScope
+; js_NewScope
+; js_GetMutableScope
+; js_HoldProperty
+; js_DropProperty
+;
+;
+;00004:jsscan (OFFSET:0x0001666b, SIZE:0x00008890):
+; - Public Definitions:
+; js_MatchToken
+; js_FlushNewlines
+; js_PeekTokenSameLine
+; js_UngetToken
+; js_GetToken
+; js_PeekToken
+; js_ReportCompileError
+ js_CloseTokenStream
+ js_NewBufferTokenStream
+; js_NewTokenStream
+; js_InitScanner
+;
+;
+;00005:jsregexp (OFFSET:0x0001eefb, SIZE:0x0000eee4):
+; - Public Definitions:
+; js_RegExpClass
+; reopsize
+; js_NewRegExpObject
+; js_InitRegExpClass
+; js_FreeRegExpStatics
+; js_InitRegExpStatics
+; js_ExecuteRegExp
+; js_NewRegExpOpt
+; js_DestroyRegExp
+; js_NewRegExp
+;
+;
+;00006:jsparse (OFFSET:0x0002dddf, SIZE:0x00010b71):
+; - Public Definitions:
+; js_ParseFunctionBody
+ js_Parse
+;
+;
+;00007:jsopcode (OFFSET:0x0003e950, SIZE:0x0000d362):
+; - Public Definitions:
+; js_EscapeMap
+; js_NumCodeSpecs
+; js_CodeSpec
+; js_incop_str
+; js_true_str
+; js_false_str
+; js_this_str
+; js_null_str
+; js_void_str
+; js_typeof_str
+; js_delete_str
+; js_new_str
+; js_ValueToSource
+; js_DecompileScript
+; js_DecompileCode
+; js_DecompileFunction
+; js_puts
+; js_printf
+; js_GetPrinterOutput
+; js_DestroyPrinter
+; js_NewPrinter
+; js_EscapeString
+; js_Disassemble1
+; js_Disassemble
+;
+;00008:jsobj (OFFSET:0x0004bcb2, SIZE:0x000090a4):
+; - Public Definitions:
+; js_WithClass
+; js_ObjectClass
+; js_TryValueOf
+; js_ValueToNonNullObject
+; js_TryMethod
+; js_ObjectToString
+; js_SetClassPrototype
+; js_DeleteProperty2
+; js_DeleteProperty
+; js_SetProperty
+; js_GetProperty
+; js_FindVariableScope
+; js_FindVariable
+; js_FindProperty
+; js_LookupProperty
+; js_DefineProperty
+; js_FreeSlot
+; js_AllocSlot
+; js_FinalizeObject
+; js_GetClassPrototype
+; js_NewObject
+; js_InitObjectClass
+; js_ValueToObject
+; js_obj_toString
+; js_SetSlot
+; js_GetSlot
+;
+;
+;00009:jsnum (OFFSET:0x00054d56, SIZE:0x00004f29):
+; - Public Definitions:
+; js_ValueToInt32
+; js_NumberToObject
+; js_FinalizeDouble
+; js_InitNumberClass
+; js_NumberToString
+; js_NewDoubleValue
+; js_NewDouble
+; js_ValueToNumber
+;
+;
+;00010:jsmath (OFFSET:0x00059c7f, SIZE:0x000054b6):
+; - Public Definitions:
+; js_InitMathClass
+;
+;
+;00011:jsjava (OFFSET:0x0005f135, SIZE:0x00022aad):
+; - Public Definitions:
+; js_Hooks
+; MojaSrcLog
+; finalizeTask
+ JSJ_FindCurrentJSContext
+; JSJ_GetPrincipals
+ JSJ_IsSafeMethod
+ JSJ_InitContext
+ JSJ_Init
+ js_JSErrorToJException
+ js_JavaErrorReporter
+ js_RemoveReflection
+ js_ReflectJObjectToJSObject
+ js_convertJObjectToJSValue
+ js_convertJSValueToJObject
+ js_ReflectJSObjectToJObject
+; js_ReflectJClassToJSObject
+ JSJ_ExitJS
+ JSJ_EnterJS
+ JSJ_CurrentContext
+ JSJ_IsEnabled
+;added in GA code - DSR70297
+ JSJ_Finish
+ JSJ_IsCalledFromJava
+ js_GetJSPrincipalsFromJavaCaller
+
+;
+;
+;00012:jsinterp (OFFSET:0x00081be2, SIZE:0x00012274):
+; - Public Definitions:
+; js_Call
+; js_Interpret
+; js_SetLocalVariable
+; js_GetLocalVariable
+; js_SetArgument
+; js_GetArgument
+; js_FlushPropertyCacheByProp
+; js_FlushPropertyCache
+;
+;
+;00013:jsgc (OFFSET:0x00093e56, SIZE:0x00004f8d):
+; - Public Definitions:
+; js_ForceGC
+; js_UnlockGCThing
+; js_LockGCThing
+; js_GC
+; js_AllocGCThing
+; js_RemoveRoot
+; js_AddRoot
+; js_FinishGC
+; js_InitGC
+;
+;
+;00014:jsfun (OFFSET:0x00098de3, SIZE:0x0000977c):
+; - Public Definitions:
+; js_FunctionClass
+; js_ClosureClass
+; js_CallClass
+; js_DefineFunction
+; js_NewFunction
+; js_InitCallAndClosureClasses
+; js_InitFunctionClass
+; js_ValueToFunction
+; js_SetCallVariable
+; js_GetCallVariable
+; js_PutCallObject
+; js_GetCallObject
+;
+;
+;00015:jsemit (OFFSET:0x000a255f, SIZE:0x000077be):
+; - Public Definitions:
+; js_SrcNoteName
+; js_SrcNoteArity
+ js_FinishTakingSrcNotes
+; js_MoveSrcNotes
+; js_GetSrcNoteOffset
+; js_BumpSrcNoteDelta
+; js_NewSrcNote3
+; js_NewSrcNote2
+; js_PopStatement
+; js_EmitContinue
+; js_EmitBreak
+; js_SetSrcNoteOffset
+; js_NewSrcNote
+; js_PushStatement
+; js_MoveCode
+; js_SetJumpOffset
+; js_Emit3
+; js_Emit2
+; js_Emit1
+; js_UpdateDepth
+; js_SrcNoteLength
+; js_CancelLastOpcode
+ js_InitCodeGenerator
+;
+;
+;00016:jsdbgapi (OFFSET:0x000a9d1d, SIZE:0x000057db):
+; - Public Definitions:
+; js_watchpoint_list
+; js_trap_list
+; JS_SetAnnotationInFrame
+; JS_GetAnnotationFromFrame
+; JS_GetJSPrincipalArrayFromFrame
+; JS_NextJSFrame
+; JS_InitJSFrameIterator
+ JS_LineNumberToPC
+ JS_PCToLineNumber
+ JS_ClearAllWatchPoints
+ JS_ClearWatchPoint
+ JS_SetWatchPoint
+ JS_HandleTrap
+ JS_ClearAllTraps
+ JS_ClearScriptTraps
+ JS_ClearTrap
+ JS_GetTrapOpcode
+ JS_SetTrap
+;DSR070297 - added in GA code
+ JS_FrameIterator
+ JS_GetFrameAnnotation
+ JS_GetFramePrincipalArray
+ JS_GetFrameScript
+ JS_GetScriptFilename
+ JS_SetFrameAnnotation
+ JS_GetFramePC
+ JS_GetFunctionScript
+
+;
+;
+;00017:jsdate (OFFSET:0x000af4f8, SIZE:0x00009a8e):
+; - Public Definitions:
+ js_DateGetSeconds
+ js_DateGetMinutes
+ js_DateGetHours
+ js_DateGetDate
+ js_DateGetMonth
+ js_DateGetYear
+ js_NewDateObject
+; js_InitDateClass
+;
+;
+;00018:jscntxt (OFFSET:0x000b8f86, SIZE:0x00003732):
+; - Public Definitions:
+; js_InterpreterHooks
+; js_ReportIsNotDefined
+; js_ReportErrorAgain
+; js_ReportErrorVA
+; js_ContextIterator
+; js_DestroyContext
+; js_NewContext
+; js_SetInterpreterHooks
+;
+;
+;00019:jsbool (OFFSET:0x000bc6b8, SIZE:0x00003375):
+; - Public Definitions:
+; js_BooleanToString
+; js_BooleanToObject
+; js_InitBooleanClass
+; js_ValueToBoolean
+;
+;
+;00020:jsatom (OFFSET:0x000bfa2d, SIZE:0x000058d0):
+; - Public Definitions:
+; js_valueOf_str
+; js_toString_str
+; js_length_str
+; js_eval_str
+; js_constructor_str
+; js_class_prototype_str
+; js_assign_str
+; js_anonymous_str
+; js_Object_str
+; js_Array_str
+; js_type_str
+; js_DropUnmappedAtoms
+ js_FreeAtomMap
+ js_InitAtomMap
+; js_GetAtom
+; js_DropAtom
+; js_IndexAtom
+; js_ValueToStringAtom
+; js_AtomizeString
+; js_AtomizeDouble
+; js_AtomizeInt
+; js_AtomizeBoolean
+; js_AtomizeObject
+; js_HoldAtom
+; js_MarkAtomState
+; js_FreeAtomState
+; js_Atomize
+; js_InitAtomState
+;
+;
+;00021:jsarray (OFFSET:0x000c52fd, SIZE:0x00007c86):
+; - Public Definitions:
+; js_ArrayClass
+; js_SetArrayLength
+; js_GetArrayLength
+; js_InitArrayClass
+; js_NewArrayObject
+; PR_qsort
+;
+;
+;00022:jsapi (OFFSET:0x000ccf83, SIZE:0x0000de8c):
+; - Public Definitions:
+ JS_ClearRegExpStatics
+ JS_SetRegExpInput
+ JS_NewRegExpObject
+ JS_SetErrorReporter
+ JS_CompareStrings
+ JS_GetStringLength
+ JS_GetStringBytes
+ JS_InternString
+ JS_NewStringCopyZ
+ JS_NewStringCopyN
+ JS_NewString
+ JS_IsRunning
+ JS_SetBranchCallback
+ JS_CallFunctionValue
+ JS_CallFunctionName
+ JS_CallFunction
+ JS_EvaluateScriptForPrincipals
+ JS_EvaluateScript
+ JS_ExecuteScript
+ JS_DecompileFunctionBody
+ JS_DecompileFunction
+ JS_DecompileScript
+ JS_CompileFunctionForPrincipals
+ JS_CompileFunction
+ JS_DestroyScript
+ JS_CompileScriptForPrincipals
+ JS_CompileScript
+ JS_DefineFunction
+ JS_GetFunctionName
+ JS_GetFunctionObject
+ JS_NewFunction
+ JS_ClearScope
+ JS_DeleteElement
+ JS_SetElement
+ JS_GetElement
+ JS_LookupElement
+ JS_AliasElement
+ JS_DefineElement
+ JS_SetArrayLength
+ JS_GetArrayLength
+ JS_NewArrayObject
+ JS_DeleteProperty
+ JS_SetProperty
+ JS_GetProperty
+ JS_LookupProperty
+ JS_AliasProperty
+ JS_DefinePropertyWithTinyId
+ JS_DefineProperty
+ JS_DefineConstDoubles
+ JS_DefineObject
+ JS_NewObject
+ JS_GetConstructor
+ JS_SetParent
+ JS_GetParent
+ JS_SetPrototype
+ JS_GetPrototype
+ JS_GetInstancePrivate
+ JS_SetPrivate
+ JS_GetPrivate
+ JS_InstanceOf
+ JS_GetClass
+ JS_DefineFunctions
+ JS_DefineProperties
+ JS_InitClass
+ JS_FinalizeStub
+ JS_ConvertStub
+ JS_ResolveStub
+ JS_EnumerateStub
+ JS_PropertyStub
+ JS_GC
+ JS_UnlockGCThing
+ JS_LockGCThing
+ JS_RemoveRoot
+ JS_AddRoot
+ JS_NewDoubleValue
+ JS_NewDouble
+ JS_strdup
+ JS_free
+ JS_realloc
+ JS_ReportOutOfMemory
+ JS_malloc
+ JS_GetScopeChain
+ JS_InitStandardClasses
+ JS_SetGlobalObject
+ JS_GetGlobalObject
+ JS_SetVersion
+ JS_GetVersion
+ JS_ContextIterator
+ JS_GetTaskState
+ JS_DestroyContext
+ JS_NewContext
+ JS_Unlock
+ JS_Lock
+ JS_Finish
+ JS_Init
+ JS_GetTypeName
+ JS_TypeOfValue
+ JS_ValueToBoolean
+ JS_ValueToInt32
+ JS_ValueToNumber
+ JS_ValueToString
+ JS_ValueToFunction
+ JS_ValueToObject
+ JS_ReportError
+ JS_ConvertValue
+ JS_GetEmptyStringValue
+ JS_GetPositiveInfinityValue
+ JS_GetNegativeInfinityValue
+ JS_GetNaNValue
+;DSR062897 - added for GA code
+ JS_MaybeGC
+ JS_GetScriptPrincipals
+ JS_IsAssigning
+ JS_SetCharSetInfo
+;brendan@mozilla.org, 2-Sept-2000
+ JS_SetCallReturnValue2
+ JS_SetGCCallback
+ JS_SetGCCallbackRT
+ JS_AddExternalStringFinalizer
+ JS_RemoveExternalStringFinalizer
+ JS_NewExternalString
+;
+;
+;00023:prmjtime (OFFSET:0x000dae0f, SIZE:0x00008986):
+; - Public Definitions:
+ PRMJ_FormatTimeUSEnglish
+ PRMJ_gmtime
+ PRMJ_FormatTime
+ PRMJ_mktime
+ PRMJ_ComputeTime
+ PRMJ_localtime
+ PRMJ_ExplodeTime
+ PRMJ_ToLocal
+ PRMJ_ToGMT
+ PRMJ_NowLocal
+ PRMJ_DSTOffset
+ PRMJ_NowS
+ PRMJ_NowMS
+ PRMJ_Now
+ PRMJ_ToExtendedTime
+ PRMJ_ToBaseTime
+ PRMJ_setDST
+ PRMJ_LocalGMTDifference
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp
new file mode 100644
index 0000000..db713c8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.cpp
@@ -0,0 +1,6060 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript API.
+ */
+#include "jsstddef.h"
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jsdhash.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdate.h"
+#include "jsdtoa.h"
+#include "jsemit.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsmath.h"
+#include "jsnum.h"
+#include "json.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "prmjtime.h"
+#include "jsstaticcheck.h"
+
+#if !defined JS_THREADSAFE && defined JS_TRACER
+#include "jstracer.h"
+#endif
+
+#if JS_HAS_FILE_OBJECT
+#include "jsfile.h"
+#endif
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#ifdef HAVE_VA_LIST_AS_ARRAY
+#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
+#else
+#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
+#endif
+
+#if defined(JS_THREADSAFE)
+#define CHECK_REQUEST(cx) \
+ JS_ASSERT((cx)->requestDepth || (cx)->thread == (cx)->runtime->gcThread)
+#else
+#define CHECK_REQUEST(cx) ((void)0)
+#endif
+
+JS_PUBLIC_API(int64)
+JS_Now()
+{
+ return PRMJ_Now();
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetNaNValue(JSContext *cx)
+{
+ return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetNegativeInfinityValue(JSContext *cx)
+{
+ return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetPositiveInfinityValue(JSContext *cx)
+{
+ return DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetEmptyStringValue(JSContext *cx)
+{
+ return STRING_TO_JSVAL(cx->runtime->emptyString);
+}
+
+static JSBool
+TryArgumentFormatter(JSContext *cx, const char **formatp, JSBool fromJS,
+ jsval **vpp, va_list *app)
+{
+ const char *format;
+ JSArgumentFormatMap *map;
+
+ format = *formatp;
+ for (map = cx->argumentFormatMap; map; map = map->next) {
+ if (!strncmp(format, map->format, map->length)) {
+ *formatp = format + map->length;
+ return map->formatter(cx, format, fromJS, vpp, app);
+ }
+ }
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR, format);
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+ ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, format);
+ ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+ const char *format, va_list ap)
+{
+ jsval *sp;
+ JSBool required;
+ char c;
+ JSFunction *fun;
+ jsdouble d;
+ JSString *str;
+ JSObject *obj;
+
+ CHECK_REQUEST(cx);
+ sp = argv;
+ required = JS_TRUE;
+ while ((c = *format++) != '\0') {
+ if (isspace(c))
+ continue;
+ if (c == '/') {
+ required = JS_FALSE;
+ continue;
+ }
+ if (sp == argv + argc) {
+ if (required) {
+ fun = js_ValueToFunction(cx, &argv[-2], 0);
+ if (fun) {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%u", argc);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_MORE_ARGS_NEEDED,
+ JS_GetFunctionName(fun), numBuf,
+ (argc == 1) ? "" : "s");
+ }
+ return JS_FALSE;
+ }
+ break;
+ }
+ switch (c) {
+ case 'b':
+ *va_arg(ap, JSBool *) = js_ValueToBoolean(*sp);
+ break;
+ case 'c':
+ if (!JS_ValueToUint16(cx, *sp, va_arg(ap, uint16 *)))
+ return JS_FALSE;
+ break;
+ case 'i':
+ if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32 *)))
+ return JS_FALSE;
+ break;
+ case 'u':
+ if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32 *)))
+ return JS_FALSE;
+ break;
+ case 'j':
+ if (!JS_ValueToInt32(cx, *sp, va_arg(ap, int32 *)))
+ return JS_FALSE;
+ break;
+ case 'd':
+ if (!JS_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
+ return JS_FALSE;
+ break;
+ case 'I':
+ if (!JS_ValueToNumber(cx, *sp, &d))
+ return JS_FALSE;
+ *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
+ break;
+ case 's':
+ case 'S':
+ case 'W':
+ str = js_ValueToString(cx, *sp);
+ if (!str)
+ return JS_FALSE;
+ *sp = STRING_TO_JSVAL(str);
+ if (c == 's') {
+ const char *bytes = js_GetStringBytes(cx, str);
+ if (!bytes)
+ return JS_FALSE;
+ *va_arg(ap, const char **) = bytes;
+ } else if (c == 'W') {
+ const jschar *chars = js_GetStringChars(cx, str);
+ if (!chars)
+ return JS_FALSE;
+ *va_arg(ap, const jschar **) = chars;
+ } else {
+ *va_arg(ap, JSString **) = str;
+ }
+ break;
+ case 'o':
+ if (!js_ValueToObject(cx, *sp, &obj))
+ return JS_FALSE;
+ *sp = OBJECT_TO_JSVAL(obj);
+ *va_arg(ap, JSObject **) = obj;
+ break;
+ case 'f':
+ obj = js_ValueToFunctionObject(cx, sp, 0);
+ if (!obj)
+ return JS_FALSE;
+ *sp = OBJECT_TO_JSVAL(obj);
+ *va_arg(ap, JSFunction **) = (JSFunction *) JS_GetPrivate(cx, obj);
+ break;
+ case 'v':
+ *va_arg(ap, jsval *) = *sp;
+ break;
+ case '*':
+ break;
+ default:
+ format--;
+ if (!TryArgumentFormatter(cx, &format, JS_TRUE, &sp,
+ JS_ADDRESSOF_VA_LIST(ap))) {
+ return JS_FALSE;
+ }
+ /* NB: the formatter already updated sp, so we continue here. */
+ continue;
+ }
+ sp++;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(jsval *)
+JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
+{
+ va_list ap;
+ jsval *argv;
+
+ va_start(ap, format);
+ argv = JS_PushArgumentsVA(cx, markp, format, ap);
+ va_end(ap);
+ return argv;
+}
+
+JS_PUBLIC_API(jsval *)
+JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
+{
+ uintN argc;
+ jsval *argv, *sp;
+ char c;
+ const char *cp;
+ JSString *str;
+ JSFunction *fun;
+ JSStackHeader *sh;
+
+ CHECK_REQUEST(cx);
+ *markp = NULL;
+ argc = 0;
+ for (cp = format; (c = *cp) != '\0'; cp++) {
+ /*
+ * Count non-space non-star characters as individual jsval arguments.
+ * This may over-allocate stack, but we'll fix below.
+ */
+ if (isspace(c) || c == '*')
+ continue;
+ argc++;
+ }
+ sp = js_AllocStack(cx, argc, markp);
+ if (!sp)
+ return NULL;
+ argv = sp;
+ while ((c = *format++) != '\0') {
+ if (isspace(c) || c == '*')
+ continue;
+ switch (c) {
+ case 'b':
+ *sp = BOOLEAN_TO_JSVAL((JSBool) va_arg(ap, int));
+ break;
+ case 'c':
+ *sp = INT_TO_JSVAL((uint16) va_arg(ap, unsigned int));
+ break;
+ case 'i':
+ case 'j':
+ /*
+ * Use JS_New{Double,Number}Value here and in the next two cases,
+ * not js_New{Double,Number}InRootedValue, as sp may point to an
+ * unrooted location.
+ */
+ if (!JS_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
+ goto bad;
+ break;
+ case 'u':
+ if (!JS_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
+ goto bad;
+ break;
+ case 'd':
+ case 'I':
+ if (!JS_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
+ goto bad;
+ break;
+ case 's':
+ str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
+ if (!str)
+ goto bad;
+ *sp = STRING_TO_JSVAL(str);
+ break;
+ case 'W':
+ str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
+ if (!str)
+ goto bad;
+ *sp = STRING_TO_JSVAL(str);
+ break;
+ case 'S':
+ str = va_arg(ap, JSString *);
+ *sp = STRING_TO_JSVAL(str);
+ break;
+ case 'o':
+ *sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
+ break;
+ case 'f':
+ fun = va_arg(ap, JSFunction *);
+ *sp = fun ? OBJECT_TO_JSVAL(FUN_OBJECT(fun)) : JSVAL_NULL;
+ break;
+ case 'v':
+ *sp = va_arg(ap, jsval);
+ break;
+ default:
+ format--;
+ if (!TryArgumentFormatter(cx, &format, JS_FALSE, &sp,
+ JS_ADDRESSOF_VA_LIST(ap))) {
+ goto bad;
+ }
+ /* NB: the formatter already updated sp, so we continue here. */
+ continue;
+ }
+ sp++;
+ }
+
+ /*
+ * We may have overallocated stack due to a multi-character format code
+ * handled by a JSArgumentFormatter. Give back that stack space!
+ */
+ JS_ASSERT(sp <= argv + argc);
+ if (sp < argv + argc) {
+ /* Return slots not pushed to the current stack arena. */
+ cx->stackPool.current->avail = (jsuword)sp;
+
+ /* Reduce the count of slots the GC will scan in this stack segment. */
+ sh = cx->stackHeaders;
+ JS_ASSERT(JS_STACK_SEGMENT(sh) + sh->nslots == argv + argc);
+ sh->nslots -= argc - (sp - argv);
+ }
+ return argv;
+
+bad:
+ js_FreeStack(cx, *markp);
+ return NULL;
+}
+
+JS_PUBLIC_API(void)
+JS_PopArguments(JSContext *cx, void *mark)
+{
+ CHECK_REQUEST(cx);
+ js_FreeStack(cx, mark);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddArgumentFormatter(JSContext *cx, const char *format,
+ JSArgumentFormatter formatter)
+{
+ size_t length;
+ JSArgumentFormatMap **mpp, *map;
+
+ length = strlen(format);
+ mpp = &cx->argumentFormatMap;
+ while ((map = *mpp) != NULL) {
+ /* Insert before any shorter string to match before prefixes. */
+ if (map->length < length)
+ break;
+ if (map->length == length && !strcmp(map->format, format))
+ goto out;
+ mpp = &map->next;
+ }
+ map = (JSArgumentFormatMap *) JS_malloc(cx, sizeof *map);
+ if (!map)
+ return JS_FALSE;
+ map->format = format;
+ map->length = length;
+ map->next = *mpp;
+ *mpp = map;
+out:
+ map->formatter = formatter;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_RemoveArgumentFormatter(JSContext *cx, const char *format)
+{
+ size_t length;
+ JSArgumentFormatMap **mpp, *map;
+
+ length = strlen(format);
+ mpp = &cx->argumentFormatMap;
+ while ((map = *mpp) != NULL) {
+ if (map->length == length && !strcmp(map->format, format)) {
+ *mpp = map->next;
+ JS_free(cx, map);
+ return;
+ }
+ mpp = &map->next;
+ }
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj;
+ JSString *str;
+ jsdouble d, *dp;
+
+ CHECK_REQUEST(cx);
+ switch (type) {
+ case JSTYPE_VOID:
+ *vp = JSVAL_VOID;
+ ok = JS_TRUE;
+ break;
+ case JSTYPE_OBJECT:
+ ok = js_ValueToObject(cx, v, &obj);
+ if (ok)
+ *vp = OBJECT_TO_JSVAL(obj);
+ break;
+ case JSTYPE_FUNCTION:
+ *vp = v;
+ obj = js_ValueToFunctionObject(cx, vp, JSV2F_SEARCH_STACK);
+ ok = (obj != NULL);
+ break;
+ case JSTYPE_STRING:
+ str = js_ValueToString(cx, v);
+ ok = (str != NULL);
+ if (ok)
+ *vp = STRING_TO_JSVAL(str);
+ break;
+ case JSTYPE_NUMBER:
+ ok = JS_ValueToNumber(cx, v, &d);
+ if (ok) {
+ dp = js_NewWeaklyRootedDouble(cx, d);
+ ok = (dp != NULL);
+ if (ok)
+ *vp = DOUBLE_TO_JSVAL(dp);
+ }
+ break;
+ case JSTYPE_BOOLEAN:
+ *vp = BOOLEAN_TO_JSVAL(js_ValueToBoolean(v));
+ return JS_TRUE;
+ default: {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_TYPE,
+ numBuf);
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToObject(cx, v, objp);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_ValueToFunction(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_ValueToConstructor(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToFunction(cx, &v, JSV2F_SEARCH_STACK);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_ValueToString(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToString(cx, v);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_ValueToSource(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ValueToSource(cx, v);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *dp = js_ValueToNumber(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToECMAInt32(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToECMAUint32(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToInt32(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip)
+{
+ JSTempValueRooter tvr;
+
+ CHECK_REQUEST(cx);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ *ip = js_ValueToUint16(cx, &tvr.u.value);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return !JSVAL_IS_NULL(tvr.u.value);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp)
+{
+ CHECK_REQUEST(cx);
+ *bp = js_ValueToBoolean(v);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSType)
+JS_TypeOfValue(JSContext *cx, jsval v)
+{
+ JSType type;
+ JSObject *obj;
+ JSObjectOps *ops;
+ JSClass *clasp;
+
+ CHECK_REQUEST(cx);
+ if (JSVAL_IS_OBJECT(v)) {
+ type = JSTYPE_OBJECT; /* XXXbe JSTYPE_NULL for JS2 */
+ obj = JSVAL_TO_OBJECT(v);
+ if (obj) {
+ JSObject *wrapped;
+
+ wrapped = js_GetWrappedObject(cx, obj);
+ if (wrapped)
+ obj = wrapped;
+
+ ops = obj->map->ops;
+#if JS_HAS_XML_SUPPORT
+ if (ops == &js_XMLObjectOps.base) {
+ type = JSTYPE_XML;
+ } else
+#endif
+ {
+ /*
+ * ECMA 262, 11.4.3 says that any native object that implements
+ * [[Call]] should be of type "function". Note that RegExp and
+ * Script are both of type "function" for compatibility with
+ * older SpiderMonkeys.
+ */
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if ((ops == &js_ObjectOps)
+ ? (clasp->call
+ ? clasp == &js_ScriptClass
+ : clasp == &js_FunctionClass)
+ : ops->call != NULL) {
+ type = JSTYPE_FUNCTION;
+ } else {
+#ifdef NARCISSUS
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .__call__Atom),
+ &v)) {
+ JS_ClearPendingException(cx);
+ } else if (VALUE_IS_FUNCTION(cx, v)) {
+ type = JSTYPE_FUNCTION;
+ }
+#endif
+ }
+ }
+ }
+ } else if (JSVAL_IS_NUMBER(v)) {
+ type = JSTYPE_NUMBER;
+ } else if (JSVAL_IS_STRING(v)) {
+ type = JSTYPE_STRING;
+ } else if (JSVAL_IS_BOOLEAN(v)) {
+ type = JSTYPE_BOOLEAN;
+ } else {
+ type = JSTYPE_VOID;
+ }
+ return type;
+}
+
+JS_PUBLIC_API(const char *)
+JS_GetTypeName(JSContext *cx, JSType type)
+{
+ if ((uintN)type >= (uintN)JSTYPE_LIMIT)
+ return NULL;
+ return JS_TYPE_STR(type);
+}
+
+/************************************************************************/
+
+/*
+ * Has a new runtime ever been created? This flag is used to detect unsafe
+ * changes to js_CStringsAreUTF8 after a runtime has been created, and to
+ * ensure that "first checks" on runtime creation are run only once.
+ */
+#ifdef DEBUG
+static JSBool js_NewRuntimeWasCalled = JS_FALSE;
+#endif
+
+JS_PUBLIC_API(JSRuntime *)
+JS_NewRuntime(uint32 maxbytes)
+{
+ JSRuntime *rt;
+
+#ifdef DEBUG
+ if (!js_NewRuntimeWasCalled) {
+ /*
+ * This code asserts that the numbers associated with the error names
+ * in jsmsg.def are monotonically increasing. It uses values for the
+ * error names enumerated in jscntxt.c. It's not a compile-time check
+ * but it's better than nothing.
+ */
+ int errorNumber = 0;
+#define MSG_DEF(name, number, count, exception, format) \
+ JS_ASSERT(name == errorNumber++);
+#include "js.msg"
+#undef MSG_DEF
+
+#define MSG_DEF(name, number, count, exception, format) \
+ JS_BEGIN_MACRO \
+ uintN numfmtspecs = 0; \
+ const char *fmt; \
+ for (fmt = format; *fmt != '\0'; fmt++) { \
+ if (*fmt == '{' && isdigit(fmt[1])) \
+ ++numfmtspecs; \
+ } \
+ JS_ASSERT(count == numfmtspecs); \
+ JS_END_MACRO;
+#include "js.msg"
+#undef MSG_DEF
+
+ js_NewRuntimeWasCalled = JS_TRUE;
+ }
+#endif /* DEBUG */
+
+ rt = (JSRuntime *) malloc(sizeof(JSRuntime));
+ if (!rt)
+ return NULL;
+
+ /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
+ memset(rt, 0, sizeof(JSRuntime));
+ JS_INIT_CLIST(&rt->contextList);
+ JS_INIT_CLIST(&rt->trapList);
+ JS_INIT_CLIST(&rt->watchPointList);
+
+ if (!js_InitDtoa())
+ goto bad;
+ if (!js_InitGC(rt, maxbytes))
+ goto bad;
+ if (!js_InitAtomState(rt))
+ goto bad;
+ if (!js_InitDeflatedStringCache(rt))
+ goto bad;
+#ifdef JS_THREADSAFE
+ if (!js_InitThreadPrivateIndex(js_ThreadDestructorCB))
+ goto bad;
+ rt->gcLock = JS_NEW_LOCK();
+ if (!rt->gcLock)
+ goto bad;
+ rt->gcDone = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->gcDone)
+ goto bad;
+ rt->requestDone = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->requestDone)
+ goto bad;
+ /* this is asymmetric with JS_ShutDown: */
+ if (!js_SetupLocks(8, 16))
+ goto bad;
+ rt->rtLock = JS_NEW_LOCK();
+ if (!rt->rtLock)
+ goto bad;
+ rt->stateChange = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->stateChange)
+ goto bad;
+ rt->titleSharingDone = JS_NEW_CONDVAR(rt->gcLock);
+ if (!rt->titleSharingDone)
+ goto bad;
+ rt->titleSharingTodo = NO_TITLE_SHARING_TODO;
+ rt->debuggerLock = JS_NEW_LOCK();
+ if (!rt->debuggerLock)
+ goto bad;
+#endif
+ if (!js_InitPropertyTree(rt))
+ goto bad;
+
+#if !defined JS_THREADSAFE && defined JS_TRACER
+ js_InitJIT(&rt->traceMonitor);
+#endif
+
+ return rt;
+
+bad:
+ JS_DestroyRuntime(rt);
+ return NULL;
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyRuntime(JSRuntime *rt)
+{
+#ifdef DEBUG
+ /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
+ if (!JS_CLIST_IS_EMPTY(&rt->contextList)) {
+ JSContext *cx, *iter = NULL;
+ uintN cxcount = 0;
+ while ((cx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL) {
+ fprintf(stderr,
+"JS API usage error: found live context at %p\n",
+ cx);
+ cxcount++;
+ }
+ fprintf(stderr,
+"JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
+ cxcount, (cxcount == 1) ? "" : "s");
+ }
+#endif
+
+#if !defined JS_THREADSAFE && defined JS_TRACER
+ js_FinishJIT(&rt->traceMonitor);
+#endif
+
+ js_FreeRuntimeScriptState(rt);
+ js_FinishAtomState(rt);
+
+ /*
+ * Free unit string storage only after all strings have been finalized, so
+ * that js_FinalizeString can detect unit strings and avoid calling free
+ * on their chars storage.
+ */
+ js_FinishUnitStrings(rt);
+
+ /*
+ * Finish the deflated string cache after the last GC and after
+ * calling js_FinishAtomState, which finalizes strings.
+ */
+ js_FinishDeflatedStringCache(rt);
+ js_FinishGC(rt);
+#ifdef JS_THREADSAFE
+ if (rt->gcLock)
+ JS_DESTROY_LOCK(rt->gcLock);
+ if (rt->gcDone)
+ JS_DESTROY_CONDVAR(rt->gcDone);
+ if (rt->requestDone)
+ JS_DESTROY_CONDVAR(rt->requestDone);
+ if (rt->rtLock)
+ JS_DESTROY_LOCK(rt->rtLock);
+ if (rt->stateChange)
+ JS_DESTROY_CONDVAR(rt->stateChange);
+ if (rt->titleSharingDone)
+ JS_DESTROY_CONDVAR(rt->titleSharingDone);
+ if (rt->debuggerLock)
+ JS_DESTROY_LOCK(rt->debuggerLock);
+#else
+ GSN_CACHE_CLEAR(&rt->gsnCache);
+#endif
+ js_FinishPropertyTree(rt);
+ free(rt);
+}
+
+JS_PUBLIC_API(void)
+JS_ShutDown(void)
+{
+#ifdef JS_OPMETER
+ extern void js_DumpOpMeters();
+
+ js_DumpOpMeters();
+#endif
+
+ js_FinishDtoa();
+#ifdef JS_THREADSAFE
+ js_CleanupLocks();
+#endif
+ PRMJ_NowShutdown();
+}
+
+JS_PUBLIC_API(void *)
+JS_GetRuntimePrivate(JSRuntime *rt)
+{
+ return rt->data;
+}
+
+JS_PUBLIC_API(void)
+JS_SetRuntimePrivate(JSRuntime *rt, void *data)
+{
+ rt->data = data;
+}
+
+JS_PUBLIC_API(void)
+JS_BeginRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ JSRuntime *rt;
+
+ JS_ASSERT(cx->thread->id == js_CurrentThreadId());
+ if (!cx->requestDepth) {
+ JS_ASSERT(cx->gcLocalFreeLists == &js_GCEmptyFreeListSet);
+
+ /* Wait until the GC is finished. */
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+
+ /* NB: we use cx->thread here, not js_GetCurrentThread(). */
+ if (rt->gcThread != cx->thread) {
+ while (rt->gcLevel > 0)
+ JS_AWAIT_GC_DONE(rt);
+ }
+
+ /* Indicate that a request is running. */
+ rt->requestCount++;
+ cx->requestDepth = 1;
+ cx->outstandingRequests++;
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+ cx->requestDepth++;
+ cx->outstandingRequests++;
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_EndRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ JSRuntime *rt;
+ JSTitle *title, **todop;
+ JSBool shared;
+
+ CHECK_REQUEST(cx);
+ JS_ASSERT(cx->requestDepth > 0);
+ JS_ASSERT(cx->outstandingRequests > 0);
+ if (cx->requestDepth == 1) {
+ /* Lock before clearing to interlock with ClaimScope, in jslock.c. */
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+ cx->requestDepth = 0;
+ cx->outstandingRequests--;
+
+ /* See whether cx has any single-threaded titles to start sharing. */
+ todop = &rt->titleSharingTodo;
+ shared = JS_FALSE;
+ while ((title = *todop) != NO_TITLE_SHARING_TODO) {
+ if (title->ownercx != cx) {
+ todop = &title->u.link;
+ continue;
+ }
+ *todop = title->u.link;
+ title->u.link = NULL; /* null u.link for sanity ASAP */
+
+ /*
+ * If js_DropObjectMap returns null, we held the last ref to scope.
+ * The waiting thread(s) must have been killed, after which the GC
+ * collected the object that held this scope. Unlikely, because it
+ * requires that the GC ran (e.g., from an operation callback)
+ * during this request, but possible.
+ */
+ if (js_DropObjectMap(cx, TITLE_TO_MAP(title), NULL)) {
+ js_InitLock(&title->lock);
+ title->u.count = 0; /* NULL may not pun as 0 */
+ js_FinishSharingTitle(cx, title); /* set ownercx = NULL */
+ shared = JS_TRUE;
+ }
+ }
+ if (shared)
+ JS_NOTIFY_ALL_CONDVAR(rt->titleSharingDone);
+
+ js_RevokeGCLocalFreeLists(cx);
+
+ /* Give the GC a chance to run if this was the last request running. */
+ JS_ASSERT(rt->requestCount > 0);
+ rt->requestCount--;
+ if (rt->requestCount == 0)
+ JS_NOTIFY_REQUEST_DONE(rt);
+
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+
+ cx->requestDepth--;
+ cx->outstandingRequests--;
+#endif
+}
+
+/* Yield to pending GC operations, regardless of request depth */
+JS_PUBLIC_API(void)
+JS_YieldRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->thread);
+ CHECK_REQUEST(cx);
+ JS_ResumeRequest(cx, JS_SuspendRequest(cx));
+#endif
+}
+
+JS_PUBLIC_API(jsrefcount)
+JS_SuspendRequest(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ jsrefcount saveDepth = cx->requestDepth;
+
+ while (cx->requestDepth) {
+ cx->outstandingRequests++; /* compensate for JS_EndRequest */
+ JS_EndRequest(cx);
+ }
+ return saveDepth;
+#else
+ return 0;
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth)
+{
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!cx->requestDepth);
+ while (--saveDepth >= 0) {
+ JS_BeginRequest(cx);
+ cx->outstandingRequests--; /* compensate for JS_BeginRequest */
+ }
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_Lock(JSRuntime *rt)
+{
+ JS_LOCK_RUNTIME(rt);
+}
+
+JS_PUBLIC_API(void)
+JS_Unlock(JSRuntime *rt)
+{
+ JS_UNLOCK_RUNTIME(rt);
+}
+
+JS_PUBLIC_API(JSContextCallback)
+JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback)
+{
+ JSContextCallback old;
+
+ old = rt->cxCallback;
+ rt->cxCallback = cxCallback;
+ return old;
+}
+
+JS_PUBLIC_API(JSContext *)
+JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
+{
+ return js_NewContext(rt, stackChunkSize);
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyContext(JSContext *cx)
+{
+ js_DestroyContext(cx, JSDCM_FORCE_GC);
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyContextNoGC(JSContext *cx)
+{
+ js_DestroyContext(cx, JSDCM_NO_GC);
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyContextMaybeGC(JSContext *cx)
+{
+ js_DestroyContext(cx, JSDCM_MAYBE_GC);
+}
+
+JS_PUBLIC_API(void *)
+JS_GetContextPrivate(JSContext *cx)
+{
+ return cx->data;
+}
+
+JS_PUBLIC_API(void)
+JS_SetContextPrivate(JSContext *cx, void *data)
+{
+ cx->data = data;
+}
+
+JS_PUBLIC_API(JSRuntime *)
+JS_GetRuntime(JSContext *cx)
+{
+ return cx->runtime;
+}
+
+JS_PUBLIC_API(JSContext *)
+JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
+{
+ return js_ContextIterator(rt, JS_TRUE, iterp);
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_GetVersion(JSContext *cx)
+{
+ return JSVERSION_NUMBER(cx);
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_SetVersion(JSContext *cx, JSVersion version)
+{
+ JSVersion oldVersion;
+
+ JS_ASSERT(version != JSVERSION_UNKNOWN);
+ JS_ASSERT((version & ~JSVERSION_MASK) == 0);
+
+ oldVersion = JSVERSION_NUMBER(cx);
+ if (version == oldVersion)
+ return oldVersion;
+
+ /* We no longer support 1.4 or below. */
+ if (version != JSVERSION_DEFAULT && version <= JSVERSION_1_4)
+ return oldVersion;
+
+ cx->version = (cx->version & ~JSVERSION_MASK) | version;
+ js_OnVersionChange(cx);
+ return oldVersion;
+}
+
+static struct v2smap {
+ JSVersion version;
+ const char *string;
+} v2smap[] = {
+ {JSVERSION_1_0, "1.0"},
+ {JSVERSION_1_1, "1.1"},
+ {JSVERSION_1_2, "1.2"},
+ {JSVERSION_1_3, "1.3"},
+ {JSVERSION_1_4, "1.4"},
+ {JSVERSION_ECMA_3, "ECMAv3"},
+ {JSVERSION_1_5, "1.5"},
+ {JSVERSION_1_6, "1.6"},
+ {JSVERSION_1_7, "1.7"},
+ {JSVERSION_1_8, "1.8"},
+ {JSVERSION_DEFAULT, js_default_str},
+ {JSVERSION_UNKNOWN, NULL}, /* must be last, NULL is sentinel */
+};
+
+JS_PUBLIC_API(const char *)
+JS_VersionToString(JSVersion version)
+{
+ int i;
+
+ for (i = 0; v2smap[i].string; i++)
+ if (v2smap[i].version == version)
+ return v2smap[i].string;
+ return "unknown";
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_StringToVersion(const char *string)
+{
+ int i;
+
+ for (i = 0; v2smap[i].string; i++)
+ if (strcmp(v2smap[i].string, string) == 0)
+ return v2smap[i].version;
+ return JSVERSION_UNKNOWN;
+}
+
+JS_PUBLIC_API(uint32)
+JS_GetOptions(JSContext *cx)
+{
+ return cx->options;
+}
+
+#define SYNC_OPTIONS_TO_VERSION(cx) \
+ JS_BEGIN_MACRO \
+ if ((cx)->options & JSOPTION_XML) \
+ (cx)->version |= JSVERSION_HAS_XML; \
+ else \
+ (cx)->version &= ~JSVERSION_HAS_XML; \
+ JS_END_MACRO
+
+JS_PUBLIC_API(uint32)
+JS_SetOptions(JSContext *cx, uint32 options)
+{
+ uint32 oldopts = cx->options;
+ cx->options = options;
+ SYNC_OPTIONS_TO_VERSION(cx);
+ return oldopts;
+}
+
+JS_PUBLIC_API(uint32)
+JS_ToggleOptions(JSContext *cx, uint32 options)
+{
+ uint32 oldopts = cx->options;
+ cx->options ^= options;
+ SYNC_OPTIONS_TO_VERSION(cx);
+ return oldopts;
+}
+
+JS_PUBLIC_API(const char *)
+JS_GetImplementationVersion(void)
+{
+ return "JavaScript-C 1.8.0 pre-release 1 2007-10-03";
+}
+
+
+JS_PUBLIC_API(JSObject *)
+JS_GetGlobalObject(JSContext *cx)
+{
+ return cx->globalObject;
+}
+
+JS_PUBLIC_API(void)
+JS_SetGlobalObject(JSContext *cx, JSObject *obj)
+{
+ cx->globalObject = obj;
+
+#if JS_HAS_XML_SUPPORT
+ cx->xmlSettingFlags = 0;
+#endif
+}
+
+JS_BEGIN_EXTERN_C
+
+JSObject *
+js_InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
+{
+ JSDHashTable *table;
+ JSBool resolving;
+ JSRuntime *rt;
+ JSResolvingKey key;
+ JSResolvingEntry *entry;
+ JSObject *fun_proto, *obj_proto;
+
+ /* If cx has no global object, use obj so prototypes can be found. */
+ if (!cx->globalObject)
+ JS_SetGlobalObject(cx, obj);
+
+ /* Record Function and Object in cx->resolvingTable, if we are resolving. */
+ table = cx->resolvingTable;
+ resolving = (table && table->entryCount);
+ rt = cx->runtime;
+ key.obj = obj;
+ if (resolving) {
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
+ if (entry && entry->key.obj && (entry->flags & JSRESFLAG_LOOKUP)) {
+ /* Already resolving Function, record Object too. */
+ JS_ASSERT(entry->key.obj == obj);
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, &key, JS_DHASH_ADD);
+ }
+ if (!entry) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ JS_ASSERT(!entry->key.obj && entry->flags == 0);
+ entry->key = key;
+ entry->flags = JSRESFLAG_LOOKUP;
+ } else {
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry))
+ return NULL;
+
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]);
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) {
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+ return NULL;
+ }
+
+ table = cx->resolvingTable;
+ }
+
+ /* Initialize the function class first so constructors can be made. */
+ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Function),
+ &fun_proto)) {
+ fun_proto = NULL;
+ goto out;
+ }
+ if (!fun_proto) {
+ fun_proto = js_InitFunctionClass(cx, obj);
+ if (!fun_proto)
+ goto out;
+ } else {
+ JSObject *ctor;
+
+ ctor = JS_GetConstructor(cx, fun_proto);
+ if (!ctor) {
+ fun_proto = NULL;
+ goto out;
+ }
+ OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(CLASS_ATOM(cx, Function)),
+ OBJECT_TO_JSVAL(ctor), 0, 0, 0, NULL);
+ }
+
+ /* Initialize the object class next so Object.prototype works. */
+ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
+ &obj_proto)) {
+ fun_proto = NULL;
+ goto out;
+ }
+ if (!obj_proto)
+ obj_proto = js_InitObjectClass(cx, obj);
+ if (!obj_proto) {
+ fun_proto = NULL;
+ goto out;
+ }
+
+ /* Function.prototype and the global object delegate to Object.prototype. */
+ OBJ_SET_PROTO(cx, fun_proto, obj_proto);
+ if (!OBJ_GET_PROTO(cx, obj))
+ OBJ_SET_PROTO(cx, obj, obj_proto);
+
+out:
+ /* If resolving, remove the other entry (Object or Function) from table. */
+ JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+ if (!resolving) {
+ /* If not resolving, remove the first entry added above, for Object. */
+ JS_ASSERT(key.id == \
+ ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Function]));
+ key.id = ATOM_TO_JSID(rt->atomState.classAtoms[JSProto_Object]);
+ JS_DHashTableOperate(table, &key, JS_DHASH_REMOVE);
+ }
+ return fun_proto;
+}
+
+JS_END_EXTERN_C
+
+JS_PUBLIC_API(JSBool)
+JS_InitStandardClasses(JSContext *cx, JSObject *obj)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+
+ /* Define a top-level property 'undefined' with the undefined value. */
+ atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+ NULL, NULL, JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+
+ /* Function and Object require cooperative bootstrapping magic. */
+ if (!js_InitFunctionAndObjectClasses(cx, obj))
+ return JS_FALSE;
+
+ /* Initialize the rest of the standard objects and functions. */
+ return js_InitArrayClass(cx, obj) &&
+ js_InitBlockClass(cx, obj) &&
+ js_InitBooleanClass(cx, obj) &&
+ js_InitCallClass(cx, obj) &&
+ js_InitExceptionClasses(cx, obj) &&
+ js_InitMathClass(cx, obj) &&
+ js_InitNumberClass(cx, obj) &&
+ js_InitJSONClass(cx, obj) &&
+ js_InitRegExpClass(cx, obj) &&
+ js_InitStringClass(cx, obj) &&
+ js_InitEval(cx, obj) &&
+#if JS_HAS_SCRIPT_OBJECT
+ js_InitScriptClass(cx, obj) &&
+#endif
+#if JS_HAS_XML_SUPPORT
+ js_InitXMLClasses(cx, obj) &&
+#endif
+#if JS_HAS_FILE_OBJECT
+ js_InitFileClass(cx, obj) &&
+#endif
+#if JS_HAS_GENERATORS
+ js_InitIteratorClasses(cx, obj) &&
+#endif
+ js_InitDateClass(cx, obj);
+}
+
+#define CLASP(name) (&js_##name##Class)
+#define EXT_CLASP(name) (&js_##name##Class.base)
+#define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
+#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
+#define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
+#define EAGER_ATOM_AND_EXT_CLASP(name) EAGER_CLASS_ATOM(name), EXT_CLASP(name)
+#define LAZY_ATOM(name) ATOM_OFFSET(lazy.name), js_##name##_str
+
+typedef struct JSStdName {
+ JSObjectOp init;
+ size_t atomOffset; /* offset of atom pointer in JSAtomState */
+ const char *name; /* null if atom is pre-pinned, else name */
+ JSClass *clasp;
+} JSStdName;
+
+static JSAtom *
+StdNameToAtom(JSContext *cx, JSStdName *stdn)
+{
+ size_t offset;
+ JSAtom *atom;
+ const char *name;
+
+ offset = stdn->atomOffset;
+ atom = OFFSET_TO_ATOM(cx->runtime, offset);
+ if (!atom) {
+ name = stdn->name;
+ if (name) {
+ atom = js_Atomize(cx, name, strlen(name), ATOM_PINNED);
+ OFFSET_TO_ATOM(cx->runtime, offset) = atom;
+ }
+ }
+ return atom;
+}
+
+/*
+ * Table of class initializers and their atom offsets in rt->atomState.
+ * If you add a "standard" class, remember to update this table.
+ */
+static JSStdName standard_class_atoms[] = {
+ {js_InitFunctionAndObjectClasses, EAGER_ATOM_AND_CLASP(Function)},
+ {js_InitFunctionAndObjectClasses, EAGER_ATOM_AND_CLASP(Object)},
+ {js_InitArrayClass, EAGER_ATOM_AND_CLASP(Array)},
+ {js_InitBlockClass, EAGER_ATOM_AND_CLASP(Block)},
+ {js_InitBooleanClass, EAGER_ATOM_AND_CLASP(Boolean)},
+ {js_InitDateClass, EAGER_ATOM_AND_CLASP(Date)},
+ {js_InitMathClass, EAGER_ATOM_AND_CLASP(Math)},
+ {js_InitNumberClass, EAGER_ATOM_AND_CLASP(Number)},
+ {js_InitStringClass, EAGER_ATOM_AND_CLASP(String)},
+ {js_InitCallClass, EAGER_ATOM_AND_CLASP(Call)},
+ {js_InitExceptionClasses, EAGER_ATOM_AND_CLASP(Error)},
+ {js_InitRegExpClass, EAGER_ATOM_AND_CLASP(RegExp)},
+#if JS_HAS_SCRIPT_OBJECT
+ {js_InitScriptClass, EAGER_ATOM_AND_CLASP(Script)},
+#endif
+#if JS_HAS_XML_SUPPORT
+ {js_InitXMLClass, EAGER_ATOM_AND_CLASP(XML)},
+ {js_InitNamespaceClass, EAGER_ATOM_AND_EXT_CLASP(Namespace)},
+ {js_InitQNameClass, EAGER_ATOM_AND_EXT_CLASP(QName)},
+#endif
+#if JS_HAS_FILE_OBJECT
+ {js_InitFileClass, EAGER_ATOM_AND_CLASP(File)},
+#endif
+#if JS_HAS_GENERATORS
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(StopIteration)},
+#endif
+ {js_InitJSONClass, EAGER_ATOM_AND_CLASP(JSON)},
+ {NULL, 0, NULL, NULL}
+};
+
+/*
+ * Table of top-level function and constant names and their init functions.
+ * If you add a "standard" global function or property, remember to update
+ * this table.
+ */
+static JSStdName standard_class_names[] = {
+ /* ECMA requires that eval be a direct property of the global object. */
+ {js_InitEval, EAGER_ATOM(eval), NULL},
+
+ /* Global properties and functions defined by the Number class. */
+ {js_InitNumberClass, LAZY_ATOM(NaN), NULL},
+ {js_InitNumberClass, LAZY_ATOM(Infinity), NULL},
+ {js_InitNumberClass, LAZY_ATOM(isNaN), NULL},
+ {js_InitNumberClass, LAZY_ATOM(isFinite), NULL},
+ {js_InitNumberClass, LAZY_ATOM(parseFloat), NULL},
+ {js_InitNumberClass, LAZY_ATOM(parseInt), NULL},
+
+ /* String global functions. */
+ {js_InitStringClass, LAZY_ATOM(escape), NULL},
+ {js_InitStringClass, LAZY_ATOM(unescape), NULL},
+ {js_InitStringClass, LAZY_ATOM(decodeURI), NULL},
+ {js_InitStringClass, LAZY_ATOM(encodeURI), NULL},
+ {js_InitStringClass, LAZY_ATOM(decodeURIComponent), NULL},
+ {js_InitStringClass, LAZY_ATOM(encodeURIComponent), NULL},
+#if JS_HAS_UNEVAL
+ {js_InitStringClass, LAZY_ATOM(uneval), NULL},
+#endif
+
+ /* Exception constructors. */
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(Error), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(InternalError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(EvalError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(RangeError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(ReferenceError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(SyntaxError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(TypeError), CLASP(Error)},
+ {js_InitExceptionClasses, EAGER_CLASS_ATOM(URIError), CLASP(Error)},
+
+#if JS_HAS_XML_SUPPORT
+ {js_InitAnyNameClass, EAGER_ATOM_AND_CLASP(AnyName)},
+ {js_InitAttributeNameClass, EAGER_ATOM_AND_CLASP(AttributeName)},
+ {js_InitXMLClass, LAZY_ATOM(XMLList), &js_XMLClass},
+ {js_InitXMLClass, LAZY_ATOM(isXMLName), NULL},
+#endif
+
+#if JS_HAS_GENERATORS
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Iterator)},
+ {js_InitIteratorClasses, EAGER_ATOM_AND_CLASP(Generator)},
+#endif
+
+ {NULL, 0, NULL, NULL}
+};
+
+static JSStdName object_prototype_names[] = {
+ /* Object.prototype properties (global delegates to Object.prototype). */
+ {js_InitObjectClass, EAGER_ATOM(proto), NULL},
+ {js_InitObjectClass, EAGER_ATOM(parent), NULL},
+ {js_InitObjectClass, EAGER_ATOM(count), NULL},
+#if JS_HAS_TOSOURCE
+ {js_InitObjectClass, EAGER_ATOM(toSource), NULL},
+#endif
+ {js_InitObjectClass, EAGER_ATOM(toString), NULL},
+ {js_InitObjectClass, EAGER_ATOM(toLocaleString), NULL},
+ {js_InitObjectClass, EAGER_ATOM(valueOf), NULL},
+#if JS_HAS_OBJ_WATCHPOINT
+ {js_InitObjectClass, LAZY_ATOM(watch), NULL},
+ {js_InitObjectClass, LAZY_ATOM(unwatch), NULL},
+#endif
+ {js_InitObjectClass, LAZY_ATOM(hasOwnProperty), NULL},
+ {js_InitObjectClass, LAZY_ATOM(isPrototypeOf), NULL},
+ {js_InitObjectClass, LAZY_ATOM(propertyIsEnumerable), NULL},
+#if JS_HAS_GETTER_SETTER
+ {js_InitObjectClass, LAZY_ATOM(defineGetter), NULL},
+ {js_InitObjectClass, LAZY_ATOM(defineSetter), NULL},
+ {js_InitObjectClass, LAZY_ATOM(lookupGetter), NULL},
+ {js_InitObjectClass, LAZY_ATOM(lookupSetter), NULL},
+#endif
+
+ {NULL, 0, NULL, NULL}
+};
+
+JS_PUBLIC_API(JSBool)
+JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+ JSBool *resolved)
+{
+ JSString *idstr;
+ JSRuntime *rt;
+ JSAtom *atom;
+ JSStdName *stdnm;
+ uintN i;
+
+ CHECK_REQUEST(cx);
+ *resolved = JS_FALSE;
+
+ rt = cx->runtime;
+ JS_ASSERT(rt->state != JSRTS_DOWN);
+ if (rt->state == JSRTS_LANDING || !JSVAL_IS_STRING(id))
+ return JS_TRUE;
+
+ idstr = JSVAL_TO_STRING(id);
+
+ /* Check whether we're resolving 'undefined', and define it if so. */
+ atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+ if (idstr == ATOM_TO_STRING(atom)) {
+ *resolved = JS_TRUE;
+ return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+ NULL, NULL, JSPROP_PERMANENT, NULL);
+ }
+
+ /* Try for class constructors/prototypes named by well-known atoms. */
+ stdnm = NULL;
+ for (i = 0; standard_class_atoms[i].init; i++) {
+ atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
+ if (idstr == ATOM_TO_STRING(atom)) {
+ stdnm = &standard_class_atoms[i];
+ break;
+ }
+ }
+
+ if (!stdnm) {
+ /* Try less frequently used top-level functions and constants. */
+ for (i = 0; standard_class_names[i].init; i++) {
+ atom = StdNameToAtom(cx, &standard_class_names[i]);
+ if (!atom)
+ return JS_FALSE;
+ if (idstr == ATOM_TO_STRING(atom)) {
+ stdnm = &standard_class_names[i];
+ break;
+ }
+ }
+
+ if (!stdnm && !OBJ_GET_PROTO(cx, obj)) {
+ /*
+ * Try even less frequently used names delegated from the global
+ * object to Object.prototype, but only if the Object class hasn't
+ * yet been initialized.
+ */
+ for (i = 0; object_prototype_names[i].init; i++) {
+ atom = StdNameToAtom(cx, &object_prototype_names[i]);
+ if (!atom)
+ return JS_FALSE;
+ if (idstr == ATOM_TO_STRING(atom)) {
+ stdnm = &standard_class_names[i];
+ break;
+ }
+ }
+ }
+ }
+
+ if (stdnm) {
+ /*
+ * If this standard class is anonymous and obj advertises itself as a
+ * global object (in order to reserve slots for standard class object
+ * pointers), then we don't want to resolve by name.
+ *
+ * If inversely, either id does not name a class, or id does not name
+ * an anonymous class, or the global does not reserve slots for class
+ * objects, then we must call the init hook here.
+ */
+ if (stdnm->clasp &&
+ (stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS) &&
+ (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) {
+ return JS_TRUE;
+ }
+
+ if (!stdnm->init(cx, obj))
+ return JS_FALSE;
+ *resolved = JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
+{
+ JSScopeProperty *sprop;
+ JSScope *scope;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
+ JS_UNLOCK_SCOPE(cx, scope);
+ return sprop != NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSAtom *atom;
+ uintN i;
+
+ CHECK_REQUEST(cx);
+ rt = cx->runtime;
+
+ /* Check whether we need to bind 'undefined' and define it if so. */
+ atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+ if (!AlreadyHasOwnProperty(cx, obj, atom) &&
+ !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,
+ NULL, NULL, JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+
+ /* Initialize any classes that have not been resolved yet. */
+ for (i = 0; standard_class_atoms[i].init; i++) {
+ atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
+ if (!AlreadyHasOwnProperty(cx, obj, atom) &&
+ !standard_class_atoms[i].init(cx, obj)) {
+ return JS_FALSE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSIdArray *
+NewIdArray(JSContext *cx, jsint length)
+{
+ JSIdArray *ida;
+
+ ida = (JSIdArray *)
+ JS_malloc(cx, offsetof(JSIdArray, vector) + length * sizeof(jsval));
+ if (ida)
+ ida->length = length;
+ return ida;
+}
+
+/*
+ * Unlike realloc(3), this function frees ida on failure.
+ */
+static JSIdArray *
+SetIdArrayLength(JSContext *cx, JSIdArray *ida, jsint length)
+{
+ JSIdArray *rida;
+
+ rida = (JSIdArray *)
+ JS_realloc(cx, ida,
+ offsetof(JSIdArray, vector) + length * sizeof(jsval));
+ if (!rida)
+ JS_DestroyIdArray(cx, ida);
+ else
+ rida->length = length;
+ return rida;
+}
+
+static JSIdArray *
+AddAtomToArray(JSContext *cx, JSAtom *atom, JSIdArray *ida, jsint *ip)
+{
+ jsint i, length;
+
+ i = *ip;
+ length = ida->length;
+ if (i >= length) {
+ ida = SetIdArrayLength(cx, ida, JS_MAX(length * 2, 8));
+ if (!ida)
+ return NULL;
+ JS_ASSERT(i < ida->length);
+ }
+ ida->vector[i] = ATOM_TO_JSID(atom);
+ *ip = i + 1;
+ return ida;
+}
+
+static JSIdArray *
+EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
+ jsint *ip, JSBool *foundp)
+{
+ *foundp = AlreadyHasOwnProperty(cx, obj, atom);
+ if (*foundp)
+ ida = AddAtomToArray(cx, atom, ida, ip);
+ return ida;
+}
+
+JS_PUBLIC_API(JSIdArray *)
+JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+ JSIdArray *ida)
+{
+ JSRuntime *rt;
+ jsint i, j, k;
+ JSAtom *atom;
+ JSBool found;
+ JSObjectOp init;
+
+ CHECK_REQUEST(cx);
+ rt = cx->runtime;
+ if (ida) {
+ i = ida->length;
+ } else {
+ ida = NewIdArray(cx, 8);
+ if (!ida)
+ return NULL;
+ i = 0;
+ }
+
+ /* Check whether 'undefined' has been resolved and enumerate it if so. */
+ atom = rt->atomState.typeAtoms[JSTYPE_VOID];
+ ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
+ if (!ida)
+ return NULL;
+
+ /* Enumerate only classes that *have* been resolved. */
+ for (j = 0; standard_class_atoms[j].init; j++) {
+ atom = OFFSET_TO_ATOM(rt, standard_class_atoms[j].atomOffset);
+ ida = EnumerateIfResolved(cx, obj, atom, ida, &i, &found);
+ if (!ida)
+ return NULL;
+
+ if (found) {
+ init = standard_class_atoms[j].init;
+
+ for (k = 0; standard_class_names[k].init; k++) {
+ if (standard_class_names[k].init == init) {
+ atom = StdNameToAtom(cx, &standard_class_names[k]);
+ ida = AddAtomToArray(cx, atom, ida, &i);
+ if (!ida)
+ return NULL;
+ }
+ }
+
+ if (init == js_InitObjectClass) {
+ for (k = 0; object_prototype_names[k].init; k++) {
+ atom = StdNameToAtom(cx, &object_prototype_names[k]);
+ ida = AddAtomToArray(cx, atom, ida, &i);
+ if (!ida)
+ return NULL;
+ }
+ }
+ }
+ }
+
+ /* Trim to exact length. */
+ return SetIdArrayLength(cx, ida, i);
+}
+
+#undef CLASP
+#undef EAGER_ATOM
+#undef EAGER_CLASS_ATOM
+#undef EAGER_ATOM_CLASP
+#undef LAZY_ATOM
+
+JS_PUBLIC_API(JSBool)
+JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp)
+{
+ CHECK_REQUEST(cx);
+ return js_GetClassObject(cx, obj, key, objp);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetScopeChain(JSContext *cx)
+{
+ JSStackFrame *fp;
+
+ CHECK_REQUEST(cx);
+ fp = cx->fp;
+ if (!fp) {
+ /*
+ * There is no code active on this context. In place of an actual
+ * scope chain, use the context's global object, which is set in
+ * js_InitFunctionAndObjectClasses, and which represents the default
+ * scope chain for the embedding. See also js_FindClassObject.
+ *
+ * For embeddings that use the inner and outer object hooks, the inner
+ * object represents the ultimate global object, with the outer object
+ * acting as a stand-in.
+ */
+ JSObject *obj = cx->globalObject;
+ if (!obj) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
+ return NULL;
+ }
+
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ return obj;
+ }
+ return js_GetScopeChain(cx, fp);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
+{
+ JSObject *parent;
+
+ while ((parent = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = parent;
+ return obj;
+}
+
+JS_PUBLIC_API(jsval)
+JS_ComputeThis(JSContext *cx, jsval *vp)
+{
+ if (!js_ComputeThis(cx, JS_FALSE, vp + 2))
+ return JSVAL_NULL;
+ return vp[1];
+}
+
+JS_PUBLIC_API(void *)
+JS_malloc(JSContext *cx, size_t nbytes)
+{
+ void *p;
+
+ JS_ASSERT(nbytes != 0);
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ if (nbytes == 0)
+ nbytes = 1;
+
+ p = malloc(nbytes);
+ if (!p) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ js_UpdateMallocCounter(cx, nbytes);
+
+ return p;
+}
+
+JS_PUBLIC_API(void *)
+JS_realloc(JSContext *cx, void *p, size_t nbytes)
+{
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ p = realloc(p, nbytes);
+ if (!p)
+ JS_ReportOutOfMemory(cx);
+ return p;
+}
+
+JS_PUBLIC_API(void)
+JS_free(JSContext *cx, void *p)
+{
+ if (p)
+ free(p);
+}
+
+JS_PUBLIC_API(char *)
+JS_strdup(JSContext *cx, const char *s)
+{
+ size_t n;
+ void *p;
+
+ n = strlen(s) + 1;
+ p = JS_malloc(cx, n);
+ if (!p)
+ return NULL;
+ return (char *)memcpy(p, s, n);
+}
+
+JS_PUBLIC_API(jsdouble *)
+JS_NewDouble(JSContext *cx, jsdouble d)
+{
+ CHECK_REQUEST(cx);
+ return js_NewWeaklyRootedDouble(cx, d);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
+{
+ jsdouble *dp;
+
+ CHECK_REQUEST(cx);
+ dp = js_NewWeaklyRootedDouble(cx, d);
+ if (!dp)
+ return JS_FALSE;
+ *rval = DOUBLE_TO_JSVAL(dp);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
+{
+ jsint i;
+
+ CHECK_REQUEST(cx);
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
+ *rval = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+ return JS_NewDoubleValue(cx, d, rval);
+}
+
+#undef JS_AddRoot
+JS_PUBLIC_API(JSBool)
+JS_AddRoot(JSContext *cx, void *rp)
+{
+ CHECK_REQUEST(cx);
+ return js_AddRoot(cx, rp, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name)
+{
+ return js_AddRootRT(rt, rp, name);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveRoot(JSContext *cx, void *rp)
+{
+ CHECK_REQUEST(cx);
+ return js_RemoveRoot(cx->runtime, rp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_RemoveRootRT(JSRuntime *rt, void *rp)
+{
+ return js_RemoveRoot(rt, rp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AddNamedRoot(JSContext *cx, void *rp, const char *name)
+{
+ CHECK_REQUEST(cx);
+ return js_AddRoot(cx, rp, name);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearNewbornRoots(JSContext *cx)
+{
+ JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EnterLocalRootScope(JSContext *cx)
+{
+ CHECK_REQUEST(cx);
+ return js_EnterLocalRootScope(cx);
+}
+
+JS_PUBLIC_API(void)
+JS_LeaveLocalRootScope(JSContext *cx)
+{
+ CHECK_REQUEST(cx);
+ js_LeaveLocalRootScope(cx);
+}
+
+JS_PUBLIC_API(void)
+JS_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
+{
+ CHECK_REQUEST(cx);
+ js_LeaveLocalRootScopeWithResult(cx, rval);
+}
+
+JS_PUBLIC_API(void)
+JS_ForgetLocalRoot(JSContext *cx, void *thing)
+{
+ CHECK_REQUEST(cx);
+ js_ForgetLocalRoot(cx, (jsval) thing);
+}
+
+#ifdef DEBUG
+
+JS_PUBLIC_API(void)
+JS_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data)
+{
+ js_DumpNamedRoots(rt, dump, data);
+}
+
+#endif /* DEBUG */
+
+JS_PUBLIC_API(uint32)
+JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
+{
+ return js_MapGCRoots(rt, map, data);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LockGCThing(JSContext *cx, void *thing)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_LockGCThingRT(cx->runtime, thing);
+ if (!ok)
+ JS_ReportOutOfMemory(cx);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LockGCThingRT(JSRuntime *rt, void *thing)
+{
+ return js_LockGCThingRT(rt, thing);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_UnlockGCThing(JSContext *cx, void *thing)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_UnlockGCThingRT(cx->runtime, thing);
+ if (!ok)
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_UNLOCK);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_UnlockGCThingRT(JSRuntime *rt, void *thing)
+{
+ return js_UnlockGCThingRT(rt, thing);
+}
+
+JS_PUBLIC_API(void)
+JS_SetExtraGCRoots(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
+{
+ rt->gcExtraRootsTraceOp = traceOp;
+ rt->gcExtraRootsData = data;
+}
+
+JS_PUBLIC_API(void)
+JS_TraceRuntime(JSTracer *trc)
+{
+ JSBool allAtoms = trc->context->runtime->gcKeepAtoms != 0;
+
+ js_TraceRuntime(trc, allAtoms);
+}
+
+#ifdef DEBUG
+
+#ifdef HAVE_XPCONNECT
+#include "dump_xpc.h"
+#endif
+
+JS_PUBLIC_API(void)
+JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
+ void *thing, uint32 kind, JSBool details)
+{
+ const char *name;
+ size_t n;
+
+ if (bufsize == 0)
+ return;
+
+ switch (kind) {
+ case JSTRACE_OBJECT:
+ {
+ JSObject *obj = (JSObject *)thing;
+ JSClass *clasp = STOBJ_GET_CLASS(obj);
+
+ name = clasp->name;
+#ifdef HAVE_XPCONNECT
+ if (clasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
+ jsval privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+
+ JS_ASSERT(clasp->flags & JSCLASS_HAS_PRIVATE);
+ if (!JSVAL_IS_VOID(privateValue)) {
+ void *privateThing = JSVAL_TO_PRIVATE(privateValue);
+ const char *xpcClassName = GetXPCObjectClassName(privateThing);
+
+ if (xpcClassName)
+ name = xpcClassName;
+ }
+ }
+#endif
+ break;
+ }
+
+ case JSTRACE_STRING:
+ name = JSSTRING_IS_DEPENDENT((JSString *)thing)
+ ? "substring"
+ : "string";
+ break;
+
+ case JSTRACE_DOUBLE:
+ name = "double";
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSTRACE_XML:
+ name = "xml";
+ break;
+#endif
+ default:
+ JS_ASSERT(0);
+ return;
+ break;
+ }
+
+ n = strlen(name);
+ if (n > bufsize - 1)
+ n = bufsize - 1;
+ memcpy(buf, name, n + 1);
+ buf += n;
+ bufsize -= n;
+
+ if (details && bufsize > 2) {
+ *buf++ = ' ';
+ bufsize--;
+
+ switch (kind) {
+ case JSTRACE_OBJECT:
+ {
+ JSObject *obj = (JSObject *)thing;
+ JSClass *clasp = STOBJ_GET_CLASS(obj);
+ if (clasp == &js_FunctionClass) {
+ JSFunction *fun = (JSFunction *)
+ JS_GetPrivate(trc->context, obj);
+
+ if (!fun) {
+ JS_snprintf(buf, bufsize, "<newborn>");
+ } else if (FUN_OBJECT(fun) != obj) {
+ JS_snprintf(buf, bufsize, "%p", fun);
+ } else {
+ if (fun->atom && ATOM_IS_STRING(fun->atom))
+ js_PutEscapedString(buf, bufsize,
+ ATOM_TO_STRING(fun->atom), 0);
+ }
+ } else if (clasp->flags & JSCLASS_HAS_PRIVATE) {
+ jsval privateValue = STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+ void *privateThing = JSVAL_IS_VOID(privateValue)
+ ? NULL
+ : JSVAL_TO_PRIVATE(privateValue);
+
+ JS_snprintf(buf, bufsize, "%p", privateThing);
+ } else {
+ JS_snprintf(buf, bufsize, "<no private>");
+ }
+ break;
+ }
+
+ case JSTRACE_STRING:
+ js_PutEscapedString(buf, bufsize, (JSString *)thing, 0);
+ break;
+
+ case JSTRACE_DOUBLE:
+ JS_snprintf(buf, bufsize, "%g", *(jsdouble *)thing);
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSTRACE_XML:
+ {
+ extern const char *js_xml_class_str[];
+ JSXML *xml = (JSXML *)thing;
+
+ JS_snprintf(buf, bufsize, "%s", js_xml_class_str[xml->xml_class]);
+ break;
+ }
+#endif
+ default:
+ JS_ASSERT(0);
+ break;
+ }
+ }
+ buf[bufsize - 1] = '\0';
+}
+
+typedef struct JSHeapDumpNode JSHeapDumpNode;
+
+struct JSHeapDumpNode {
+ void *thing;
+ uint32 kind;
+ JSHeapDumpNode *next; /* next sibling */
+ JSHeapDumpNode *parent; /* node with the thing that refer to thing
+ from this node */
+ char edgeName[1]; /* name of the edge from parent->thing
+ into thing */
+};
+
+typedef struct JSDumpingTracer {
+ JSTracer base;
+ JSDHashTable visited;
+ JSBool ok;
+ void *startThing;
+ void *thingToFind;
+ void *thingToIgnore;
+ JSHeapDumpNode *parentNode;
+ JSHeapDumpNode **lastNodep;
+ char buffer[200];
+} JSDumpingTracer;
+
+static void
+DumpNotify(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSDumpingTracer *dtrc;
+ JSContext *cx;
+ JSDHashEntryStub *entry;
+ JSHeapDumpNode *node;
+ const char *edgeName;
+ size_t edgeNameSize;
+
+ JS_ASSERT(trc->callback == DumpNotify);
+ dtrc = (JSDumpingTracer *)trc;
+
+ if (!dtrc->ok || thing == dtrc->thingToIgnore)
+ return;
+
+ cx = trc->context;
+
+ /*
+ * Check if we have already seen thing unless it is thingToFind to include
+ * it to the graph each time we reach it and print all live things that
+ * refer to thingToFind.
+ *
+ * This does not print all possible paths leading to thingToFind since
+ * when a thing A refers directly or indirectly to thingToFind and A is
+ * present several times in the graph, we will print only the first path
+ * leading to A and thingToFind, other ways to reach A will be ignored.
+ */
+ if (dtrc->thingToFind != thing) {
+ /*
+ * The startThing check allows to avoid putting startThing into the
+ * hash table before tracing startThing in JS_DumpHeap.
+ */
+ if (thing == dtrc->startThing)
+ return;
+ entry = (JSDHashEntryStub *)
+ JS_DHashTableOperate(&dtrc->visited, thing, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(cx);
+ dtrc->ok = JS_FALSE;
+ return;
+ }
+ if (entry->key)
+ return;
+ entry->key = thing;
+ }
+
+ if (dtrc->base.debugPrinter) {
+ dtrc->base.debugPrinter(trc, dtrc->buffer, sizeof(dtrc->buffer));
+ edgeName = dtrc->buffer;
+ } else if (dtrc->base.debugPrintIndex != (size_t)-1) {
+ JS_snprintf(dtrc->buffer, sizeof(dtrc->buffer), "%s[%lu]",
+ (const char *)dtrc->base.debugPrintArg,
+ dtrc->base.debugPrintIndex);
+ edgeName = dtrc->buffer;
+ } else {
+ edgeName = (const char*)dtrc->base.debugPrintArg;
+ }
+
+ edgeNameSize = strlen(edgeName) + 1;
+ node = (JSHeapDumpNode *)
+ JS_malloc(cx, offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
+ if (!node) {
+ dtrc->ok = JS_FALSE;
+ return;
+ }
+
+ node->thing = thing;
+ node->kind = kind;
+ node->next = NULL;
+ node->parent = dtrc->parentNode;
+ memcpy(node->edgeName, edgeName, edgeNameSize);
+
+ JS_ASSERT(!*dtrc->lastNodep);
+ *dtrc->lastNodep = node;
+ dtrc->lastNodep = &node->next;
+}
+
+/* Dump node and the chain that leads to thing it contains. */
+static JSBool
+DumpNode(JSDumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
+{
+ JSHeapDumpNode *prev, *following;
+ size_t chainLimit;
+ JSBool ok;
+ enum { MAX_PARENTS_TO_PRINT = 10 };
+
+ JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
+ &dtrc->base, node->thing, node->kind, JS_TRUE);
+ if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
+ return JS_FALSE;
+
+ /*
+ * We need to print the parent chain in the reverse order. To do it in
+ * O(N) time where N is the chain length we first reverse the chain while
+ * searching for the top and then print each node while restoring the
+ * chain order.
+ */
+ chainLimit = MAX_PARENTS_TO_PRINT;
+ prev = NULL;
+ for (;;) {
+ following = node->parent;
+ node->parent = prev;
+ prev = node;
+ node = following;
+ if (!node)
+ break;
+ if (chainLimit == 0) {
+ if (fputs("...", fp) < 0)
+ return JS_FALSE;
+ break;
+ }
+ --chainLimit;
+ }
+
+ node = prev;
+ prev = following;
+ ok = JS_TRUE;
+ do {
+ /* Loop must continue even when !ok to restore the parent chain. */
+ if (ok) {
+ if (!prev) {
+ /* Print edge from some runtime root or startThing. */
+ if (fputs(node->edgeName, fp) < 0)
+ ok = JS_FALSE;
+ } else {
+ JS_PrintTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
+ &dtrc->base, prev->thing, prev->kind,
+ JS_FALSE);
+ if (fprintf(fp, "(%p %s).%s",
+ prev->thing, dtrc->buffer, node->edgeName) < 0) {
+ ok = JS_FALSE;
+ }
+ }
+ }
+ following = node->parent;
+ node->parent = prev;
+ prev = node;
+ node = following;
+ } while (node);
+
+ return ok && putc('\n', fp) >= 0;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
+ void *thingToFind, size_t maxDepth, void *thingToIgnore)
+{
+ JSDumpingTracer dtrc;
+ JSHeapDumpNode *node, *children, *next, *parent;
+ size_t depth;
+ JSBool thingToFindWasTraced;
+
+ if (maxDepth == 0)
+ return JS_TRUE;
+
+ JS_TRACER_INIT(&dtrc.base, cx, DumpNotify);
+ if (!JS_DHashTableInit(&dtrc.visited, JS_DHashGetStubOps(),
+ NULL, sizeof(JSDHashEntryStub),
+ JS_DHASH_DEFAULT_CAPACITY(100))) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ dtrc.ok = JS_TRUE;
+ dtrc.startThing = startThing;
+ dtrc.thingToFind = thingToFind;
+ dtrc.thingToIgnore = thingToIgnore;
+ dtrc.parentNode = NULL;
+ node = NULL;
+ dtrc.lastNodep = &node;
+ if (!startThing) {
+ JS_ASSERT(startKind == 0);
+ JS_TraceRuntime(&dtrc.base);
+ } else {
+ JS_TraceChildren(&dtrc.base, startThing, startKind);
+ }
+
+ depth = 1;
+ if (!node)
+ goto dump_out;
+
+ thingToFindWasTraced = thingToFind && thingToFind == startThing;
+ for (;;) {
+ /*
+ * Loop must continue even when !dtrc.ok to free all nodes allocated
+ * so far.
+ */
+ if (dtrc.ok) {
+ if (thingToFind == NULL || thingToFind == node->thing)
+ dtrc.ok = DumpNode(&dtrc, fp, node);
+
+ /* Descend into children. */
+ if (dtrc.ok &&
+ depth < maxDepth &&
+ (thingToFind != node->thing || !thingToFindWasTraced)) {
+ dtrc.parentNode = node;
+ children = NULL;
+ dtrc.lastNodep = &children;
+ JS_TraceChildren(&dtrc.base, node->thing, node->kind);
+ if (thingToFind == node->thing)
+ thingToFindWasTraced = JS_TRUE;
+ if (children != NULL) {
+ ++depth;
+ node = children;
+ continue;
+ }
+ }
+ }
+
+ /* Move to next or parents next and free the node. */
+ for (;;) {
+ next = node->next;
+ parent = node->parent;
+ JS_free(cx, node);
+ node = next;
+ if (node)
+ break;
+ if (!parent)
+ goto dump_out;
+ JS_ASSERT(depth > 1);
+ --depth;
+ node = parent;
+ }
+ }
+
+ dump_out:
+ JS_ASSERT(depth == 1);
+ JS_DHashTableFinish(&dtrc.visited);
+ return dtrc.ok;
+}
+
+#endif /* DEBUG */
+
+JS_PUBLIC_API(void)
+JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg)
+{
+ JSTracer *trc;
+
+ trc = (JSTracer *)arg;
+ if (!trc)
+ trc = cx->runtime->gcMarkingTracer;
+ else
+ JS_ASSERT(trc == cx->runtime->gcMarkingTracer);
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->runtime->gcThread == trc->context->thread);
+#endif
+ JS_SET_TRACING_NAME(trc, name ? name : "unknown");
+ js_CallValueTracerIfGCThing(trc, (jsval)thing);
+}
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsGCMarkingTracer(JSTracer *trc)
+{
+ return IS_GC_MARKING_TRACER(trc);
+}
+
+JS_PUBLIC_API(void)
+JS_GC(JSContext *cx)
+{
+ /* Don't nuke active arenas if executing or compiling. */
+ if (cx->stackPool.current == &cx->stackPool.first)
+ JS_FinishArenaPool(&cx->stackPool);
+ if (cx->tempPool.current == &cx->tempPool.first)
+ JS_FinishArenaPool(&cx->tempPool);
+ js_GC(cx, GC_NORMAL);
+}
+
+JS_PUBLIC_API(void)
+JS_MaybeGC(JSContext *cx)
+{
+ JSRuntime *rt;
+ uint32 bytes, lastBytes;
+
+ rt = cx->runtime;
+
+#ifdef JS_GC_ZEAL
+ if (rt->gcZeal > 0) {
+ JS_GC(cx);
+ return;
+ }
+#endif
+
+ bytes = rt->gcBytes;
+ lastBytes = rt->gcLastBytes;
+
+ /*
+ * We run the GC if we used all available free GC cells and had to
+ * allocate extra 1/3 of GC arenas since the last run of GC, or if
+ * we have malloc'd more bytes through JS_malloc than we were told
+ * to allocate by JS_NewRuntime.
+ *
+ * The reason for
+ * bytes > 4/3 lastBytes
+ * condition is the following. Bug 312238 changed bytes and lastBytes
+ * to mean the total amount of memory that the GC uses now and right
+ * after the last GC.
+ *
+ * Before the bug the variables meant the size of allocated GC things
+ * now and right after the last GC. That size did not include the
+ * memory taken by free GC cells and the condition was
+ * bytes > 3/2 lastBytes.
+ * That is, we run the GC if we have half again as many bytes of
+ * GC-things as the last time we GC'd. To be compatible we need to
+ * express that condition through the new meaning of bytes and
+ * lastBytes.
+ *
+ * We write the original condition as
+ * B*(1-F) > 3/2 Bl*(1-Fl)
+ * where B is the total memory size allocated by GC and F is the free
+ * cell density currently and Sl and Fl are the size and the density
+ * right after GC. The density by definition is memory taken by free
+ * cells divided by total amount of memory. In other words, B and Bl
+ * are bytes and lastBytes with the new meaning and B*(1-F) and
+ * Bl*(1-Fl) are bytes and lastBytes with the original meaning.
+ *
+ * Our task is to exclude F and Fl from the last statement. According
+ * to the stats from bug 331966 comment 23, Fl is about 10-25% for a
+ * typical run of the browser. It means that the original condition
+ * implied that we did not run GC unless we exhausted the pool of
+ * free cells. Indeed if we still have free cells, then B == Bl since
+ * we did not yet allocated any new arenas and the condition means
+ * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F
+ * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled
+ * for the state described by the stats. So we can write the original
+ * condition as:
+ * F == 0 && B > 3/2 Bl(1-Fl)
+ * Again using the stats we see that Fl is about 11% when the browser
+ * starts up and when we are far from hitting rt->gcMaxBytes. With
+ * this F we have
+ * F == 0 && B > 3/2 Bl(1-0.11)
+ * or approximately F == 0 && B > 4/3 Bl.
+ */
+ if ((bytes > 8192 && bytes > lastBytes + lastBytes / 3) ||
+ rt->gcMallocBytes >= rt->gcMaxMallocBytes) {
+ JS_GC(cx);
+ }
+}
+
+JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallback(JSContext *cx, JSGCCallback cb)
+{
+ CHECK_REQUEST(cx);
+ return JS_SetGCCallbackRT(cx->runtime, cb);
+}
+
+JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
+{
+ JSGCCallback oldcb;
+
+ oldcb = rt->gcCallback;
+ rt->gcCallback = cb;
+ return oldcb;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsAboutToBeFinalized(JSContext *cx, void *thing)
+{
+ JS_ASSERT(thing);
+ return js_IsAboutToBeFinalized(cx, thing);
+}
+
+JS_PUBLIC_API(void)
+JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value)
+{
+ switch (key) {
+ case JSGC_MAX_BYTES:
+ rt->gcMaxBytes = value;
+ break;
+ case JSGC_MAX_MALLOC_BYTES:
+ rt->gcMaxMallocBytes = value;
+ break;
+ case JSGC_STACKPOOL_LIFESPAN:
+ rt->gcEmptyArenaPoolLifespan = value;
+ break;
+ }
+}
+
+JS_PUBLIC_API(intN)
+JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
+{
+ return js_ChangeExternalStringFinalizer(NULL, finalizer);
+}
+
+JS_PUBLIC_API(intN)
+JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
+{
+ return js_ChangeExternalStringFinalizer(finalizer, NULL);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
+{
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ JS_ASSERT((uintN) type < (uintN) (GCX_NTYPES - GCX_EXTERNAL_STRING));
+
+ str = (JSString *) js_NewGCThing(cx, (uintN) type + GCX_EXTERNAL_STRING,
+ sizeof(JSString));
+ if (!str)
+ return NULL;
+ JSFLATSTR_INIT(str, chars, length);
+ return str;
+}
+
+JS_PUBLIC_API(intN)
+JS_GetExternalStringGCType(JSRuntime *rt, JSString *str)
+{
+ return js_GetExternalStringGCType(str);
+}
+
+JS_PUBLIC_API(void)
+JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
+{
+#if JS_STACK_GROWTH_DIRECTION > 0
+ if (limitAddr == 0)
+ limitAddr = (jsuword)-1;
+#endif
+ cx->stackLimit = limitAddr;
+}
+
+JS_PUBLIC_API(void)
+JS_SetScriptStackQuota(JSContext *cx, size_t quota)
+{
+ cx->scriptStackQuota = quota;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
+{
+ JS_free(cx, ida);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ValueToId(JSContext *cx, jsval v, jsid *idp)
+{
+ CHECK_REQUEST(cx);
+ if (JSVAL_IS_INT(v))
+ *idp = INT_JSVAL_TO_JSID(v);
+#if JS_HAS_XML_SUPPORT
+ else if (!JSVAL_IS_PRIMITIVE(v))
+ *idp = OBJECT_JSVAL_TO_JSID(v);
+#endif
+ else
+ return js_ValueToStringId(cx, v, idp);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ *vp = ID_TO_VALUE(id);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EnumerateStub(JSContext *cx, JSObject *obj)
+{
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id)
+{
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ return js_TryValueOf(cx, obj, type, vp);
+}
+
+JS_PUBLIC_API(void)
+JS_FinalizeStub(JSContext *cx, JSObject *obj)
+{
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+ JSClass *clasp, JSNative constructor, uintN nargs,
+ JSPropertySpec *ps, JSFunctionSpec *fs,
+ JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
+{
+ JSAtom *atom;
+ JSProtoKey key;
+ JSObject *proto, *ctor;
+ JSTempValueRooter tvr;
+ jsval cval, rval;
+ JSBool named;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+ if (!atom)
+ return NULL;
+
+ /*
+ * When initializing a standard class, if no parent_proto (grand-proto of
+ * instances of the class, parent-proto of the class's prototype object)
+ * is given, we must use Object.prototype if it is available. Otherwise,
+ * we could look up the wrong binding for a class name in obj. Example:
+ *
+ * String = Array;
+ * print("hi there".join);
+ *
+ * should print undefined, not Array.prototype.join. This is required by
+ * ECMA-262, alas. It might have been better to make String readonly and
+ * permanent in the global object, instead -- but that's too big a change
+ * to swallow at this point.
+ */
+ key = JSCLASS_CACHED_PROTO_KEY(clasp);
+ if (key != JSProto_Null &&
+ !parent_proto &&
+ !js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
+ &parent_proto)) {
+ return NULL;
+ }
+
+ /* Create a prototype object for this class. */
+ proto = js_NewObject(cx, clasp, parent_proto, obj, 0);
+ if (!proto)
+ return NULL;
+
+ /* After this point, control must exit via label bad or out. */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, proto, &tvr);
+
+ if (!constructor) {
+ /*
+ * Lacking a constructor, name the prototype (e.g., Math) unless this
+ * class (a) is anonymous, i.e. for internal use only; (b) the class
+ * of obj (the global object) is has a reserved slot indexed by key;
+ * and (c) key is not the null key.
+ */
+ if ((clasp->flags & JSCLASS_IS_ANONYMOUS) &&
+ (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) &&
+ key != JSProto_Null) {
+ named = JS_FALSE;
+ } else {
+ named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
+ OBJECT_TO_JSVAL(proto),
+ JS_PropertyStub, JS_PropertyStub,
+ (clasp->flags & JSCLASS_IS_ANONYMOUS)
+ ? JSPROP_READONLY | JSPROP_PERMANENT
+ : 0,
+ NULL);
+ if (!named)
+ goto bad;
+ }
+
+ ctor = proto;
+ } else {
+ /* Define the constructor function in obj's scope. */
+ fun = js_DefineFunction(cx, obj, atom, constructor, nargs,
+ JSFUN_STUB_GSOPS);
+ named = (fun != NULL);
+ if (!fun)
+ goto bad;
+
+ /*
+ * Remember the class this function is a constructor for so that
+ * we know to create an object of this class when we call the
+ * constructor.
+ */
+ FUN_CLASP(fun) = clasp;
+
+ /*
+ * Optionally construct the prototype object, before the class has
+ * been fully initialized. Allow the ctor to replace proto with a
+ * different object, as is done for operator new -- and as at least
+ * XML support requires.
+ */
+ ctor = FUN_OBJECT(fun);
+ if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) {
+ cval = OBJECT_TO_JSVAL(ctor);
+ if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval))
+ goto bad;
+ if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto)
+ proto = JSVAL_TO_OBJECT(rval);
+ }
+
+ /* Connect constructor and prototype by named properties. */
+ if (!js_SetClassPrototype(cx, ctor, proto,
+ JSPROP_READONLY | JSPROP_PERMANENT)) {
+ goto bad;
+ }
+
+ /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */
+ if (OBJ_GET_CLASS(cx, ctor) == clasp) {
+ OBJ_SET_PROTO(cx, ctor, proto);
+ }
+ }
+
+ /* Add properties and methods to the prototype and the constructor. */
+ if ((ps && !JS_DefineProperties(cx, proto, ps)) ||
+ (fs && !JS_DefineFunctions(cx, proto, fs)) ||
+ (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) ||
+ (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) {
+ goto bad;
+ }
+
+ /* If this is a standard class, cache its prototype. */
+ if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor))
+ goto bad;
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return proto;
+
+bad:
+ if (named)
+ (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval);
+ proto = NULL;
+ goto out;
+}
+
+#ifdef JS_THREADSAFE
+JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSContext *cx, JSObject *obj)
+{
+ return OBJ_GET_CLASS(cx, obj);
+}
+#else
+JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSObject *obj)
+{
+ return LOCKED_OBJ_GET_CLASS(obj);
+}
+#endif
+
+JS_PUBLIC_API(JSBool)
+JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv)
+{
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ if (obj && OBJ_GET_CLASS(cx, obj) == clasp)
+ return JS_TRUE;
+ if (argv) {
+ fun = js_ValueToFunction(cx, &argv[-2], 0);
+ if (fun) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ clasp->name, JS_GetFunctionName(fun),
+ obj
+ ? OBJ_GET_CLASS(cx, obj)->name
+ : js_null_str);
+ }
+ }
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ return js_HasInstance(cx, obj, v, bp);
+}
+
+JS_PUBLIC_API(void *)
+JS_GetPrivate(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
+ v = obj->fslots[JSSLOT_PRIVATE];
+ if (!JSVAL_IS_INT(v))
+ return NULL;
+ return JSVAL_TO_PRIVATE(v);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPrivate(JSContext *cx, JSObject *obj, void *data)
+{
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE);
+ obj->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(data);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void *)
+JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+ jsval *argv)
+{
+ if (!JS_InstanceOf(cx, obj, clasp, argv))
+ return NULL;
+ return JS_GetPrivate(cx, obj);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetPrototype(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ CHECK_REQUEST(cx);
+ proto = OBJ_GET_PROTO(cx, obj);
+
+ /* Beware ref to dead object (we may be called from obj's finalizer). */
+ return proto && proto->map ? proto : NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
+{
+ CHECK_REQUEST(cx);
+ JS_ASSERT(obj != proto);
+#ifdef DEBUG
+ /*
+ * FIXME: bug 408416. The cycle-detection required for script-writeable
+ * __proto__ lives in js_SetProtoOrParent over in jsobj.c, also known as
+ * js_ObjectOps.setProto. This hook must detect cycles, to prevent scripts
+ * from ilooping SpiderMonkey trivially. But the overhead of detecting
+ * cycles is high enough, and the threat from JS-API-calling C++ code is
+ * low enough, that it's not worth burdening the non-DEBUG callers. Same
+ * goes for JS_SetParent, below.
+ */
+ if (obj->map->ops->setProto)
+ return obj->map->ops->setProto(cx, obj, JSSLOT_PROTO, proto);
+#else
+ if (OBJ_IS_NATIVE(obj)) {
+ JS_LOCK_OBJ(cx, obj);
+ if (!js_GetMutableScope(cx, obj)) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ LOCKED_OBJ_SET_PROTO(obj, proto);
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+ }
+#endif
+ OBJ_SET_PROTO(cx, obj, proto);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetParent(JSContext *cx, JSObject *obj)
+{
+ JSObject *parent;
+
+ parent = OBJ_GET_PARENT(cx, obj);
+
+ /* Beware ref to dead object (we may be called from obj's finalizer). */
+ return parent && parent->map ? parent : NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ JS_ASSERT(obj != parent);
+#ifdef DEBUG
+ /* FIXME: bug 408416, see JS_SetPrototype just above. */
+ if (obj->map->ops->setParent)
+ return obj->map->ops->setParent(cx, obj, JSSLOT_PARENT, parent);
+#endif
+ OBJ_SET_PARENT(cx, obj, parent);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetConstructor(JSContext *cx, JSObject *proto)
+{
+ jsval cval;
+
+ CHECK_REQUEST(cx);
+ {
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ if (!OBJ_GET_PROPERTY(cx, proto,
+ ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
+ &cval)) {
+ return NULL;
+ }
+ }
+ if (!VALUE_IS_FUNCTION(cx, cval)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR,
+ OBJ_GET_CLASS(cx, proto)->name);
+ return NULL;
+ }
+ return JSVAL_TO_OBJECT(cval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
+{
+ JS_ASSERT(JSID_IS_OBJECT(obj));
+ *idp = OBJECT_TO_JSID(obj);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_NewObject(cx, clasp, proto, parent, 0);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_NewObjectWithGivenProto(cx, clasp, proto, parent, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep)
+{
+ JSScope *scope;
+ JSIdArray *ida;
+ uint32 nslots, i;
+ jsval v;
+
+ if (!OBJ_IS_NATIVE(obj)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_SEAL_OBJECT,
+ OBJ_GET_CLASS(cx, obj)->name);
+ return JS_FALSE;
+ }
+
+ scope = OBJ_SCOPE(obj);
+
+#if defined JS_THREADSAFE && defined DEBUG
+ /* Insist on scope being used exclusively by cx's thread. */
+ if (scope->title.ownercx != cx) {
+ JS_LOCK_OBJ(cx, obj);
+ JS_ASSERT(OBJ_SCOPE(obj) == scope);
+ JS_ASSERT(scope->title.ownercx == cx);
+ JS_UNLOCK_SCOPE(cx, scope);
+ }
+#endif
+
+ /* Nothing to do if obj's scope is already sealed. */
+ if (SCOPE_IS_SEALED(scope))
+ return JS_TRUE;
+
+ /* XXX Enumerate lazy properties now, as they can't be added later. */
+ ida = JS_Enumerate(cx, obj);
+ if (!ida)
+ return JS_FALSE;
+ JS_DestroyIdArray(cx, ida);
+
+ /* Ensure that obj has its own, mutable scope, and seal that scope. */
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (scope) {
+ SCOPE_SET_SEALED(scope);
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!scope)
+ return JS_FALSE;
+
+ /* If we are not sealing an entire object graph, we're done. */
+ if (!deep)
+ return JS_TRUE;
+
+ /* Walk slots in obj and if any value is a non-null object, seal it. */
+ nslots = scope->map.freeslot;
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_PRIMITIVE(v))
+ continue;
+ if (!JS_SealObject(cx, JSVAL_TO_OBJECT(v), deep))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_ConstructObject(cx, clasp, proto, parent, 0, NULL);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv)
+{
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ return js_ConstructObject(cx, clasp, proto, parent, argc, argv);
+}
+
+static JSBool
+DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN tinyid)
+{
+ if (flags != 0 && OBJ_IS_NATIVE(obj)) {
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
+ return js_DefineNativeProperty(cx, obj, id, value, getter, setter,
+ attrs, flags, tinyid, NULL);
+ }
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, value, getter, setter, attrs,
+ NULL);
+}
+
+static JSBool
+DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN tinyid)
+{
+ jsid id;
+ JSAtom *atom;
+
+ if (attrs & JSPROP_INDEX) {
+ id = INT_TO_JSID(JS_PTR_TO_INT32(name));
+ atom = NULL;
+ attrs &= ~JSPROP_INDEX;
+ } else {
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ id = ATOM_TO_JSID(atom);
+ }
+ return DefinePropertyById(cx, obj, id, value, getter, setter, attrs,
+ flags, tinyid);
+}
+
+#define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n))
+
+static JSBool
+DefineUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN tinyid)
+{
+ JSAtom *atom;
+
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+ if (flags != 0 && OBJ_IS_NATIVE(obj)) {
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
+ return js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
+ getter, setter, attrs, flags, tinyid,
+ NULL);
+ }
+ return OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), value,
+ getter, setter, attrs, NULL);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+ JSObject *proto, uintN attrs)
+{
+ JSObject *nobj;
+
+ CHECK_REQUEST(cx);
+ if (!clasp)
+ clasp = &js_ObjectClass; /* default class is Object */
+ nobj = js_NewObject(cx, clasp, proto, obj, 0);
+ if (!nobj)
+ return NULL;
+ if (!DefineProperty(cx, obj, name, OBJECT_TO_JSVAL(nobj), NULL, NULL, attrs,
+ 0, 0)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+ return nobj;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
+{
+ JSBool ok;
+ jsval value;
+ uintN attrs;
+
+ CHECK_REQUEST(cx);
+ for (ok = JS_TRUE; cds->name; cds++) {
+ ok = js_NewNumberInRootedValue(cx, cds->dval, &value);
+ if (!ok)
+ break;
+ attrs = cds->flags;
+ if (!attrs)
+ attrs = JSPROP_READONLY | JSPROP_PERMANENT;
+ ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, attrs, 0, 0);
+ if (!ok)
+ break;
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ for (ok = JS_TRUE; ps->name; ps++) {
+ ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
+ ps->getter, ps->setter, ps->flags,
+ SPROP_HAS_SHORTID, ps->tinyid);
+ if (!ok)
+ break;
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineProperty(cx, obj, name, value, getter, setter, attrs, 0, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, 0, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineProperty(cx, obj, name, value, getter, setter, attrs,
+ SPROP_HAS_SHORTID, tinyid);
+}
+
+static JSBool
+LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSAutoResolveFlags rf(cx, flags);
+ return OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, propp);
+}
+
+static JSBool
+LookupProperty(JSContext *cx, JSObject *obj, const char *name, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSAtom *atom;
+
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ return LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), flags, objp, propp);
+}
+
+static JSBool
+LookupUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSAtom *atom;
+
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+ return LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), flags, objp, propp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+ const char *alias)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSAtom *atom;
+ JSBool ok;
+ JSScopeProperty *sprop;
+
+ CHECK_REQUEST(cx);
+ if (!LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ js_ReportIsNotDefined(cx, name);
+ return JS_FALSE;
+ }
+ if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
+ alias, name, OBJ_GET_CLASS(cx, obj2)->name);
+ return JS_FALSE;
+ }
+ atom = js_Atomize(cx, alias, strlen(alias), 0);
+ if (!atom) {
+ ok = JS_FALSE;
+ } else {
+ sprop = (JSScopeProperty *)prop;
+ ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
+ sprop->getter, sprop->setter, sprop->slot,
+ sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
+ sprop->shortid)
+ != NULL);
+ }
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+static jsval
+LookupResult(JSContext *cx, JSObject *obj, JSObject *obj2, JSProperty *prop)
+{
+ JSScopeProperty *sprop;
+ jsval rval;
+
+ if (!prop) {
+ /* XXX bad API: no way to tell "not defined" from "void value" */
+ return JSVAL_VOID;
+ }
+ if (OBJ_IS_NATIVE(obj2)) {
+ /* Peek at the native property's slot value, without doing a Get. */
+ sprop = (JSScopeProperty *)prop;
+ rval = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj2))
+ ? LOCKED_OBJ_GET_SLOT(obj2, sprop->slot)
+ : JSVAL_TRUE;
+ } else {
+ /* XXX bad API: no way to return "defined but value unknown" */
+ rval = JSVAL_TRUE;
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return rval;
+}
+
+static JSBool
+GetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp, JSPropertyOp *setterp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSBool ok;
+
+ if (!atom)
+ return JS_FALSE;
+ if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED,
+ &obj2, &prop)) {
+ return JS_FALSE;
+ }
+
+ if (!prop || obj != obj2) {
+ *attrsp = 0;
+ *foundp = JS_FALSE;
+ if (getterp)
+ *getterp = NULL;
+ if (setterp)
+ *setterp = NULL;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+ }
+
+ *foundp = JS_TRUE;
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, attrsp);
+ if (ok && OBJ_IS_NATIVE(obj)) {
+ JSScopeProperty *sprop = (JSScopeProperty *) prop;
+
+ if (getterp)
+ *getterp = sprop->getter;
+ if (setterp)
+ *setterp = sprop->setter;
+ }
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+static JSBool
+SetPropertyAttributes(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN attrs, JSBool *foundp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSBool ok;
+
+ if (!atom)
+ return JS_FALSE;
+ if (!LookupPropertyById(cx, obj, ATOM_TO_JSID(atom), JSRESOLVE_QUALIFIED,
+ &obj2, &prop)) {
+ return JS_FALSE;
+ }
+ if (!prop || obj != obj2) {
+ *foundp = JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+ }
+
+ *foundp = JS_TRUE;
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop, &attrs);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN *attrsp, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_Atomize(cx, name, strlen(name), 0),
+ attrsp, foundp, NULL, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const char *name,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_Atomize(cx, name, strlen(name), 0),
+ attrsp, foundp, getterp, setterp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN attrs, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return SetPropertyAttributes(cx, obj,
+ js_Atomize(cx, name, strlen(name), 0),
+ attrs, foundp);
+}
+
+static JSBool
+AlreadyHasOwnPropertyHelper(JSContext *cx, JSObject *obj, jsid id,
+ JSBool *foundp)
+{
+ JSScope *scope;
+
+ if (!OBJ_IS_NATIVE(obj)) {
+ JSObject *obj2;
+ JSProperty *prop;
+
+ if (!LookupPropertyById(cx, obj, id,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop)) {
+ return JS_FALSE;
+ }
+ *foundp = (obj == obj2);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+ }
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ *foundp = (scope->object == obj && SCOPE_GET_PROPERTY(scope, id));
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name,
+ JSBool *foundp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ return AlreadyHasOwnPropertyHelper(cx, obj, ATOM_TO_JSID(atom), foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id,
+ JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return AlreadyHasOwnPropertyHelper(cx, obj, id, foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupProperty(cx, obj, name,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *foundp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, id,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *foundp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+ uintN flags, jsval *vp)
+{
+ JSAtom *atom;
+ JSObject *obj2;
+
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ return atom &&
+ JS_LookupPropertyWithFlagsById(cx, obj, ATOM_TO_JSID(atom), flags,
+ &obj2, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id,
+ uintN flags, JSObject **objp, jsval *vp)
+{
+ JSBool ok;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = OBJ_IS_NATIVE(obj)
+ ? js_LookupPropertyWithFlags(cx, obj, id, flags, objp, &prop) >= 0
+ : OBJ_LOOKUP_PROPERTY(cx, obj, id, objp, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, *objp, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_GET_PROPERTY(cx, obj, id, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ jsval *vp)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ CHECK_REQUEST(cx);
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, vp);
+ if (!obj)
+ return JS_FALSE;
+ } else
+#endif
+ {
+ if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
+ return JS_FALSE;
+ }
+
+ *objp = obj;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+ jsval *vp)
+{
+ JSAtom *atom;
+
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ return JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), objp, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, obj, id, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name)
+{
+ jsval junk;
+
+ return JS_DeleteProperty2(cx, obj, name, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+ jsval *rval)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id)
+{
+ jsval junk;
+
+ return JS_DeletePropertyById2(cx, obj, id, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ CHECK_REQUEST(cx);
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_DELETE_PROPERTY(cx, obj, id, rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
+ attrs, 0, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+ attrsp, foundp, NULL, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp)
+{
+ CHECK_REQUEST(cx);
+ return GetPropertyAttributes(cx, obj,
+ js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+ attrsp, foundp, getterp, setterp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN attrs, JSBool *foundp)
+{
+ CHECK_REQUEST(cx);
+ return SetPropertyAttributes(cx, obj,
+ js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0),
+ attrs, foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs)
+{
+ CHECK_REQUEST(cx);
+ return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
+ attrs, SPROP_HAS_SHORTID, tinyid);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ JSBool *foundp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+ return AlreadyHasOwnPropertyHelper(cx, obj, ATOM_TO_JSID(atom), foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ JSBool *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupUCProperty(cx, obj, name, namelen,
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *vp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupUCProperty(cx, obj, name, namelen, JSRESOLVE_QUALIFIED,
+ &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *rval)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return JS_FALSE;
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+ return OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector)
+{
+ CHECK_REQUEST(cx);
+ /* NB: jsuint cast does ToUint32. */
+ return js_NewArrayObject(cx, (jsuint)length, vector);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsArrayObject(JSContext *cx, JSObject *obj)
+{
+ return OBJ_IS_ARRAY(cx, obj);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ CHECK_REQUEST(cx);
+ return js_GetLengthProperty(cx, obj, lengthp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length)
+{
+ CHECK_REQUEST(cx);
+ return js_SetLengthProperty(cx, obj, length);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ CHECK_REQUEST(cx);
+ return js_HasLengthProperty(cx, obj, lengthp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
+
+ CHECK_REQUEST(cx);
+ return OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(index), value,
+ getter, setter, attrs, NULL);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ if (!LookupProperty(cx, obj, name, JSRESOLVE_QUALIFIED, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ js_ReportIsNotDefined(cx, name);
+ return JS_FALSE;
+ }
+ if (obj2 != obj || !OBJ_IS_NATIVE(obj)) {
+ char numBuf[12];
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)alias);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_ALIAS,
+ numBuf, name, OBJ_GET_CLASS(cx, obj2)->name);
+ return JS_FALSE;
+ }
+ sprop = (JSScopeProperty *)prop;
+ ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
+ sprop->getter, sprop->setter, sprop->slot,
+ sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
+ sprop->shortid)
+ != NULL);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, jsint index,
+ JSBool *foundp)
+{
+ return AlreadyHasOwnPropertyHelper(cx, obj, INT_TO_JSID(index), foundp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, INT_TO_JSID(index),
+ JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
+ &obj2, &prop);
+ if (ok) {
+ *foundp = (prop != NULL);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+{
+ JSBool ok;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ CHECK_REQUEST(cx);
+ ok = LookupPropertyById(cx, obj, INT_TO_JSID(index), JSRESOLVE_QUALIFIED,
+ &obj2, &prop);
+ if (ok)
+ *vp = LookupResult(cx, obj, obj2, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ CHECK_REQUEST(cx);
+ return OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+
+ CHECK_REQUEST(cx);
+ return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(index), vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index)
+{
+ jsval junk;
+
+ return JS_DeleteElement2(cx, obj, index, &junk);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval)
+{
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED);
+
+ CHECK_REQUEST(cx);
+ return OBJ_DELETE_PROPERTY(cx, obj, INT_TO_JSID(index), rval);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearScope(JSContext *cx, JSObject *obj)
+{
+ CHECK_REQUEST(cx);
+
+ if (obj->map->ops->clear)
+ obj->map->ops->clear(cx, obj);
+
+ /* Clear cached class objects on the global object. */
+ if (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) {
+ int key;
+
+ for (key = JSProto_Null; key < JSProto_LIMIT; key++)
+ JS_SetReservedSlot(cx, obj, key, JSVAL_VOID);
+ }
+}
+
+JS_PUBLIC_API(JSIdArray *)
+JS_Enumerate(JSContext *cx, JSObject *obj)
+{
+ jsint i, n;
+ jsval iter_state, num_properties;
+ jsid id;
+ JSIdArray *ida;
+ jsval *vector;
+
+ CHECK_REQUEST(cx);
+
+ ida = NULL;
+ iter_state = JSVAL_NULL;
+
+ /* Get the number of properties to enumerate. */
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties))
+ goto error;
+ if (!JSVAL_IS_INT(num_properties)) {
+ JS_ASSERT(0);
+ goto error;
+ }
+
+ /* Grow as needed if we don't know the exact amount ahead of time. */
+ n = JSVAL_TO_INT(num_properties);
+ if (n <= 0)
+ n = 8;
+
+ /* Create an array of jsids large enough to hold all the properties */
+ ida = NewIdArray(cx, n);
+ if (!ida)
+ goto error;
+
+ i = 0;
+ vector = &ida->vector[0];
+ for (;;) {
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &iter_state, &id))
+ goto error;
+
+ /* No more jsid's to enumerate ? */
+ if (iter_state == JSVAL_NULL)
+ break;
+
+ if (i == ida->length) {
+ ida = SetIdArrayLength(cx, ida, ida->length * 2);
+ if (!ida)
+ goto error;
+ vector = &ida->vector[0];
+ }
+ vector[i++] = id;
+ }
+ return SetIdArrayLength(cx, ida, i);
+
+error:
+ if (iter_state != JSVAL_NULL)
+ OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
+ if (ida)
+ JS_DestroyIdArray(cx, ida);
+ return NULL;
+}
+
+/*
+ * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
+ * prop_iterator_class somehow...
+ * + preserve the OBJ_ENUMERATE API while optimizing the native object case
+ * + native case here uses a JSScopeProperty *, but that iterates in reverse!
+ * + so we make non-native match, by reverse-iterating after JS_Enumerating
+ */
+#define JSSLOT_ITER_INDEX (JSSLOT_PRIVATE + 1)
+
+#if JSSLOT_ITER_INDEX >= JS_INITIAL_NSLOTS
+# error "JSSLOT_ITER_INDEX botch!"
+#endif
+
+static void
+prop_iter_finalize(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+ jsint i;
+ JSIdArray *ida;
+
+ v = obj->fslots[JSSLOT_ITER_INDEX];
+ if (JSVAL_IS_VOID(v))
+ return;
+
+ i = JSVAL_TO_INT(v);
+ if (i >= 0) {
+ /* Non-native case: destroy the ida enumerated when obj was created. */
+ ida = (JSIdArray *) JS_GetPrivate(cx, obj);
+ if (ida)
+ JS_DestroyIdArray(cx, ida);
+ }
+}
+
+static void
+prop_iter_trace(JSTracer *trc, JSObject *obj)
+{
+ jsval v;
+ jsint i, n;
+ JSScopeProperty *sprop;
+ JSIdArray *ida;
+ jsid id;
+
+ v = obj->fslots[JSSLOT_PRIVATE];
+ JS_ASSERT(!JSVAL_IS_VOID(v));
+
+ i = JSVAL_TO_INT(obj->fslots[JSSLOT_ITER_INDEX]);
+ if (i < 0) {
+ /* Native case: just mark the next property to visit. */
+ sprop = (JSScopeProperty *) JSVAL_TO_PRIVATE(v);
+ if (sprop)
+ TRACE_SCOPE_PROPERTY(trc, sprop);
+ } else {
+ /* Non-native case: mark each id in the JSIdArray private. */
+ ida = (JSIdArray *) JSVAL_TO_PRIVATE(v);
+ for (i = 0, n = ida->length; i < n; i++) {
+ id = ida->vector[i];
+ TRACE_ID(trc, id);
+ }
+ }
+}
+
+static JSClass prop_iter_class = {
+ "PropertyIterator",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, prop_iter_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(prop_iter_trace), NULL
+};
+
+JS_PUBLIC_API(JSObject *)
+JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
+{
+ JSObject *iterobj;
+ JSScope *scope;
+ void *pdata;
+ jsint index;
+ JSIdArray *ida;
+
+ CHECK_REQUEST(cx);
+ iterobj = js_NewObject(cx, &prop_iter_class, NULL, obj, 0);
+ if (!iterobj)
+ return NULL;
+
+ if (OBJ_IS_NATIVE(obj)) {
+ /* Native case: start with the last property in obj's own scope. */
+ scope = OBJ_SCOPE(obj);
+ pdata = (scope->object == obj) ? scope->lastProp : NULL;
+ index = -1;
+ } else {
+ JSTempValueRooter tvr;
+
+ /*
+ * Non-native case: enumerate a JSIdArray and keep it via private.
+ *
+ * Note: we have to make sure that we root obj around the call to
+ * JS_Enumerate to protect against multiple allocations under it.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(iterobj), &tvr);
+ ida = JS_Enumerate(cx, obj);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ida)
+ goto bad;
+ pdata = ida;
+ index = ida->length;
+ }
+
+ /* iterobj can not escape to other threads here. */
+ STOBJ_SET_SLOT(iterobj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(pdata));
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(index));
+ return iterobj;
+
+bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
+{
+ jsint i;
+ JSObject *obj;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+ JSIdArray *ida;
+
+ CHECK_REQUEST(cx);
+ i = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_INDEX));
+ if (i < 0) {
+ /* Native case: private data is a property tree node pointer. */
+ obj = OBJ_GET_PARENT(cx, iterobj);
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(scope->object == obj);
+ sprop = (JSScopeProperty *) JS_GetPrivate(cx, iterobj);
+
+ /*
+ * If the next property mapped by scope in the property tree ancestor
+ * line is not enumerable, or it's an alias, or one or more properties
+ * were deleted from the "middle" of the scope-mapped ancestor line
+ * and the next property was among those deleted, skip it and keep on
+ * trying to find an enumerable property that is still in scope.
+ */
+ while (sprop &&
+ (!(sprop->attrs & JSPROP_ENUMERATE) ||
+ (sprop->flags & SPROP_IS_ALIAS) ||
+ (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ !SCOPE_HAS_PROPERTY(scope, sprop)))) {
+ sprop = sprop->parent;
+ }
+
+ if (!sprop) {
+ *idp = JSVAL_VOID;
+ } else {
+ if (!JS_SetPrivate(cx, iterobj, sprop->parent))
+ return JS_FALSE;
+ *idp = sprop->id;
+ }
+ } else {
+ /* Non-native case: use the ida enumerated when iterobj was created. */
+ ida = (JSIdArray *) JS_GetPrivate(cx, iterobj);
+ JS_ASSERT(i <= ida->length);
+ if (i == 0) {
+ *idp = JSVAL_VOID;
+ } else {
+ *idp = ida->vector[--i];
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_INDEX, INT_TO_JSVAL(i));
+ }
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp)
+{
+ CHECK_REQUEST(cx);
+ return OBJ_CHECK_ACCESS(cx, obj, id, mode, vp, attrsp);
+}
+
+static JSBool
+ReservedSlotIndexOK(JSContext *cx, JSObject *obj, JSClass *clasp,
+ uint32 index, uint32 limit)
+{
+ /* Check the computed, possibly per-instance, upper bound. */
+ if (clasp->reserveSlots)
+ JS_LOCK_OBJ_VOID(cx, obj, limit += clasp->reserveSlots(cx, obj));
+ if (index >= limit) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_RESERVED_SLOT_RANGE);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp)
+{
+ JSClass *clasp;
+ uint32 limit, slot;
+
+ CHECK_REQUEST(cx);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ limit = JSCLASS_RESERVED_SLOTS(clasp);
+ if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
+ return JS_FALSE;
+ slot = JSSLOT_START(clasp) + index;
+ *vp = OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v)
+{
+ JSClass *clasp;
+ uint32 limit, slot;
+
+ CHECK_REQUEST(cx);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ limit = JSCLASS_RESERVED_SLOTS(clasp);
+ if (index >= limit && !ReservedSlotIndexOK(cx, obj, clasp, index, limit))
+ return JS_FALSE;
+ slot = JSSLOT_START(clasp) + index;
+ return OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
+}
+
+#ifdef JS_THREADSAFE
+JS_PUBLIC_API(jsrefcount)
+JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals)
+{
+ return JS_ATOMIC_INCREMENT(&principals->refcount);
+}
+
+JS_PUBLIC_API(jsrefcount)
+JS_DropPrincipals(JSContext *cx, JSPrincipals *principals)
+{
+ jsrefcount rc = JS_ATOMIC_DECREMENT(&principals->refcount);
+ if (rc == 0)
+ principals->destroy(cx, principals);
+ return rc;
+}
+#endif
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks)
+{
+ JSSecurityCallbacks *oldcallbacks;
+
+ oldcallbacks = rt->securityCallbacks;
+ rt->securityCallbacks = callbacks;
+ return oldcallbacks;
+}
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetRuntimeSecurityCallbacks(JSRuntime *rt)
+{
+ return rt->securityCallbacks;
+}
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks)
+{
+ JSSecurityCallbacks *oldcallbacks;
+
+ oldcallbacks = cx->securityCallbacks;
+ cx->securityCallbacks = callbacks;
+ return oldcallbacks;
+}
+
+JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetSecurityCallbacks(JSContext *cx)
+{
+ return cx->securityCallbacks
+ ? cx->securityCallbacks
+ : cx->runtime->securityCallbacks;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_NewFunction(JSContext *cx, JSNative native, uintN nargs, uintN flags,
+ JSObject *parent, const char *name)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+
+ if (!name) {
+ atom = NULL;
+ } else {
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return NULL;
+ }
+ return js_NewFunction(cx, NULL, native, nargs, flags, parent, atom);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
+{
+ CHECK_REQUEST(cx);
+ if (OBJ_GET_CLASS(cx, funobj) != &js_FunctionClass) {
+ /* Indicate we cannot clone this object. */
+ return funobj;
+ }
+ return js_CloneFunctionObject(cx, GET_FUNCTION_PRIVATE(cx, funobj), parent);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFunctionObject(JSFunction *fun)
+{
+ return FUN_OBJECT(fun);
+}
+
+JS_PUBLIC_API(const char *)
+JS_GetFunctionName(JSFunction *fun)
+{
+ return fun->atom
+ ? JS_GetStringBytes(ATOM_TO_STRING(fun->atom))
+ : js_anonymous_str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_GetFunctionId(JSFunction *fun)
+{
+ return fun->atom ? ATOM_TO_STRING(fun->atom) : NULL;
+}
+
+JS_PUBLIC_API(uintN)
+JS_GetFunctionFlags(JSFunction *fun)
+{
+#ifdef MOZILLA_1_8_BRANCH
+ uintN flags = fun->flags;
+
+ return JSFUN_DISJOINT_FLAGS(flags) |
+ (JSFUN_GETTER_TEST(flags) ? JSFUN_GETTER : 0) |
+ (JSFUN_SETTER_TEST(flags) ? JSFUN_SETTER : 0) |
+ (JSFUN_BOUND_METHOD_TEST(flags) ? JSFUN_BOUND_METHOD : 0) |
+ (JSFUN_HEAVYWEIGHT_TEST(flags) ? JSFUN_HEAVYWEIGHT : 0);
+#else
+ return fun->flags;
+#endif
+}
+
+JS_PUBLIC_API(uint16)
+JS_GetFunctionArity(JSFunction *fun)
+{
+ return fun->nargs;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
+{
+ return OBJ_GET_CLASS(cx, obj) == &js_FunctionClass;
+}
+
+JS_BEGIN_EXTERN_C
+static JSBool
+js_generic_fast_native_method_dispatcher(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval fsv;
+ JSFunctionSpec *fs;
+ JSObject *tmp;
+ JSFastNative native;
+
+ if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(*vp), 0, &fsv))
+ return JS_FALSE;
+ fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
+ JS_ASSERT((~fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) == 0);
+
+ /*
+ * We know that vp[2] is valid because JS_DefineFunctions, which is our
+ * only (indirect) referrer, defined us as requiring at least one argument
+ * (notice how it passes fs->nargs + 1 as the next-to-last argument to
+ * JS_DefineFunction).
+ */
+ if (JSVAL_IS_PRIMITIVE(vp[2])) {
+ /*
+ * Make sure that this is an object or null, as required by the generic
+ * functions.
+ */
+ if (!js_ValueToObject(cx, vp[2], &tmp))
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(tmp);
+ }
+
+ /*
+ * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
+ * which is almost always the class constructor object, e.g. Array. Then
+ * call the corresponding prototype native method with our first argument
+ * passed as |this|.
+ */
+ memmove(vp + 1, vp + 2, argc * sizeof(jsval));
+
+ /*
+ * Follow Function.prototype.apply and .call by using the global object as
+ * the 'this' param if no args.
+ */
+ if (!js_ComputeThis(cx, JS_FALSE, vp + 2))
+ return JS_FALSE;
+ /*
+ * Protect against argc underflowing. By calling js_ComputeThis, we made
+ * it as if the static was called with one parameter, the explicit |this|
+ * object.
+ */
+ if (argc != 0)
+ --argc;
+
+ native =
+#ifdef JS_TRACER
+ (fs->flags & JSFUN_TRACEABLE)
+ ? ((JSTraceableNative *) fs->call)->native
+ :
+#endif
+ (JSFastNative) fs->call;
+ return native(cx, argc, vp);
+}
+
+static JSBool
+js_generic_native_method_dispatcher(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ jsval fsv;
+ JSFunctionSpec *fs;
+ JSObject *tmp;
+
+ if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), 0, &fsv))
+ return JS_FALSE;
+ fs = (JSFunctionSpec *) JSVAL_TO_PRIVATE(fsv);
+ JS_ASSERT((fs->flags & (JSFUN_FAST_NATIVE | JSFUN_GENERIC_NATIVE)) ==
+ JSFUN_GENERIC_NATIVE);
+
+ /*
+ * We know that argv[0] is valid because JS_DefineFunctions, which is our
+ * only (indirect) referrer, defined us as requiring at least one argument
+ * (notice how it passes fs->nargs + 1 as the next-to-last argument to
+ * JS_DefineFunction).
+ */
+ if (JSVAL_IS_PRIMITIVE(argv[0])) {
+ /*
+ * Make sure that this is an object or null, as required by the generic
+ * functions.
+ */
+ if (!js_ValueToObject(cx, argv[0], &tmp))
+ return JS_FALSE;
+ argv[0] = OBJECT_TO_JSVAL(tmp);
+ }
+
+ /*
+ * Copy all actual (argc) arguments down over our |this| parameter,
+ * argv[-1], which is almost always the class constructor object, e.g.
+ * Array. Then call the corresponding prototype native method with our
+ * first argument passed as |this|.
+ */
+ memmove(argv - 1, argv, argc * sizeof(jsval));
+
+ /*
+ * Follow Function.prototype.apply and .call by using the global object as
+ * the 'this' param if no args.
+ */
+ JS_ASSERT(cx->fp->argv == argv);
+ if (!js_ComputeThis(cx, JS_TRUE, argv))
+ return JS_FALSE;
+ cx->fp->thisp = JSVAL_TO_OBJECT(argv[-1]);
+
+ /*
+ * Protect against argc underflowing. By calling js_ComputeThis, we made
+ * it as if the static was called with one parameter, the explicit |this|
+ * object.
+ */
+ if (argc != 0)
+ --argc;
+
+ return fs->call(cx, JSVAL_TO_OBJECT(argv[-1]), argc, argv, rval);
+}
+JS_END_EXTERN_C
+
+JS_PUBLIC_API(JSBool)
+JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs)
+{
+ uintN flags;
+ JSObject *ctor;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ ctor = NULL;
+ for (; fs->name; fs++) {
+ flags = fs->flags;
+
+ /*
+ * Define a generic arity N+1 static method for the arity N prototype
+ * method if flags contains JSFUN_GENERIC_NATIVE.
+ */
+ if (flags & JSFUN_GENERIC_NATIVE) {
+ if (!ctor) {
+ ctor = JS_GetConstructor(cx, obj);
+ if (!ctor)
+ return JS_FALSE;
+ }
+
+ flags &= ~JSFUN_GENERIC_NATIVE;
+ fun = JS_DefineFunction(cx, ctor, fs->name,
+ (flags & JSFUN_FAST_NATIVE)
+ ? (JSNative)
+ js_generic_fast_native_method_dispatcher
+ : js_generic_native_method_dispatcher,
+ fs->nargs + 1,
+ flags & ~JSFUN_TRACEABLE);
+ if (!fun)
+ return JS_FALSE;
+ fun->u.n.extra = (uint16)fs->extra;
+
+ /*
+ * As jsapi.h notes, fs must point to storage that lives as long
+ * as fun->object lives.
+ */
+ if (!JS_SetReservedSlot(cx, FUN_OBJECT(fun), 0, PRIVATE_TO_JSVAL(fs)))
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(!(flags & JSFUN_FAST_NATIVE) ||
+ (uint16)(fs->extra >> 16) <= fs->nargs);
+ fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, flags);
+ if (!fun)
+ return JS_FALSE;
+ fun->u.n.extra = (uint16)fs->extra;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+ uintN nargs, uintN attrs)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return NULL;
+ return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, JSNative call,
+ uintN nargs, uintN attrs)
+{
+ JSAtom *atom;
+
+ atom = js_AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen), 0);
+ if (!atom)
+ return NULL;
+ return js_DefineFunction(cx, obj, atom, call, nargs, attrs);
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileScript(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ script = JS_CompileUCScript(cx, obj, chars, length, filename, lineno);
+ JS_free(cx, chars);
+ return script;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ script = JS_CompileUCScriptForPrincipals(cx, obj, principals,
+ chars, length, filename, lineno);
+ JS_free(cx, chars);
+ return script;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ CHECK_REQUEST(cx);
+ return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length,
+ filename, lineno);
+}
+
+#define LAST_FRAME_EXCEPTION_CHECK(cx,result) \
+ JS_BEGIN_MACRO \
+ if (!(result) && !((cx)->options & JSOPTION_DONT_REPORT_UNCAUGHT)) \
+ js_ReportUncaughtException(cx); \
+ JS_END_MACRO
+
+#define LAST_FRAME_CHECKS(cx,result) \
+ JS_BEGIN_MACRO \
+ if (!(cx)->fp) { \
+ (cx)->weakRoots.lastInternalResult = JSVAL_NULL; \
+ LAST_FRAME_EXCEPTION_CHECK(cx, result); \
+ } \
+ JS_END_MACRO
+
+#define JS_OPTIONS_TO_TCFLAGS(cx) \
+ ((((cx)->options & JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) | \
+ (((cx)->options & JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0))
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ uint32 tcflags;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
+ script = js_CompileScript(cx, obj, NULL, principals, tcflags,
+ chars, length, NULL, filename, lineno);
+ LAST_FRAME_CHECKS(cx, script);
+ return script;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length)
+{
+ jschar *chars;
+ JSBool result;
+ JSExceptionState *exnState;
+ JSParseContext pc;
+ JSErrorReporter older;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return JS_TRUE;
+
+ /*
+ * Return true on any out-of-memory error, so our caller doesn't try to
+ * collect more buffered source.
+ */
+ result = JS_TRUE;
+ exnState = JS_SaveExceptionState(cx);
+ if (js_InitParseContext(cx, &pc, NULL, NULL, chars, length, NULL, NULL,
+ 1)) {
+ older = JS_SetErrorReporter(cx, NULL);
+ if (!js_ParseScript(cx, obj, &pc) &&
+ (pc.tokenStream.flags & TSF_UNEXPECTED_EOF)) {
+ /*
+ * We ran into an error. If it was because we ran out of source,
+ * we return false, so our caller will know to try to collect more
+ * buffered source.
+ */
+ result = JS_FALSE;
+ }
+ JS_SetErrorReporter(cx, older);
+ js_FinishParseContext(cx, &pc);
+ }
+ JS_free(cx, chars);
+ JS_RestoreExceptionState(cx, exnState);
+ return result;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
+{
+ FILE *fp;
+ uint32 tcflags;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ if (!filename || strcmp(filename, "-") == 0) {
+ fp = stdin;
+ } else {
+ fp = fopen(filename, "r");
+ if (!fp) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
+ filename, "No such file or directory");
+ return NULL;
+ }
+ }
+
+ tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
+ script = js_CompileScript(cx, obj, NULL, NULL, tcflags,
+ NULL, 0, fp, filename, 1);
+ if (fp != stdin)
+ fclose(fp);
+ LAST_FRAME_CHECKS(cx, script);
+ return script;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+ FILE *file)
+{
+ return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+ const char *filename, FILE *file,
+ JSPrincipals *principals)
+{
+ uint32 tcflags;
+ JSScript *script;
+
+ CHECK_REQUEST(cx);
+ tcflags = JS_OPTIONS_TO_TCFLAGS(cx);
+ script = js_CompileScript(cx, obj, NULL, principals, tcflags,
+ NULL, 0, file, filename, 1);
+ LAST_FRAME_CHECKS(cx, script);
+ return script;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewScriptObject(JSContext *cx, JSScript *script)
+{
+ JSTempValueRooter tvr;
+ JSObject *obj;
+
+ CHECK_REQUEST(cx);
+ if (!script)
+ return js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
+
+ JS_ASSERT(!script->u.object);
+
+ JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
+ obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
+ if (obj) {
+ JS_SetPrivate(cx, obj, script);
+ script->u.object = obj;
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = NULL;
+#endif
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetScriptObject(JSScript *script)
+{
+ return script->u.object;
+}
+
+JS_PUBLIC_API(void)
+JS_DestroyScript(JSContext *cx, JSScript *script)
+{
+ CHECK_REQUEST(cx);
+ js_DestroyScript(cx, script);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ fun = JS_CompileUCFunction(cx, obj, name, nargs, argnames, chars, length,
+ filename, lineno);
+ JS_free(cx, chars);
+ return fun;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno)
+{
+ jschar *chars;
+ JSFunction *fun;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ fun = JS_CompileUCFunctionForPrincipals(cx, obj, principals, name,
+ nargs, argnames, chars, length,
+ filename, lineno);
+ JS_free(cx, chars);
+ return fun;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ CHECK_REQUEST(cx);
+ return JS_CompileUCFunctionForPrincipals(cx, obj, NULL, name,
+ nargs, argnames,
+ chars, length,
+ filename, lineno);
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ JSFunction *fun;
+ JSTempValueRooter tvr;
+ JSAtom *funAtom, *argAtom;
+ uintN i;
+
+ CHECK_REQUEST(cx);
+ if (!name) {
+ funAtom = NULL;
+ } else {
+ funAtom = js_Atomize(cx, name, strlen(name), 0);
+ if (!funAtom) {
+ fun = NULL;
+ goto out2;
+ }
+ }
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, obj, funAtom);
+ if (!fun)
+ goto out2;
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
+ for (i = 0; i < nargs; i++) {
+ argAtom = js_Atomize(cx, argnames[i], strlen(argnames[i]), 0);
+ if (!argAtom) {
+ fun = NULL;
+ goto out;
+ }
+ if (!js_AddLocal(cx, fun, argAtom, JSLOCAL_ARG)) {
+ fun = NULL;
+ goto out;
+ }
+ }
+
+ if (!js_CompileFunctionBody(cx, fun, principals, chars, length,
+ filename, lineno)) {
+ fun = NULL;
+ goto out;
+ }
+
+ if (obj &&
+ funAtom &&
+ !OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(funAtom),
+ OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
+ NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+ fun = NULL;
+ }
+
+#ifdef JS_SCOPE_DEPTH_METER
+ if (fun && obj) {
+ JSObject *pobj = obj;
+ uintN depth = 1;
+
+ while ((pobj = OBJ_GET_PARENT(cx, pobj)) != NULL)
+ ++depth;
+ JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth);
+ }
+#endif
+
+ out:
+ cx->weakRoots.newborn[JSTRACE_OBJECT] = FUN_OBJECT(fun);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ out2:
+ LAST_FRAME_CHECKS(cx, fun);
+ return fun;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+ uintN indent)
+{
+ JSPrinter *jp;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ jp = JS_NEW_PRINTER(cx, name, NULL,
+ indent & ~JS_DONT_PRETTY_PRINT,
+ !(indent & JS_DONT_PRETTY_PRINT));
+ if (!jp)
+ return NULL;
+ if (js_DecompileScript(jp, script))
+ str = js_GetPrinterOutput(jp);
+ else
+ str = NULL;
+ js_DestroyPrinter(jp);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
+{
+ JSPrinter *jp;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ jp = JS_NEW_PRINTER(cx, "JS_DecompileFunction", fun,
+ indent & ~JS_DONT_PRETTY_PRINT,
+ !(indent & JS_DONT_PRETTY_PRINT));
+ if (!jp)
+ return NULL;
+ if (js_DecompileFunction(jp))
+ str = js_GetPrinterOutput(jp);
+ else
+ str = NULL;
+ js_DestroyPrinter(jp);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent)
+{
+ JSPrinter *jp;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ jp = JS_NEW_PRINTER(cx, "JS_DecompileFunctionBody", fun,
+ indent & ~JS_DONT_PRETTY_PRINT,
+ !(indent & JS_DONT_PRETTY_PRINT));
+ if (!jp)
+ return NULL;
+ if (js_DecompileFunctionBody(jp))
+ str = js_GetPrinterOutput(jp);
+ else
+ str = NULL;
+ js_DestroyPrinter(jp);
+ return str;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_Execute(cx, obj, script, NULL, 0, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+ JSExecPart part, jsval *rval)
+{
+ JSScript tmp;
+ JSDebugHooks *hooks;
+ JSBool ok;
+
+ /* Make a temporary copy of the JSScript structure and farble it a bit. */
+ tmp = *script;
+ if (part == JSEXEC_PROLOG) {
+ tmp.length = PTRDIFF(tmp.main, tmp.code, jsbytecode);
+ } else {
+ tmp.length -= PTRDIFF(tmp.main, tmp.code, jsbytecode);
+ tmp.code = tmp.main;
+ }
+
+ /* Tell the debugger about our temporary copy of the script structure. */
+ hooks = cx->debugHooks;
+ if (hooks->newScriptHook) {
+ hooks->newScriptHook(cx, tmp.filename, tmp.lineno, &tmp, NULL,
+ hooks->newScriptHookData);
+ }
+
+ /* Execute the farbled struct and tell the debugger to forget about it. */
+ ok = JS_ExecuteScript(cx, obj, &tmp, rval);
+ if (hooks->destroyScriptHook)
+ hooks->destroyScriptHook(cx, &tmp, hooks->destroyScriptHookData);
+ return ok;
+}
+
+/* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
+JS_PUBLIC_API(JSBool)
+JS_EvaluateScript(JSContext *cx, JSObject *obj,
+ const char *bytes, uintN nbytes,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ size_t length = nbytes;
+ jschar *chars;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return JS_FALSE;
+ ok = JS_EvaluateUCScript(cx, obj, chars, length, filename, lineno, rval);
+ JS_free(cx, chars);
+ return ok;
+}
+
+/* Ancient uintN nbytes is part of API/ABI, so use size_t length local. */
+JS_PUBLIC_API(JSBool)
+JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, uintN nbytes,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ size_t length = nbytes;
+ jschar *chars;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return JS_FALSE;
+ ok = JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length,
+ filename, lineno, rval);
+ JS_free(cx, chars);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ CHECK_REQUEST(cx);
+ return JS_EvaluateUCScriptForPrincipals(cx, obj, NULL, chars, length,
+ filename, lineno, rval);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ JSScript *script;
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ script = js_CompileScript(cx, obj, NULL, principals,
+ !rval
+ ? TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL
+ : TCF_COMPILE_N_GO,
+ chars, length, NULL, filename, lineno);
+ if (!script) {
+ LAST_FRAME_CHECKS(cx, script);
+ return JS_FALSE;
+ }
+ ok = js_Execute(cx, obj, script, NULL, 0, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ JS_DestroyScript(cx, script);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(FUN_OBJECT(fun)), argc, argv,
+ rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ JSBool ok;
+ jsval fval;
+
+ CHECK_REQUEST(cx);
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+ JSAtom *atom;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ atom = js_Atomize(cx, name, strlen(name), 0);
+ if (!atom)
+ return JS_FALSE;
+ obj = ops->getMethod(cx, obj, ATOM_TO_JSID(atom), &fval);
+ if (!obj)
+ return JS_FALSE;
+ } else
+#endif
+ if (!JS_GetProperty(cx, obj, name, &fval))
+ return JS_FALSE;
+ ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ JSBool ok;
+
+ CHECK_REQUEST(cx);
+ ok = js_InternalCall(cx, obj, fval, argc, argv, rval);
+ LAST_FRAME_CHECKS(cx, ok);
+ return ok;
+}
+
+JS_PUBLIC_API(void)
+JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback,
+ uint32 operationLimit)
+{
+ JS_ASSERT(callback);
+ JS_ASSERT(operationLimit <= JS_MAX_OPERATION_LIMIT);
+ JS_ASSERT(operationLimit > 0);
+
+ cx->operationCount = (int32) operationLimit;
+ cx->operationLimit = operationLimit;
+ cx->operationCallbackIsSet = 1;
+ cx->operationCallback = callback;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearOperationCallback(JSContext *cx)
+{
+ cx->operationCount = (int32) JS_MAX_OPERATION_LIMIT;
+ cx->operationLimit = JS_MAX_OPERATION_LIMIT;
+ cx->operationCallbackIsSet = 0;
+ cx->operationCallback = NULL;
+}
+
+JS_PUBLIC_API(JSOperationCallback)
+JS_GetOperationCallback(JSContext *cx)
+{
+ JS_ASSERT(cx->operationCallbackIsSet || !cx->operationCallback);
+ return cx->operationCallback;
+}
+
+JS_PUBLIC_API(uint32)
+JS_GetOperationLimit(JSContext *cx)
+{
+ JS_ASSERT(cx->operationCallbackIsSet);
+ return cx->operationLimit;
+}
+
+JS_PUBLIC_API(void)
+JS_SetOperationLimit(JSContext *cx, uint32 operationLimit)
+{
+ JS_ASSERT(operationLimit <= JS_MAX_OPERATION_LIMIT);
+ JS_ASSERT(operationLimit > 0);
+ JS_ASSERT(cx->operationCallbackIsSet);
+
+ cx->operationLimit = operationLimit;
+ if (cx->operationCount > (int32) operationLimit)
+ cx->operationCount = (int32) operationLimit;
+}
+
+JS_PUBLIC_API(JSBranchCallback)
+JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb)
+{
+ JSBranchCallback oldcb;
+
+ if (cx->operationCallbackIsSet) {
+#ifdef DEBUG
+ fprintf(stderr,
+"JS API usage error: call to JS_SetOperationCallback is followed by\n"
+"invocation of deprecated JS_SetBranchCallback\n");
+ JS_ASSERT(0);
+#endif
+ cx->operationCallbackIsSet = 0;
+ oldcb = NULL;
+ } else {
+ oldcb = (JSBranchCallback) cx->operationCallback;
+ }
+ if (cb) {
+ cx->operationCount = JSOW_SCRIPT_JUMP;
+ cx->operationLimit = JSOW_SCRIPT_JUMP;
+ cx->operationCallback = (JSOperationCallback) cb;
+ } else {
+ JS_ClearOperationCallback(cx);
+ }
+ return oldcb;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsRunning(JSContext *cx)
+{
+ return cx->fp != NULL;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsConstructing(JSContext *cx)
+{
+ return cx->fp && (cx->fp->flags & JSFRAME_CONSTRUCTING);
+}
+
+JS_FRIEND_API(JSBool)
+JS_IsAssigning(JSContext *cx)
+{
+ JSStackFrame *fp;
+
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
+ if (!fp || !fp->regs)
+ return JS_FALSE;
+ return (js_CodeSpec[*fp->regs->pc].format & JOF_ASSIGNING) != 0;
+}
+
+JS_PUBLIC_API(void)
+JS_SetCallReturnValue2(JSContext *cx, jsval v)
+{
+#if JS_HAS_LVALUE_RETURN
+ cx->rval2 = v;
+ cx->rval2set = JS_TRUE;
+#endif
+}
+
+JS_PUBLIC_API(JSStackFrame *)
+JS_SaveFrameChain(JSContext *cx)
+{
+ JSStackFrame *fp;
+
+ fp = cx->fp;
+ if (!fp)
+ return fp;
+
+ JS_ASSERT(!fp->dormantNext);
+ fp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = fp;
+ cx->fp = NULL;
+ return fp;
+}
+
+JS_PUBLIC_API(void)
+JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
+{
+ JS_ASSERT(!cx->fp);
+ if (!fp)
+ return;
+
+ JS_ASSERT(fp == cx->dormantFrameChain);
+ cx->fp = fp;
+ cx->dormantFrameChain = fp->dormantNext;
+ fp->dormantNext = NULL;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSString *)
+JS_NewString(JSContext *cx, char *bytes, size_t nbytes)
+{
+ size_t length = nbytes;
+ jschar *chars;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+
+ /* Make a UTF-16 vector from the 8-bit char codes in bytes. */
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+
+ /* Free chars (but not bytes, which caller frees on error) if we fail. */
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return NULL;
+ }
+
+ /* Hand off bytes to the deflated string cache, if possible. */
+ if (!js_SetStringBytes(cx, str, bytes, nbytes))
+ JS_free(cx, bytes);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
+{
+ jschar *js;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ js = js_InflateString(cx, s, &n);
+ if (!js)
+ return NULL;
+ str = js_NewString(cx, js, n);
+ if (!str)
+ JS_free(cx, js);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewStringCopyZ(JSContext *cx, const char *s)
+{
+ size_t n;
+ jschar *js;
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ if (!s)
+ return cx->runtime->emptyString;
+ n = strlen(s);
+ js = js_InflateString(cx, s, &n);
+ if (!js)
+ return NULL;
+ str = js_NewString(cx, js, n);
+ if (!str)
+ JS_free(cx, js);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_InternString(JSContext *cx, const char *s)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
+ if (!atom)
+ return NULL;
+ return ATOM_TO_STRING(atom);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
+{
+ CHECK_REQUEST(cx);
+ return js_NewString(cx, chars, length);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
+{
+ CHECK_REQUEST(cx);
+ return js_NewStringCopyN(cx, s, n);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
+{
+ CHECK_REQUEST(cx);
+ if (!s)
+ return cx->runtime->emptyString;
+ return js_NewStringCopyZ(cx, s);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
+{
+ JSAtom *atom;
+
+ CHECK_REQUEST(cx);
+ atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
+ if (!atom)
+ return NULL;
+ return ATOM_TO_STRING(atom);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_InternUCString(JSContext *cx, const jschar *s)
+{
+ return JS_InternUCStringN(cx, s, js_strlen(s));
+}
+
+JS_PUBLIC_API(char *)
+JS_GetStringBytes(JSString *str)
+{
+ const char *bytes;
+
+ bytes = js_GetStringBytes(NULL, str);
+ return (char *)(bytes ? bytes : "");
+}
+
+JS_PUBLIC_API(jschar *)
+JS_GetStringChars(JSString *str)
+{
+ size_t n, size;
+ jschar *s;
+
+ /*
+ * API botch (again, shades of JS_GetStringBytes): we have no cx to report
+ * out-of-memory when undepending strings, so we replace js_UndependString
+ * with explicit malloc call and ignore its errors.
+ *
+ * If we fail to convert a dependent string into an independent one, our
+ * caller will not be guaranteed a \u0000 terminator as a backstop. This
+ * may break some clients who already misbehave on embedded NULs.
+ *
+ * The gain of dependent strings, which cure quadratic and cubic growth
+ * rate bugs in string concatenation, is worth this slight loss in API
+ * compatibility.
+ */
+ if (JSSTRING_IS_DEPENDENT(str)) {
+ n = JSSTRDEP_LENGTH(str);
+ size = (n + 1) * sizeof(jschar);
+ s = (jschar *) malloc(size);
+ if (s) {
+ memcpy(s, JSSTRDEP_CHARS(str), n * sizeof *s);
+ s[n] = 0;
+ JSFLATSTR_INIT(str, s, n);
+ } else {
+ s = JSSTRDEP_CHARS(str);
+ }
+ } else {
+ JSFLATSTR_CLEAR_MUTABLE(str);
+ s = JSFLATSTR_CHARS(str);
+ }
+ return s;
+}
+
+JS_PUBLIC_API(size_t)
+JS_GetStringLength(JSString *str)
+{
+ return JSSTRING_LENGTH(str);
+}
+
+JS_PUBLIC_API(intN)
+JS_CompareStrings(JSString *str1, JSString *str2)
+{
+ return js_CompareStrings(str1, str2);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length)
+{
+ JSString *str;
+
+ CHECK_REQUEST(cx);
+ str = js_NewString(cx, chars, length);
+ if (!str)
+ return str;
+ JSFLATSTR_SET_MUTABLE(str);
+ return str;
+}
+
+JS_PUBLIC_API(JSString *)
+JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+ size_t length)
+{
+ CHECK_REQUEST(cx);
+ return js_NewDependentString(cx, str, start, length);
+}
+
+JS_PUBLIC_API(JSString *)
+JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
+{
+ CHECK_REQUEST(cx);
+ return js_ConcatStrings(cx, left, right);
+}
+
+JS_PUBLIC_API(const jschar *)
+JS_UndependString(JSContext *cx, JSString *str)
+{
+ CHECK_REQUEST(cx);
+ return js_UndependString(cx, str);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_MakeStringImmutable(JSContext *cx, JSString *str)
+{
+ CHECK_REQUEST(cx);
+ return js_MakeStringImmutable(cx, str);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
+ size_t *dstlenp)
+{
+ size_t n;
+
+ if (!dst) {
+ n = js_GetDeflatedStringLength(cx, src, srclen);
+ if (n == (size_t)-1) {
+ *dstlenp = 0;
+ return JS_FALSE;
+ }
+ *dstlenp = n;
+ return JS_TRUE;
+ }
+
+ return js_DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
+ size_t *dstlenp)
+{
+ return js_InflateStringToBuffer(cx, src, srclen, dst, dstlenp);
+}
+
+JS_PUBLIC_API(char *)
+JS_EncodeString(JSContext *cx, JSString *str)
+{
+ return js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+}
+
+JS_PUBLIC_API(JSBool)
+JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data)
+{
+ CHECK_REQUEST(cx);
+ return js_Stringify(cx, vp, replacer, callback, data, 0);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_TryJSON(JSContext *cx, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ return js_TryJSON(cx, vp);
+}
+
+JS_PUBLIC_API(JSONParser *)
+JS_BeginJSONParse(JSContext *cx, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ return js_BeginJSONParse(cx, vp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len)
+{
+ CHECK_REQUEST(cx);
+ return js_ConsumeJSONText(cx, jp, data, len);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_FinishJSONParse(JSContext *cx, JSONParser *jp)
+{
+ CHECK_REQUEST(cx);
+ return js_FinishJSONParse(cx, jp);
+}
+
+/*
+ * The following determines whether C Strings are to be treated as UTF-8
+ * or ISO-8859-1. For correct operation, it must be set prior to the
+ * first call to JS_NewRuntime.
+ */
+#ifndef JS_C_STRINGS_ARE_UTF8
+JSBool js_CStringsAreUTF8 = JS_FALSE;
+#endif
+
+JS_PUBLIC_API(JSBool)
+JS_CStringsAreUTF8()
+{
+ return js_CStringsAreUTF8;
+}
+
+JS_PUBLIC_API(void)
+JS_SetCStringsAreUTF8()
+{
+ JS_ASSERT(!js_NewRuntimeWasCalled);
+
+#ifndef JS_C_STRINGS_ARE_UTF8
+ js_CStringsAreUTF8 = JS_TRUE;
+#endif
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_ReportError(JSContext *cx, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
+ va_end(ap);
+}
+
+JS_PUBLIC_API(void)
+JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...)
+{
+ va_list ap;
+
+ va_start(ap, errorNumber);
+ js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
+ errorNumber, JS_TRUE, ap);
+ va_end(ap);
+}
+
+JS_PUBLIC_API(void)
+JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...)
+{
+ va_list ap;
+
+ va_start(ap, errorNumber);
+ js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
+ errorNumber, JS_FALSE, ap);
+ va_end(ap);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportWarning(JSContext *cx, const char *format, ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, format);
+ ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, errorNumber);
+ ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
+ errorNumber, JS_TRUE, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...)
+{
+ va_list ap;
+ JSBool ok;
+
+ va_start(ap, errorNumber);
+ ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
+ errorNumber, JS_FALSE, ap);
+ va_end(ap);
+ return ok;
+}
+
+JS_PUBLIC_API(void)
+JS_ReportOutOfMemory(JSContext *cx)
+{
+ js_ReportOutOfMemory(cx);
+}
+
+JS_PUBLIC_API(void)
+JS_ReportAllocationOverflow(JSContext *cx)
+{
+ js_ReportAllocationOverflow(cx);
+}
+
+JS_PUBLIC_API(JSErrorReporter)
+JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
+{
+ JSErrorReporter older;
+
+ older = cx->errorReporter;
+ cx->errorReporter = er;
+ return older;
+}
+
+/************************************************************************/
+
+/*
+ * Regular Expressions.
+ */
+JS_PUBLIC_API(JSObject *)
+JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags)
+{
+ jschar *chars;
+ JSObject *obj;
+
+ CHECK_REQUEST(cx);
+ chars = js_InflateString(cx, bytes, &length);
+ if (!chars)
+ return NULL;
+ obj = js_NewRegExpObject(cx, NULL, chars, length, flags);
+ JS_free(cx, chars);
+ return obj;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags)
+{
+ CHECK_REQUEST(cx);
+ return js_NewRegExpObject(cx, NULL, chars, length, flags);
+}
+
+JS_PUBLIC_API(void)
+JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline)
+{
+ JSRegExpStatics *res;
+
+ CHECK_REQUEST(cx);
+ /* No locking required, cx is thread-private and input must be live. */
+ res = &cx->regExpStatics;
+ res->input = input;
+ res->multiline = multiline;
+ cx->runtime->gcPoke = JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearRegExpStatics(JSContext *cx)
+{
+ JSRegExpStatics *res;
+
+ /* No locking required, cx is thread-private and input must be live. */
+ res = &cx->regExpStatics;
+ res->input = NULL;
+ res->multiline = JS_FALSE;
+ res->parenCount = 0;
+ res->lastMatch = res->lastParen = js_EmptySubString;
+ res->leftContext = res->rightContext = js_EmptySubString;
+ cx->runtime->gcPoke = JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearRegExpRoots(JSContext *cx)
+{
+ JSRegExpStatics *res;
+
+ /* No locking required, cx is thread-private and input must be live. */
+ res = &cx->regExpStatics;
+ res->input = NULL;
+ cx->runtime->gcPoke = JS_TRUE;
+}
+
+/* TODO: compile, execute, get/set other statics... */
+
+/************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks)
+{
+ cx->localeCallbacks = callbacks;
+}
+
+JS_PUBLIC_API(JSLocaleCallbacks *)
+JS_GetLocaleCallbacks(JSContext *cx)
+{
+ return cx->localeCallbacks;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSBool)
+JS_IsExceptionPending(JSContext *cx)
+{
+ return (JSBool) cx->throwing;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPendingException(JSContext *cx, jsval *vp)
+{
+ CHECK_REQUEST(cx);
+ if (!cx->throwing)
+ return JS_FALSE;
+ *vp = cx->exception;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_SetPendingException(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ cx->throwing = JS_TRUE;
+ cx->exception = v;
+}
+
+JS_PUBLIC_API(void)
+JS_ClearPendingException(JSContext *cx)
+{
+ cx->throwing = JS_FALSE;
+ cx->exception = JSVAL_VOID;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ReportPendingException(JSContext *cx)
+{
+ JSBool save, ok;
+
+ CHECK_REQUEST(cx);
+
+ /*
+ * Set cx->generatingError to suppress the standard error-to-exception
+ * conversion done by all {js,JS}_Report* functions except for OOM. The
+ * cx->generatingError flag was added to suppress recursive divergence
+ * under js_ErrorToException, but it serves for our purposes here too.
+ */
+ save = cx->generatingError;
+ cx->generatingError = JS_TRUE;
+ ok = js_ReportUncaughtException(cx);
+ cx->generatingError = save;
+ return ok;
+}
+
+struct JSExceptionState {
+ JSBool throwing;
+ jsval exception;
+};
+
+JS_PUBLIC_API(JSExceptionState *)
+JS_SaveExceptionState(JSContext *cx)
+{
+ JSExceptionState *state;
+
+ CHECK_REQUEST(cx);
+ state = (JSExceptionState *) JS_malloc(cx, sizeof(JSExceptionState));
+ if (state) {
+ state->throwing = JS_GetPendingException(cx, &state->exception);
+ if (state->throwing && JSVAL_IS_GCTHING(state->exception))
+ js_AddRoot(cx, &state->exception, "JSExceptionState.exception");
+ }
+ return state;
+}
+
+JS_PUBLIC_API(void)
+JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
+{
+ CHECK_REQUEST(cx);
+ if (state) {
+ if (state->throwing)
+ JS_SetPendingException(cx, state->exception);
+ else
+ JS_ClearPendingException(cx);
+ JS_DropExceptionState(cx, state);
+ }
+}
+
+JS_PUBLIC_API(void)
+JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
+{
+ CHECK_REQUEST(cx);
+ if (state) {
+ if (state->throwing && JSVAL_IS_GCTHING(state->exception))
+ JS_RemoveRoot(cx, &state->exception);
+ JS_free(cx, state);
+ }
+}
+
+JS_PUBLIC_API(JSErrorReport *)
+JS_ErrorFromException(JSContext *cx, jsval v)
+{
+ CHECK_REQUEST(cx);
+ return js_ErrorFromException(cx, v);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ThrowReportedError(JSContext *cx, const char *message,
+ JSErrorReport *reportp)
+{
+ return cx->fp && js_ErrorToException(cx, message, reportp);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ThrowStopIteration(JSContext *cx)
+{
+ return js_ThrowStopIteration(cx);
+}
+
+/*
+ * Get the owning thread id of a context. Returns 0 if the context is not
+ * owned by any thread.
+ */
+JS_PUBLIC_API(jsword)
+JS_GetContextThread(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ return JS_THREAD_ID(cx);
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Set the current thread as the owning thread of a context. Returns the
+ * old owning thread id, or -1 if the operation failed.
+ */
+JS_PUBLIC_API(jsword)
+JS_SetContextThread(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ jsword old = JS_THREAD_ID(cx);
+ if (!js_SetContextThread(cx))
+ return -1;
+ return old;
+#else
+ return 0;
+#endif
+}
+
+JS_PUBLIC_API(jsword)
+JS_ClearContextThread(JSContext *cx)
+{
+#ifdef JS_THREADSAFE
+ jsword old = JS_THREAD_ID(cx);
+ js_ClearContextThread(cx);
+ return old;
+#else
+ return 0;
+#endif
+}
+
+#ifdef JS_GC_ZEAL
+JS_PUBLIC_API(void)
+JS_SetGCZeal(JSContext *cx, uint8 zeal)
+{
+ cx->runtime->gcZeal = zeal;
+}
+#endif
+
+/************************************************************************/
+
+#if !defined(STATIC_JS_API) && defined(XP_WIN) && !defined (WINCE)
+
+#include <windows.h>
+
+/*
+ * Initialization routine for the JS DLL.
+ */
+BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
+{
+ return TRUE;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsapi.h b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.h
new file mode 100644
index 0000000..7842192
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsapi.h
@@ -0,0 +1,2699 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsapi_h___
+#define jsapi_h___
+/*
+ * JavaScript API.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include "js-config.h"
+#include "jspubtd.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Type tags stored in the low bits of a jsval.
+ */
+#define JSVAL_OBJECT 0x0 /* untagged reference to object */
+#define JSVAL_INT 0x1 /* tagged 31-bit integer value */
+#define JSVAL_DOUBLE 0x2 /* tagged reference to double */
+#define JSVAL_STRING 0x4 /* tagged reference to string */
+#define JSVAL_BOOLEAN 0x6 /* tagged boolean value */
+
+/* Type tag bitfield length and derived macros. */
+#define JSVAL_TAGBITS 3
+#define JSVAL_TAGMASK JS_BITMASK(JSVAL_TAGBITS)
+#define JSVAL_TAG(v) ((v) & JSVAL_TAGMASK)
+#define JSVAL_SETTAG(v,t) ((v) | (t))
+#define JSVAL_CLRTAG(v) ((v) & ~(jsval)JSVAL_TAGMASK)
+#define JSVAL_ALIGN JS_BIT(JSVAL_TAGBITS)
+
+/* Predicates for type testing. */
+#define JSVAL_IS_OBJECT(v) (JSVAL_TAG(v) == JSVAL_OBJECT)
+#define JSVAL_IS_NUMBER(v) (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
+#define JSVAL_IS_INT(v) ((v) & JSVAL_INT)
+#define JSVAL_IS_DOUBLE(v) (JSVAL_TAG(v) == JSVAL_DOUBLE)
+#define JSVAL_IS_STRING(v) (JSVAL_TAG(v) == JSVAL_STRING)
+#define JSVAL_IS_BOOLEAN(v) (((v) & ~((jsval)1 << JSVAL_TAGBITS)) == \
+ JSVAL_BOOLEAN)
+#define JSVAL_IS_NULL(v) ((v) == JSVAL_NULL)
+#define JSVAL_IS_VOID(v) ((v) == JSVAL_VOID)
+#define JSVAL_IS_PRIMITIVE(v) (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+
+/* Objects, strings, and doubles are GC'ed. */
+#define JSVAL_IS_GCTHING(v) (!((v) & JSVAL_INT) && \
+ JSVAL_TAG(v) != JSVAL_BOOLEAN)
+#define JSVAL_TO_GCTHING(v) ((void *)JSVAL_CLRTAG(v))
+#define JSVAL_TO_OBJECT(v) ((JSObject *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_DOUBLE(v) ((jsdouble *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_STRING(v) ((JSString *)JSVAL_TO_GCTHING(v))
+#define OBJECT_TO_JSVAL(obj) ((jsval)(obj))
+#define DOUBLE_TO_JSVAL(dp) JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
+#define STRING_TO_JSVAL(str) JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
+
+/* Lock and unlock the GC thing held by a jsval. */
+#define JSVAL_LOCK(cx,v) (JSVAL_IS_GCTHING(v) \
+ ? JS_LockGCThing(cx, JSVAL_TO_GCTHING(v)) \
+ : JS_TRUE)
+#define JSVAL_UNLOCK(cx,v) (JSVAL_IS_GCTHING(v) \
+ ? JS_UnlockGCThing(cx, JSVAL_TO_GCTHING(v)) \
+ : JS_TRUE)
+
+/* Domain limits for the jsval int type. */
+#define JSVAL_INT_BITS 31
+#define JSVAL_INT_POW2(n) ((jsval)1 << (n))
+#define JSVAL_INT_MIN (-JSVAL_INT_POW2(30))
+#define JSVAL_INT_MAX (JSVAL_INT_POW2(30) - 1)
+#define INT_FITS_IN_JSVAL(i) ((jsuint)(i) - (jsuint)JSVAL_INT_MIN <= \
+ (jsuint)(JSVAL_INT_MAX - JSVAL_INT_MIN))
+#define JSVAL_TO_INT(v) ((jsint)(v) >> 1)
+#define INT_TO_JSVAL(i) (((jsval)(i) << 1) | JSVAL_INT)
+
+/* Convert between boolean and jsval. */
+#define JSVAL_TO_BOOLEAN(v) ((JSBool)((v) >> JSVAL_TAGBITS))
+#define BOOLEAN_TO_JSVAL(b) JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS, \
+ JSVAL_BOOLEAN)
+
+/* A private data pointer (2-byte-aligned) can be stored as an int jsval. */
+#define JSVAL_TO_PRIVATE(v) ((void *)((v) & ~JSVAL_INT))
+#define PRIVATE_TO_JSVAL(p) ((jsval)(p) | JSVAL_INT)
+
+/* Property attributes, set in JSPropertySpec and passed to API functions. */
+#define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */
+#define JSPROP_READONLY 0x02 /* not settable: assignment is no-op */
+#define JSPROP_PERMANENT 0x04 /* property cannot be deleted */
+#define JSPROP_GETTER 0x10 /* property holds getter function */
+#define JSPROP_SETTER 0x20 /* property holds setter function */
+#define JSPROP_SHARED 0x40 /* don't allocate a value slot for this
+ property; don't copy the property on
+ set of the same-named property in an
+ object that delegates to a prototype
+ containing this property */
+#define JSPROP_INDEX 0x80 /* name is actually (jsint) index */
+
+/* Function flags, set in JSFunctionSpec and passed to JS_NewFunction etc. */
+#define JSFUN_LAMBDA 0x08 /* expressed, not declared, function */
+#define JSFUN_GETTER JSPROP_GETTER
+#define JSFUN_SETTER JSPROP_SETTER
+#define JSFUN_BOUND_METHOD 0x40 /* bind this to fun->object's parent */
+#define JSFUN_HEAVYWEIGHT 0x80 /* activation requires a Call object */
+
+#define JSFUN_DISJOINT_FLAGS(f) ((f) & 0x0f)
+#define JSFUN_GSFLAGS(f) ((f) & (JSFUN_GETTER | JSFUN_SETTER))
+
+#define JSFUN_GETTER_TEST(f) ((f) & JSFUN_GETTER)
+#define JSFUN_SETTER_TEST(f) ((f) & JSFUN_SETTER)
+#define JSFUN_BOUND_METHOD_TEST(f) ((f) & JSFUN_BOUND_METHOD)
+#define JSFUN_HEAVYWEIGHT_TEST(f) ((f) & JSFUN_HEAVYWEIGHT)
+
+#define JSFUN_GSFLAG2ATTR(f) JSFUN_GSFLAGS(f)
+
+#define JSFUN_THISP_FLAGS(f) (f)
+#define JSFUN_THISP_TEST(f,t) ((f) & t)
+
+#define JSFUN_THISP_STRING 0x0100 /* |this| may be a primitive string */
+#define JSFUN_THISP_NUMBER 0x0200 /* |this| may be a primitive number */
+#define JSFUN_THISP_BOOLEAN 0x0400 /* |this| may be a primitive boolean */
+#define JSFUN_THISP_PRIMITIVE 0x0700 /* |this| may be any primitive value */
+
+#define JSFUN_FAST_NATIVE 0x0800 /* JSFastNative needs no JSStackFrame */
+
+#define JSFUN_FLAGS_MASK 0x0ff8 /* overlay JSFUN_* attributes --
+ note that bit #15 is used internally
+ to flag interpreted functions */
+
+#define JSFUN_STUB_GSOPS 0x1000 /* use JS_PropertyStub getter/setter
+ instead of defaulting to class gsops
+ for property holding function */
+
+/*
+ * Re-use JSFUN_LAMBDA, which applies only to scripted functions, for use in
+ * JSFunctionSpec arrays that specify generic native prototype methods, i.e.,
+ * methods of a class prototype that are exposed as static methods taking an
+ * extra leading argument: the generic |this| parameter.
+ *
+ * If you set this flag in a JSFunctionSpec struct's flags initializer, then
+ * that struct must live at least as long as the native static method object
+ * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically
+ * JSFunctionSpec structs are allocated in static arrays.
+ */
+#define JSFUN_GENERIC_NATIVE JSFUN_LAMBDA
+
+/*
+ * Well-known JS values. The extern'd variables are initialized when the
+ * first JSContext is created by JS_NewContext (see below).
+ */
+#define JSVAL_VOID BOOLEAN_TO_JSVAL(2)
+#define JSVAL_NULL OBJECT_TO_JSVAL(0)
+#define JSVAL_ZERO INT_TO_JSVAL(0)
+#define JSVAL_ONE INT_TO_JSVAL(1)
+#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE)
+#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE)
+
+/*
+ * Microseconds since the epoch, midnight, January 1, 1970 UTC. See the
+ * comment in jstypes.h regarding safe int64 usage.
+ */
+extern JS_PUBLIC_API(int64)
+JS_Now(void);
+
+/* Don't want to export data, so provide accessors for non-inline jsvals. */
+extern JS_PUBLIC_API(jsval)
+JS_GetNaNValue(JSContext *cx);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetNegativeInfinityValue(JSContext *cx);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetPositiveInfinityValue(JSContext *cx);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetEmptyStringValue(JSContext *cx);
+
+/*
+ * Format is a string of the following characters (spaces are insignificant),
+ * specifying the tabulated type conversions:
+ *
+ * b JSBool Boolean
+ * c uint16/jschar ECMA uint16, Unicode char
+ * i int32 ECMA int32
+ * u uint32 ECMA uint32
+ * j int32 Rounded int32 (coordinate)
+ * d jsdouble IEEE double
+ * I jsdouble Integral IEEE double
+ * s char * C string
+ * S JSString * Unicode string, accessed by a JSString pointer
+ * W jschar * Unicode character vector, 0-terminated (W for wide)
+ * o JSObject * Object reference
+ * f JSFunction * Function private
+ * v jsval Argument value (no conversion)
+ * * N/A Skip this argument (no vararg)
+ * / N/A End of required arguments
+ *
+ * The variable argument list after format must consist of &b, &c, &s, e.g.,
+ * where those variables have the types given above. For the pointer types
+ * char *, JSString *, and JSObject *, the pointed-at memory returned belongs
+ * to the JS runtime, not to the calling native code. The runtime promises
+ * to keep this memory valid so long as argv refers to allocated stack space
+ * (so long as the native function is active).
+ *
+ * Fewer arguments than format specifies may be passed only if there is a /
+ * in format after the last required argument specifier and argc is at least
+ * the number of required arguments. More arguments than format specifies
+ * may be passed without error; it is up to the caller to deal with trailing
+ * unconverted arguments.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
+ ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
+ const char *format, va_list ap);
+#endif
+
+/*
+ * Inverse of JS_ConvertArguments: scan format and convert trailing arguments
+ * into jsvals, GC-rooted if necessary by the JS stack. Return null on error,
+ * and a pointer to the new argument vector on success. Also return a stack
+ * mark on success via *markp, in which case the caller must eventually clean
+ * up by calling JS_PopArguments.
+ *
+ * Note that the number of actual arguments supplied is specified exclusively
+ * by format, so there is no argc parameter.
+ */
+extern JS_PUBLIC_API(jsval *)
+JS_PushArguments(JSContext *cx, void **markp, const char *format, ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(jsval *)
+JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap);
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_PopArguments(JSContext *cx, void *mark);
+
+#ifdef JS_ARGUMENT_FORMATTER_DEFINED
+
+/*
+ * Add and remove a format string handler for JS_{Convert,Push}Arguments{,VA}.
+ * The handler function has this signature (see jspubtd.h):
+ *
+ * JSBool MyArgumentFormatter(JSContext *cx, const char *format,
+ * JSBool fromJS, jsval **vpp, va_list *app);
+ *
+ * It should return true on success, and return false after reporting an error
+ * or detecting an already-reported error.
+ *
+ * For a given format string, for example "AA", the formatter is called from
+ * JS_ConvertArgumentsVA like so:
+ *
+ * formatter(cx, "AA...", JS_TRUE, &sp, &ap);
+ *
+ * sp points into the arguments array on the JS stack, while ap points into
+ * the stdarg.h va_list on the C stack. The JS_TRUE passed for fromJS tells
+ * the formatter to convert zero or more jsvals at sp to zero or more C values
+ * accessed via pointers-to-values at ap, updating both sp (via *vpp) and ap
+ * (via *app) to point past the converted arguments and their result pointers
+ * on the C stack.
+ *
+ * When called from JS_PushArgumentsVA, the formatter is invoked thus:
+ *
+ * formatter(cx, "AA...", JS_FALSE, &sp, &ap);
+ *
+ * where JS_FALSE for fromJS means to wrap the C values at ap according to the
+ * format specifier and store them at sp, updating ap and sp appropriately.
+ *
+ * The "..." after "AA" is the rest of the format string that was passed into
+ * JS_{Convert,Push}Arguments{,VA}. The actual format trailing substring used
+ * in each Convert or PushArguments call is passed to the formatter, so that
+ * one such function may implement several formats, in order to share code.
+ *
+ * Remove just forgets about any handler associated with format. Add does not
+ * copy format, it points at the string storage allocated by the caller, which
+ * is typically a string constant. If format is in dynamic storage, it is up
+ * to the caller to keep the string alive until Remove is called.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_AddArgumentFormatter(JSContext *cx, const char *format,
+ JSArgumentFormatter formatter);
+
+extern JS_PUBLIC_API(void)
+JS_RemoveArgumentFormatter(JSContext *cx, const char *format);
+
+#endif /* JS_ARGUMENT_FORMATTER_DEFINED */
+
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_ValueToFunction(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_ValueToConstructor(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSString *)
+JS_ValueToString(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSString *)
+JS_ValueToSource(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
+
+/*
+ * Convert a value to a number, then to an int32, according to the ECMA rules
+ * for ToInt32.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip);
+
+/*
+ * Convert a value to a number, then to a uint32, according to the ECMA rules
+ * for ToUint32.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32 *ip);
+
+/*
+ * Convert a value to a number, then to an int32 if it fits by rounding to
+ * nearest; but failing with an error report if the double is out of range
+ * or unordered.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToInt32(JSContext *cx, jsval v, int32 *ip);
+
+/*
+ * ECMA ToUint16, for mapping a jsval to a Unicode point.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToUint16(JSContext *cx, jsval v, uint16 *ip);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp);
+
+extern JS_PUBLIC_API(JSType)
+JS_TypeOfValue(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(const char *)
+JS_GetTypeName(JSContext *cx, JSType type);
+
+/************************************************************************/
+
+/*
+ * Initialization, locking, contexts, and memory allocation.
+ *
+ * It is important that the first runtime and first context be created in a
+ * single-threaded fashion, otherwise the behavior of the library is undefined.
+ * See: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
+ */
+#define JS_NewRuntime JS_Init
+#define JS_DestroyRuntime JS_Finish
+#define JS_LockRuntime JS_Lock
+#define JS_UnlockRuntime JS_Unlock
+
+extern JS_PUBLIC_API(JSRuntime *)
+JS_NewRuntime(uint32 maxbytes);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyRuntime(JSRuntime *rt);
+
+extern JS_PUBLIC_API(void)
+JS_ShutDown(void);
+
+JS_PUBLIC_API(void *)
+JS_GetRuntimePrivate(JSRuntime *rt);
+
+JS_PUBLIC_API(void)
+JS_SetRuntimePrivate(JSRuntime *rt, void *data);
+
+extern JS_PUBLIC_API(void)
+JS_BeginRequest(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_EndRequest(JSContext *cx);
+
+/* Yield to pending GC operations, regardless of request depth */
+extern JS_PUBLIC_API(void)
+JS_YieldRequest(JSContext *cx);
+
+extern JS_PUBLIC_API(jsrefcount)
+JS_SuspendRequest(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_ResumeRequest(JSContext *cx, jsrefcount saveDepth);
+
+#ifdef __cplusplus
+JS_END_EXTERN_C
+
+class JSAutoRequest {
+ public:
+ JSAutoRequest(JSContext *cx) : mContext(cx), mSaveDepth(0) {
+ JS_BeginRequest(mContext);
+ }
+ ~JSAutoRequest() {
+ JS_EndRequest(mContext);
+ }
+
+ void suspend() {
+ mSaveDepth = JS_SuspendRequest(mContext);
+ }
+ void resume() {
+ JS_ResumeRequest(mContext, mSaveDepth);
+ }
+
+ protected:
+ JSContext *mContext;
+ jsrefcount mSaveDepth;
+
+#if 0
+ private:
+ static void *operator new(size_t) CPP_THROW_NEW { return 0; };
+ static void operator delete(void *, size_t) { };
+#endif
+};
+
+class JSAutoSuspendRequest {
+ public:
+ JSAutoSuspendRequest(JSContext *cx) : mContext(cx), mSaveDepth(0) {
+ if (mContext) {
+ mSaveDepth = JS_SuspendRequest(mContext);
+ }
+ }
+ ~JSAutoSuspendRequest() {
+ resume();
+ }
+
+ void resume() {
+ if (mContext) {
+ JS_ResumeRequest(mContext, mSaveDepth);
+ mContext = 0;
+ }
+ }
+
+ protected:
+ JSContext *mContext;
+ jsrefcount mSaveDepth;
+
+#if 0
+ private:
+ static void *operator new(size_t) CPP_THROW_NEW { return 0; };
+ static void operator delete(void *, size_t) { };
+#endif
+};
+
+JS_BEGIN_EXTERN_C
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_Lock(JSRuntime *rt);
+
+extern JS_PUBLIC_API(void)
+JS_Unlock(JSRuntime *rt);
+
+extern JS_PUBLIC_API(JSContextCallback)
+JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback);
+
+extern JS_PUBLIC_API(JSContext *)
+JS_NewContext(JSRuntime *rt, size_t stackChunkSize);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContext(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContextNoGC(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContextMaybeGC(JSContext *cx);
+
+extern JS_PUBLIC_API(void *)
+JS_GetContextPrivate(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_SetContextPrivate(JSContext *cx, void *data);
+
+extern JS_PUBLIC_API(JSRuntime *)
+JS_GetRuntime(JSContext *cx);
+
+extern JS_PUBLIC_API(JSContext *)
+JS_ContextIterator(JSRuntime *rt, JSContext **iterp);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_GetVersion(JSContext *cx);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_SetVersion(JSContext *cx, JSVersion version);
+
+extern JS_PUBLIC_API(const char *)
+JS_VersionToString(JSVersion version);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_StringToVersion(const char *string);
+
+/*
+ * JS options are orthogonal to version, and may be freely composed with one
+ * another as well as with version.
+ *
+ * JSOPTION_VAROBJFIX is recommended -- see the comments associated with the
+ * prototypes for JS_ExecuteScript, JS_EvaluateScript, etc.
+ */
+#define JSOPTION_STRICT JS_BIT(0) /* warn on dubious practice */
+#define JSOPTION_WERROR JS_BIT(1) /* convert warning to error */
+#define JSOPTION_VAROBJFIX JS_BIT(2) /* make JS_EvaluateScript use
+ the last object on its 'obj'
+ param's scope chain as the
+ ECMA 'variables object' */
+#define JSOPTION_PRIVATE_IS_NSISUPPORTS \
+ JS_BIT(3) /* context private data points
+ to an nsISupports subclass */
+#define JSOPTION_COMPILE_N_GO JS_BIT(4) /* caller of JS_Compile*Script
+ promises to execute compiled
+ script once only; enables
+ compile-time scope chain
+ resolution of consts. */
+#define JSOPTION_ATLINE JS_BIT(5) /* //@line number ["filename"]
+ option supported for the
+ XUL preprocessor and kindred
+ beasts. */
+#define JSOPTION_XML JS_BIT(6) /* EMCAScript for XML support:
+ parse <!-- --> as a token,
+ not backward compatible with
+ the comment-hiding hack used
+ in HTML script tags. */
+#define JSOPTION_NATIVE_BRANCH_CALLBACK \
+ JS_BIT(7) /* the branch callback set by
+ JS_SetBranchCallback may be
+ called with a null script
+ parameter, by native code
+ that loops intensively.
+ Deprecated, use
+ JS_SetOperationCallback
+ instead */
+#define JSOPTION_DONT_REPORT_UNCAUGHT \
+ JS_BIT(8) /* When returning from the
+ outermost API call, prevent
+ uncaught exceptions from
+ being converted to error
+ reports */
+
+#define JSOPTION_RELIMIT JS_BIT(9) /* Throw exception on any
+ regular expression which
+ backtracks more than n^3
+ times, where n is length
+ of the input string */
+#define JSOPTION_ANONFUNFIX JS_BIT(10) /* Disallow function () {} in
+ statement context per
+ ECMA-262 Edition 3. */
+
+#define JSOPTION_JIT JS_BIT(11) /* Enable JIT compilation. */
+
+#define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler
+ that a null rval out-param
+ will be passed to each call
+ to JS_ExecuteScript. */
+
+extern JS_PUBLIC_API(uint32)
+JS_GetOptions(JSContext *cx);
+
+extern JS_PUBLIC_API(uint32)
+JS_SetOptions(JSContext *cx, uint32 options);
+
+extern JS_PUBLIC_API(uint32)
+JS_ToggleOptions(JSContext *cx, uint32 options);
+
+extern JS_PUBLIC_API(const char *)
+JS_GetImplementationVersion(void);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetGlobalObject(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_SetGlobalObject(JSContext *cx, JSObject *obj);
+
+/*
+ * Initialize standard JS class constructors, prototypes, and any top-level
+ * functions and constants associated with the standard classes (e.g. isNaN
+ * for Number).
+ *
+ * NB: This sets cx's global object to obj if it was null.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_InitStandardClasses(JSContext *cx, JSObject *obj);
+
+/*
+ * Resolve id, which must contain either a string or an int, to a standard
+ * class name in obj if possible, defining the class's constructor and/or
+ * prototype and storing true in *resolved. If id does not name a standard
+ * class or a top-level property induced by initializing a standard class,
+ * store false in *resolved and just return true. Return false on error,
+ * as usual for JSBool result-typed API entry points.
+ *
+ * This API can be called directly from a global object class's resolve op,
+ * to define standard classes lazily. The class's enumerate op should call
+ * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
+ * loops any classes not yet resolved lazily.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
+ JSBool *resolved);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj);
+
+/*
+ * Enumerate any already-resolved standard class ids into ida, or into a new
+ * JSIdArray if ida is null. Return the augmented array on success, null on
+ * failure with ida (if it was non-null on entry) destroyed.
+ */
+extern JS_PUBLIC_API(JSIdArray *)
+JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj,
+ JSIdArray *ida);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetScopeChain(JSContext *cx);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetGlobalForObject(JSContext *cx, JSObject *obj);
+
+/*
+ * Macros to hide interpreter stack layout details from a JSFastNative using
+ * its jsval *vp parameter. The stack layout underlying invocation can't change
+ * without breaking source and binary compatibility (argv[-2] is well-known to
+ * be the callee jsval, and argv[-1] is as well known to be |this|).
+ *
+ * Note well: However, argv[-1] may be JSVAL_NULL where with slow natives it
+ * is the global object, so embeddings implementing fast natives *must* call
+ * JS_THIS or JS_THIS_OBJECT and test for failure indicated by a null return,
+ * which should propagate as a false return from native functions and hooks.
+ *
+ * To reduce boilerplace checks, JS_InstanceOf and JS_GetInstancePrivate now
+ * handle a null obj parameter by returning false (throwing a TypeError if
+ * given non-null argv), so most native functions that type-check their |this|
+ * parameter need not add null checking.
+ *
+ * NB: there is an anti-dependency between JS_CALLEE and JS_SET_RVAL: native
+ * methods that may inspect their callee must defer setting their return value
+ * until after any such possible inspection. Otherwise the return value will be
+ * inspected instead of the callee function object.
+ *
+ * WARNING: These are not (yet) mandatory macros, but new code outside of the
+ * engine should use them. In the Mozilla 2.0 milestone their definitions may
+ * change incompatibly.
+ */
+#define JS_CALLEE(cx,vp) ((vp)[0])
+#define JS_ARGV_CALLEE(argv) ((argv)[-2])
+#define JS_THIS(cx,vp) JS_ComputeThis(cx, vp)
+#define JS_THIS_OBJECT(cx,vp) ((JSObject *) JS_THIS(cx,vp))
+#define JS_ARGV(cx,vp) ((vp) + 2)
+#define JS_RVAL(cx,vp) (*(vp))
+#define JS_SET_RVAL(cx,vp,v) (*(vp) = (v))
+
+extern JS_PUBLIC_API(jsval)
+JS_ComputeThis(JSContext *cx, jsval *vp);
+
+extern JS_PUBLIC_API(void *)
+JS_malloc(JSContext *cx, size_t nbytes);
+
+extern JS_PUBLIC_API(void *)
+JS_realloc(JSContext *cx, void *p, size_t nbytes);
+
+extern JS_PUBLIC_API(void)
+JS_free(JSContext *cx, void *p);
+
+extern JS_PUBLIC_API(char *)
+JS_strdup(JSContext *cx, const char *s);
+
+extern JS_PUBLIC_API(jsdouble *)
+JS_NewDouble(JSContext *cx, jsdouble d);
+
+extern JS_PUBLIC_API(JSBool)
+JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
+
+/*
+ * A JS GC root is a pointer to a JSObject *, JSString *, or jsdouble * that
+ * itself points into the GC heap (more recently, we support this extension:
+ * a root may be a pointer to a jsval v for which JSVAL_IS_GCTHING(v) is true).
+ *
+ * Therefore, you never pass JSObject *obj to JS_AddRoot(cx, obj). You always
+ * call JS_AddRoot(cx, &obj), passing obj by reference. And later, before obj
+ * or the structure it is embedded within goes out of scope or is freed, you
+ * must call JS_RemoveRoot(cx, &obj).
+ *
+ * Also, use JS_AddNamedRoot(cx, &structPtr->memberObj, "structPtr->memberObj")
+ * in preference to JS_AddRoot(cx, &structPtr->memberObj), in order to identify
+ * roots by their source callsites. This way, you can find the callsite while
+ * debugging if you should fail to do JS_RemoveRoot(cx, &structPtr->memberObj)
+ * before freeing structPtr's memory.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_AddRoot(JSContext *cx, void *rp);
+
+#ifdef NAME_ALL_GC_ROOTS
+#define JS_DEFINE_TO_TOKEN(def) #def
+#define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def)
+#define JS_AddRoot(cx,rp) JS_AddNamedRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__))
+#endif
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedRoot(JSContext *cx, void *rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AddNamedRootRT(JSRuntime *rt, void *rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveRoot(JSContext *cx, void *rp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_RemoveRootRT(JSRuntime *rt, void *rp);
+
+/*
+ * The last GC thing of each type (object, string, double, external string
+ * types) created on a given context is kept alive until another thing of the
+ * same type is created, using a newborn root in the context. These newborn
+ * roots help native code protect newly-created GC-things from GC invocations
+ * activated before those things can be rooted using local or global roots.
+ *
+ * However, the newborn roots can also entrain great gobs of garbage, so the
+ * JS_GC entry point clears them for the context on which GC is being forced.
+ * Embeddings may need to do likewise for all contexts.
+ *
+ * See the scoped local root API immediately below for a better way to manage
+ * newborns in cases where native hooks (functions, getters, setters, etc.)
+ * create many GC-things, potentially without connecting them to predefined
+ * local roots such as *rval or argv[i] in an active native function. Using
+ * JS_EnterLocalRootScope disables updating of the context's per-gc-thing-type
+ * newborn roots, until control flow unwinds and leaves the outermost nesting
+ * local root scope.
+ */
+extern JS_PUBLIC_API(void)
+JS_ClearNewbornRoots(JSContext *cx);
+
+/*
+ * Scoped local root management allows native functions, getter/setters, etc.
+ * to avoid worrying about the newborn root pigeon-holes, overloading local
+ * roots allocated in argv and *rval, or ending up having to call JS_Add*Root
+ * and JS_RemoveRoot to manage global roots temporarily.
+ *
+ * Instead, calling JS_EnterLocalRootScope and JS_LeaveLocalRootScope around
+ * the body of the native hook causes the engine to allocate a local root for
+ * each newborn created in between the two API calls, using a local root stack
+ * associated with cx. For example:
+ *
+ * JSBool
+ * my_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+ * {
+ * JSBool ok;
+ *
+ * if (!JS_EnterLocalRootScope(cx))
+ * return JS_FALSE;
+ * ok = my_GetPropertyBody(cx, obj, id, vp);
+ * JS_LeaveLocalRootScope(cx);
+ * return ok;
+ * }
+ *
+ * NB: JS_LeaveLocalRootScope must be called once for every prior successful
+ * call to JS_EnterLocalRootScope. If JS_EnterLocalRootScope fails, you must
+ * not make the matching JS_LeaveLocalRootScope call.
+ *
+ * JS_LeaveLocalRootScopeWithResult(cx, rval) is an alternative way to leave
+ * a local root scope that protects a result or return value, by effectively
+ * pushing it in the caller's local root scope.
+ *
+ * In case a native hook allocates many objects or other GC-things, but the
+ * native protects some of those GC-things by storing them as property values
+ * in an object that is itself protected, the hook can call JS_ForgetLocalRoot
+ * to free the local root automatically pushed for the now-protected GC-thing.
+ *
+ * JS_ForgetLocalRoot works on any GC-thing allocated in the current local
+ * root scope, but it's more time-efficient when called on references to more
+ * recently created GC-things. Calling it successively on other than the most
+ * recently allocated GC-thing will tend to average the time inefficiency, and
+ * may risk O(n^2) growth rate, but in any event, you shouldn't allocate too
+ * many local roots if you can root as you go (build a tree of objects from
+ * the top down, forgetting each latest-allocated GC-thing immediately upon
+ * linking it to its parent).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_EnterLocalRootScope(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_LeaveLocalRootScope(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval);
+
+extern JS_PUBLIC_API(void)
+JS_ForgetLocalRoot(JSContext *cx, void *thing);
+
+#ifdef __cplusplus
+JS_END_EXTERN_C
+
+class JSAutoLocalRootScope {
+ public:
+ JSAutoLocalRootScope(JSContext *cx) : mContext(cx) {
+ JS_EnterLocalRootScope(mContext);
+ }
+ ~JSAutoLocalRootScope() {
+ JS_LeaveLocalRootScope(mContext);
+ }
+
+ void forget(void *thing) {
+ JS_ForgetLocalRoot(mContext, thing);
+ }
+
+ protected:
+ JSContext *mContext;
+
+#if 0
+ private:
+ static void *operator new(size_t) CPP_THROW_NEW { return 0; };
+ static void operator delete(void *, size_t) { };
+#endif
+};
+
+JS_BEGIN_EXTERN_C
+#endif
+
+#ifdef DEBUG
+extern JS_PUBLIC_API(void)
+JS_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data);
+#endif
+
+/*
+ * Call JS_MapGCRoots to map the GC's roots table using map(rp, name, data).
+ * The root is pointed at by rp; if the root is unnamed, name is null; data is
+ * supplied from the third parameter to JS_MapGCRoots.
+ *
+ * The map function should return JS_MAP_GCROOT_REMOVE to cause the currently
+ * enumerated root to be removed. To stop enumeration, set JS_MAP_GCROOT_STOP
+ * in the return value. To keep on mapping, return JS_MAP_GCROOT_NEXT. These
+ * constants are flags; you can OR them together.
+ *
+ * This function acquires and releases rt's GC lock around the mapping of the
+ * roots table, so the map function should run to completion in as few cycles
+ * as possible. Of course, map cannot call JS_GC, JS_MaybeGC, JS_BeginRequest,
+ * or any JS API entry point that acquires locks, without double-tripping or
+ * deadlocking on the GC lock.
+ *
+ * JS_MapGCRoots returns the count of roots that were successfully mapped.
+ */
+#define JS_MAP_GCROOT_NEXT 0 /* continue mapping entries */
+#define JS_MAP_GCROOT_STOP 1 /* stop mapping entries */
+#define JS_MAP_GCROOT_REMOVE 2 /* remove and free the current entry */
+
+typedef intN
+(* JSGCRootMapFun)(void *rp, const char *name, void *data);
+
+extern JS_PUBLIC_API(uint32)
+JS_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LockGCThing(JSContext *cx, void *thing);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LockGCThingRT(JSRuntime *rt, void *thing);
+
+extern JS_PUBLIC_API(JSBool)
+JS_UnlockGCThing(JSContext *cx, void *thing);
+
+extern JS_PUBLIC_API(JSBool)
+JS_UnlockGCThingRT(JSRuntime *rt, void *thing);
+
+/*
+ * Register externally maintained GC roots.
+ *
+ * traceOp: the trace operation. For each root the implementation should call
+ * JS_CallTracer whenever the root contains a traceable thing.
+ * data: the data argument to pass to each invocation of traceOp.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetExtraGCRoots(JSRuntime *rt, JSTraceDataOp traceOp, void *data);
+
+/*
+ * For implementors of JSMarkOp. All new code should implement JSTraceOp
+ * instead.
+ */
+extern JS_PUBLIC_API(void)
+JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg);
+
+/*
+ * JS_CallTracer API and related macros for implementors of JSTraceOp, to
+ * enumerate all references to traceable things reachable via a property or
+ * other strong ref identified for debugging purposes by name or index or
+ * a naming callback.
+ *
+ * By definition references to traceable things include non-null pointers
+ * to JSObject, JSString and jsdouble and corresponding jsvals.
+ *
+ * See the JSTraceOp typedef in jspubtd.h.
+ */
+
+/* Trace kinds to pass to JS_Tracing. */
+#define JSTRACE_OBJECT 0
+#define JSTRACE_DOUBLE 1
+#define JSTRACE_STRING 2
+
+/*
+ * Use the following macros to check if a particular jsval is a traceable
+ * thing and to extract the thing and its kind to pass to JS_CallTracer.
+ */
+#define JSVAL_IS_TRACEABLE(v) (JSVAL_IS_GCTHING(v) && !JSVAL_IS_NULL(v))
+#define JSVAL_TO_TRACEABLE(v) (JSVAL_TO_GCTHING(v))
+#define JSVAL_TRACE_KIND(v) (JSVAL_TAG(v) >> 1)
+
+JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_OBJECT) == JSTRACE_OBJECT);
+JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_DOUBLE) == JSTRACE_DOUBLE);
+JS_STATIC_ASSERT(JSVAL_TRACE_KIND(JSVAL_STRING) == JSTRACE_STRING);
+
+struct JSTracer {
+ JSContext *context;
+ JSTraceCallback callback;
+#ifdef DEBUG
+ JSTraceNamePrinter debugPrinter;
+ const void *debugPrintArg;
+ size_t debugPrintIndex;
+#endif
+};
+
+/*
+ * The method to call on each reference to a traceable thing stored in a
+ * particular JSObject or other runtime structure. With DEBUG defined the
+ * caller before calling JS_CallTracer must initialize JSTracer fields
+ * describing the reference using the macros below.
+ */
+extern JS_PUBLIC_API(void)
+JS_CallTracer(JSTracer *trc, void *thing, uint32 kind);
+
+/*
+ * Set debugging information about a reference to a traceable thing to prepare
+ * for the following call to JS_CallTracer.
+ *
+ * When printer is null, arg must be const char * or char * C string naming
+ * the reference and index must be either (size_t)-1 indicating that the name
+ * alone describes the reference or it must be an index into some array vector
+ * that stores the reference.
+ *
+ * When printer callback is not null, the arg and index arguments are
+ * available to the callback as debugPrinterArg and debugPrintIndex fields
+ * of JSTracer.
+ *
+ * The storage for name or callback's arguments needs to live only until
+ * the following call to JS_CallTracer returns.
+ */
+#ifdef DEBUG
+# define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \
+ JS_BEGIN_MACRO \
+ (trc)->debugPrinter = (printer); \
+ (trc)->debugPrintArg = (arg); \
+ (trc)->debugPrintIndex = (index); \
+ JS_END_MACRO
+#else
+# define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \
+ JS_BEGIN_MACRO \
+ JS_END_MACRO
+#endif
+
+/*
+ * Convenience macro to describe the argument of JS_CallTracer using C string
+ * and index.
+ */
+# define JS_SET_TRACING_INDEX(trc, name, index) \
+ JS_SET_TRACING_DETAILS(trc, NULL, name, index)
+
+/*
+ * Convenience macro to describe the argument of JS_CallTracer using C string.
+ */
+# define JS_SET_TRACING_NAME(trc, name) \
+ JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1)
+
+/*
+ * Convenience macro to invoke JS_CallTracer using C string as the name for
+ * the reference to a traceable thing.
+ */
+# define JS_CALL_TRACER(trc, thing, kind, name) \
+ JS_BEGIN_MACRO \
+ JS_SET_TRACING_NAME(trc, name); \
+ JS_CallTracer((trc), (thing), (kind)); \
+ JS_END_MACRO
+
+/*
+ * Convenience macros to invoke JS_CallTracer when jsval represents a
+ * reference to a traceable thing.
+ */
+#define JS_CALL_VALUE_TRACER(trc, val, name) \
+ JS_BEGIN_MACRO \
+ if (JSVAL_IS_TRACEABLE(val)) { \
+ JS_CALL_TRACER((trc), JSVAL_TO_GCTHING(val), \
+ JSVAL_TRACE_KIND(val), name); \
+ } \
+ JS_END_MACRO
+
+#define JS_CALL_OBJECT_TRACER(trc, object, name) \
+ JS_BEGIN_MACRO \
+ JSObject *obj_ = (object); \
+ JS_ASSERT(obj_); \
+ JS_CALL_TRACER((trc), obj_, JSTRACE_OBJECT, name); \
+ JS_END_MACRO
+
+#define JS_CALL_STRING_TRACER(trc, string, name) \
+ JS_BEGIN_MACRO \
+ JSString *str_ = (string); \
+ JS_ASSERT(str_); \
+ JS_CALL_TRACER((trc), str_, JSTRACE_STRING, name); \
+ JS_END_MACRO
+
+#define JS_CALL_DOUBLE_TRACER(trc, number, name) \
+ JS_BEGIN_MACRO \
+ jsdouble *num_ = (number); \
+ JS_ASSERT(num_); \
+ JS_CALL_TRACER((trc), num_, JSTRACE_DOUBLE, name); \
+ JS_END_MACRO
+
+/*
+ * API for JSTraceCallback implementations.
+ */
+# define JS_TRACER_INIT(trc, cx_, callback_) \
+ JS_BEGIN_MACRO \
+ (trc)->context = (cx_); \
+ (trc)->callback = (callback_); \
+ JS_SET_TRACING_DETAILS(trc, NULL, NULL, (size_t)-1); \
+ JS_END_MACRO
+
+extern JS_PUBLIC_API(void)
+JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind);
+
+extern JS_PUBLIC_API(void)
+JS_TraceRuntime(JSTracer *trc);
+
+#ifdef DEBUG
+
+extern JS_PUBLIC_API(void)
+JS_PrintTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc,
+ void *thing, uint32 kind, JSBool includeDetails);
+
+/*
+ * DEBUG-only method to dump the object graph of heap-allocated things.
+ *
+ * fp: file for the dump output.
+ * start: when non-null, dump only things reachable from start
+ * thing. Otherwise dump all things reachable from the
+ * runtime roots.
+ * startKind: trace kind of start if start is not null. Must be 0 when
+ * start is null.
+ * thingToFind: dump only paths in the object graph leading to thingToFind
+ * when non-null.
+ * maxDepth: the upper bound on the number of edges to descend from the
+ * graph roots.
+ * thingToIgnore: thing to ignore during the graph traversal when non-null.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
+ void *thingToFind, size_t maxDepth, void *thingToIgnore);
+
+#endif
+
+/*
+ * Garbage collector API.
+ */
+extern JS_PUBLIC_API(void)
+JS_GC(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_MaybeGC(JSContext *cx);
+
+extern JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallback(JSContext *cx, JSGCCallback cb);
+
+extern JS_PUBLIC_API(JSGCCallback)
+JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsGCMarkingTracer(JSTracer *trc);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsAboutToBeFinalized(JSContext *cx, void *thing);
+
+typedef enum JSGCParamKey {
+ /* Maximum nominal heap before last ditch GC. */
+ JSGC_MAX_BYTES = 0,
+
+ /* Number of JS_malloc bytes before last ditch GC. */
+ JSGC_MAX_MALLOC_BYTES = 1,
+
+ /* Hoard stackPools for this long, in ms, default is 30 seconds. */
+ JSGC_STACKPOOL_LIFESPAN = 2
+} JSGCParamKey;
+
+extern JS_PUBLIC_API(void)
+JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value);
+
+/*
+ * Add a finalizer for external strings created by JS_NewExternalString (see
+ * below) using a type-code returned from this function, and that understands
+ * how to free or release the memory pointed at by JS_GetStringChars(str).
+ *
+ * Return a nonnegative type index if there is room for finalizer in the
+ * global GC finalizers table, else return -1. If the engine is compiled
+ * JS_THREADSAFE and used in a multi-threaded environment, this function must
+ * be invoked on the primordial thread only, at startup -- or else the entire
+ * program must single-thread itself while loading a module that calls this
+ * function.
+ */
+extern JS_PUBLIC_API(intN)
+JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer);
+
+/*
+ * Remove finalizer from the global GC finalizers table, returning its type
+ * code if found, -1 if not found.
+ *
+ * As with JS_AddExternalStringFinalizer, there is a threading restriction
+ * if you compile the engine JS_THREADSAFE: this function may be called for a
+ * given finalizer pointer on only one thread; different threads may call to
+ * remove distinct finalizers safely.
+ *
+ * You must ensure that all strings with finalizer's type have been collected
+ * before calling this function. Otherwise, string data will be leaked by the
+ * GC, for want of a finalizer to call.
+ */
+extern JS_PUBLIC_API(intN)
+JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer);
+
+/*
+ * Create a new JSString whose chars member refers to external memory, i.e.,
+ * memory requiring special, type-specific finalization. The type code must
+ * be a nonnegative return value from JS_AddExternalStringFinalizer.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type);
+
+/*
+ * Returns the external-string finalizer index for this string, or -1 if it is
+ * an "internal" (native to JS engine) string.
+ */
+extern JS_PUBLIC_API(intN)
+JS_GetExternalStringGCType(JSRuntime *rt, JSString *str);
+
+/*
+ * Sets maximum (if stack grows upward) or minimum (downward) legal stack byte
+ * address in limitAddr for the thread or process stack used by cx. To disable
+ * stack size checking, pass 0 for limitAddr.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr);
+
+/*
+ * Set the quota on the number of bytes that stack-like data structures can
+ * use when the runtime compiles and executes scripts. These structures
+ * consume heap space, so JS_SetThreadStackLimit does not bound their size.
+ * The default quota is 32MB which is quite generous.
+ *
+ * The function must be called before any script compilation or execution API
+ * calls, i.e. either immediately after JS_NewContext or from JSCONTEXT_NEW
+ * context callback.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetScriptStackQuota(JSContext *cx, size_t quota);
+
+#define JS_DEFAULT_SCRIPT_STACK_QUOTA ((size_t) 0x2000000)
+
+/************************************************************************/
+
+/*
+ * Classes, objects, and properties.
+ */
+
+/* For detailed comments on the function pointer types, see jspubtd.h. */
+struct JSClass {
+ const char *name;
+ uint32 flags;
+
+ /* Mandatory non-null function pointer members. */
+ JSPropertyOp addProperty;
+ JSPropertyOp delProperty;
+ JSPropertyOp getProperty;
+ JSPropertyOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSConvertOp convert;
+ JSFinalizeOp finalize;
+
+ /* Optionally non-null members start here. */
+ JSGetObjectOps getObjectOps;
+ JSCheckAccessOp checkAccess;
+ JSNative call;
+ JSNative construct;
+ JSXDRObjectOp xdrObject;
+ JSHasInstanceOp hasInstance;
+ JSMarkOp mark;
+ JSReserveSlotsOp reserveSlots;
+};
+
+struct JSExtendedClass {
+ JSClass base;
+ JSEqualityOp equality;
+ JSObjectOp outerObject;
+ JSObjectOp innerObject;
+ JSIteratorOp iteratorObject;
+ JSObjectOp wrappedObject; /* NB: infallible, null
+ returns are treated as
+ the original object */
+ void (*reserved0)(void);
+ void (*reserved1)(void);
+ void (*reserved2)(void);
+};
+
+#define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */
+#define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */
+#define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */
+#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */
+#define JSCLASS_SHARE_ALL_PROPERTIES (1<<4) /* all properties are SHARED */
+#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5) /* JSNewResolveOp gets starting
+ object in prototype chain
+ passed in via *objp in/out
+ parameter */
+#define JSCLASS_CONSTRUCT_PROTOTYPE (1<<6) /* call constructor on class
+ prototype */
+#define JSCLASS_DOCUMENT_OBSERVER (1<<7) /* DOM document observer */
+
+/*
+ * To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or
+ * JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where
+ * n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1.
+ */
+#define JSCLASS_RESERVED_SLOTS_SHIFT 8 /* room for 8 flags below */
+#define JSCLASS_RESERVED_SLOTS_WIDTH 8 /* and 16 above this field */
+#define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH)
+#define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \
+ << JSCLASS_RESERVED_SLOTS_SHIFT)
+#define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \
+ >> JSCLASS_RESERVED_SLOTS_SHIFT) \
+ & JSCLASS_RESERVED_SLOTS_MASK)
+
+#define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \
+ JSCLASS_RESERVED_SLOTS_WIDTH)
+
+/* True if JSClass is really a JSExtendedClass. */
+#define JSCLASS_IS_EXTENDED (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0))
+#define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1))
+#define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2))
+
+/* Indicates that JSClass.mark is a tracer with JSTraceOp type. */
+#define JSCLASS_MARK_IS_TRACE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3))
+
+/*
+ * ECMA-262 requires that most constructors used internally create objects
+ * with "the original Foo.prototype value" as their [[Prototype]] (__proto__)
+ * member initial value. The "original ... value" verbiage is there because
+ * in ECMA-262, global properties naming class objects are read/write and
+ * deleteable, for the most part.
+ *
+ * Implementing this efficiently requires that global objects have classes
+ * with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS won't break
+ * anything except the ECMA-262 "original prototype value" behavior, which was
+ * broken for years in SpiderMonkey. In other words, without these flags you
+ * get backward compatibility.
+ */
+#define JSCLASS_GLOBAL_FLAGS \
+ (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSProto_LIMIT))
+
+/* Fast access to the original value of each standard class's prototype. */
+#define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 8)
+#define JSCLASS_CACHED_PROTO_WIDTH 8
+#define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH)
+#define JSCLASS_HAS_CACHED_PROTO(key) ((key) << JSCLASS_CACHED_PROTO_SHIFT)
+#define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \
+ (((clasp)->flags \
+ >> JSCLASS_CACHED_PROTO_SHIFT) \
+ & JSCLASS_CACHED_PROTO_MASK))
+
+/* Initializer for unused members of statically initialized JSClass structs. */
+#define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,0,0,0
+#define JSCLASS_NO_RESERVED_MEMBERS 0,0,0
+
+/* For detailed comments on these function pointer types, see jspubtd.h. */
+struct JSObjectOps {
+ /* Mandatory non-null function pointer members. */
+ JSNewObjectMapOp newObjectMap;
+ JSObjectMapOp destroyObjectMap;
+ JSLookupPropOp lookupProperty;
+ JSDefinePropOp defineProperty;
+ JSPropertyIdOp getProperty;
+ JSPropertyIdOp setProperty;
+ JSAttributesOp getAttributes;
+ JSAttributesOp setAttributes;
+ JSPropertyIdOp deleteProperty;
+ JSConvertOp defaultValue;
+ JSNewEnumerateOp enumerate;
+ JSCheckAccessIdOp checkAccess;
+
+ /* Optionally non-null members start here. */
+ JSObjectOp thisObject;
+ JSPropertyRefOp dropProperty;
+ JSNative call;
+ JSNative construct;
+ JSXDRObjectOp xdrObject;
+ JSHasInstanceOp hasInstance;
+ JSSetObjectSlotOp setProto;
+ JSSetObjectSlotOp setParent;
+ JSTraceOp trace;
+ JSFinalizeOp clear;
+ JSGetRequiredSlotOp getRequiredSlot;
+ JSSetRequiredSlotOp setRequiredSlot;
+};
+
+struct JSXMLObjectOps {
+ JSObjectOps base;
+ JSGetMethodOp getMethod;
+ JSSetMethodOp setMethod;
+ JSEnumerateValuesOp enumerateValues;
+ JSEqualityOp equality;
+ JSConcatenateOp concatenate;
+};
+
+/*
+ * Classes that expose JSObjectOps via a non-null getObjectOps class hook may
+ * derive a property structure from this struct, return a pointer to it from
+ * lookupProperty and defineProperty, and use the pointer to avoid rehashing
+ * in getAttributes and setAttributes.
+ *
+ * The jsid type contains either an int jsval (see JSVAL_IS_INT above), or an
+ * internal pointer that is opaque to users of this API, but which users may
+ * convert from and to a jsval using JS_ValueToId and JS_IdToValue.
+ */
+struct JSProperty {
+ jsid id;
+};
+
+struct JSIdArray {
+ jsint length;
+ jsid vector[1]; /* actually, length jsid words */
+};
+
+extern JS_PUBLIC_API(void)
+JS_DestroyIdArray(JSContext *cx, JSIdArray *ida);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ValueToId(JSContext *cx, jsval v, jsid *idp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
+
+/*
+ * The magic XML namespace id is int-tagged, but not a valid integer jsval.
+ * Global object classes in embeddings that enable JS_HAS_XML_SUPPORT (E4X)
+ * should handle this id specially before converting id via JSVAL_TO_INT.
+ */
+#define JS_DEFAULT_XML_NAMESPACE_ID ((jsid) JSVAL_VOID)
+
+/*
+ * JSNewResolveOp flag bits.
+ */
+#define JSRESOLVE_QUALIFIED 0x01 /* resolve a qualified property id */
+#define JSRESOLVE_ASSIGNING 0x02 /* resolve on the left of assignment */
+#define JSRESOLVE_DETECTING 0x04 /* 'if (o.p)...' or '(o.p) ?...:...' */
+#define JSRESOLVE_DECLARING 0x08 /* var, const, or function prolog op */
+#define JSRESOLVE_CLASSNAME 0x10 /* class name used when constructing */
+
+extern JS_PUBLIC_API(JSBool)
+JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EnumerateStub(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+
+extern JS_PUBLIC_API(void)
+JS_FinalizeStub(JSContext *cx, JSObject *obj);
+
+struct JSConstDoubleSpec {
+ jsdouble dval;
+ const char *name;
+ uint8 flags;
+ uint8 spare[3];
+};
+
+/*
+ * To define an array element rather than a named property member, cast the
+ * element's index to (const char *) and initialize name with it, and set the
+ * JSPROP_INDEX bit in flags.
+ */
+struct JSPropertySpec {
+ const char *name;
+ int8 tinyid;
+ uint8 flags;
+ JSPropertyOp getter;
+ JSPropertyOp setter;
+};
+
+struct JSFunctionSpec {
+ const char *name;
+ JSNative call;
+ uint16 nargs;
+ uint16 flags;
+
+ /*
+ * extra & 0xFFFF: Number of extra argument slots for local GC roots.
+ * If fast native, must be zero.
+ * extra >> 16: Reserved for future use (must be 0).
+ */
+ uint32 extra;
+};
+
+/*
+ * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
+ * that's passed to JS_DefineFunctions or JS_InitClass.
+ */
+#define JS_FS_END JS_FS(NULL,NULL,0,0,0)
+
+/*
+ * Initializer macro for a JSFunctionSpec array element. This is the original
+ * kind of native function specifier initializer. Use JS_FN ("fast native", see
+ * JSFastNative in jspubtd.h) for all functions that do not need a stack frame
+ * when activated.
+ */
+#define JS_FS(name,call,nargs,flags,extra) \
+ {name, call, nargs, flags, extra}
+
+/*
+ * "Fast native" initializer macro for a JSFunctionSpec array element. Use this
+ * in preference to JS_FS if the native in question does not need its own stack
+ * frame when activated.
+ */
+#define JS_FN(name,fastcall,nargs,flags) \
+ {name, (JSNative)(fastcall), nargs, \
+ (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS, 0}
+
+extern JS_PUBLIC_API(JSObject *)
+JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
+ JSClass *clasp, JSNative constructor, uintN nargs,
+ JSPropertySpec *ps, JSFunctionSpec *fs,
+ JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
+
+#ifdef JS_THREADSAFE
+extern JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSContext *cx, JSObject *obj);
+
+#define JS_GET_CLASS(cx,obj) JS_GetClass(cx, obj)
+#else
+extern JS_PUBLIC_API(JSClass *)
+JS_GetClass(JSObject *obj);
+
+#define JS_GET_CLASS(cx,obj) JS_GetClass(obj)
+#endif
+
+extern JS_PUBLIC_API(JSBool)
+JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+extern JS_PUBLIC_API(void *)
+JS_GetPrivate(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetPrivate(JSContext *cx, JSObject *obj, void *data);
+
+extern JS_PUBLIC_API(void *)
+JS_GetInstancePrivate(JSContext *cx, JSObject *obj, JSClass *clasp,
+ jsval *argv);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetPrototype(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetParent(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetConstructor(JSContext *cx, JSObject *proto);
+
+/*
+ * Get a unique identifier for obj, good for the lifetime of obj (even if it
+ * is moved by a copying GC). Return false on failure (likely out of memory),
+ * and true with *idp containing the unique id on success.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent);
+
+/*
+ * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default
+ * proto if proto's actual parameter value is null.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SealObject(JSContext *cx, JSObject *obj, JSBool deep);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_ConstructObjectWithArguments(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
+ JSObject *proto, uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+
+/*
+ * Determine the attributes (JSPROP_* flags) of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and the value of *attrsp is undefined.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN *attrsp, JSBool *foundp);
+
+/*
+ * The same, but if the property is native, return its getter and setter via
+ * *getterp and *setterp, respectively (and only if the out parameter pointer
+ * is not null).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const char *name,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp);
+
+/*
+ * Set the attributes of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and nothing will be altered.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
+ uintN attrs, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
+ const char *alias);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, const char *name,
+ JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnPropertyById(JSContext *cx, JSObject *obj, jsid id,
+ JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasProperty(JSContext *cx, JSObject *obj, const char *name, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasPropertyById(JSContext *cx, JSObject *obj, jsid id, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, const char *name,
+ uintN flags, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupPropertyWithFlagsById(JSContext *cx, JSObject *obj, jsid id,
+ uintN flags, JSObject **objp, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetProperty(JSContext *cx, JSObject *obj, const char *name, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteProperty(JSContext *cx, JSObject *obj, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteProperty2(JSContext *cx, JSObject *obj, const char *name,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById(JSContext *cx, JSObject *obj, jsid id);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeletePropertyById2(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs);
+
+/*
+ * Determine the attributes (JSPROP_* flags) of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and the value of *attrsp is undefined.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp);
+
+/*
+ * The same, but if the property is native, return its getter and setter via
+ * *getterp and *setterp, respectively (and only if the out parameter pointer
+ * is not null).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_GetUCPropertyAttrsGetterAndSetter(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN *attrsp, JSBool *foundp,
+ JSPropertyOp *getterp,
+ JSPropertyOp *setterp);
+
+/*
+ * Set the attributes of a property on a given object.
+ *
+ * If the object does not have a property by that name, *foundp will be
+ * JS_FALSE and nothing will be altered.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_SetUCPropertyAttributes(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ uintN attrs, JSBool *foundp);
+
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ int8 tinyid, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter,
+ uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnUCProperty(JSContext *cx, JSObject *obj, const jschar *name,
+ size_t namelen, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ JSBool *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetUCProperty(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteUCProperty2(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewArrayObject(JSContext *cx, jsint length, jsval *vector);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsArrayObject(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetArrayLength(JSContext *cx, JSObject *obj, jsuint length);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasArrayLength(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineElement(JSContext *cx, JSObject *obj, jsint index, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias);
+
+extern JS_PUBLIC_API(JSBool)
+JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, jsint index,
+ JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HasElement(JSContext *cx, JSObject *obj, jsint index, JSBool *foundp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_LookupElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetElement(JSContext *cx, JSObject *obj, jsint index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteElement(JSContext *cx, JSObject *obj, jsint index);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DeleteElement2(JSContext *cx, JSObject *obj, jsint index, jsval *rval);
+
+extern JS_PUBLIC_API(void)
+JS_ClearScope(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSIdArray *)
+JS_Enumerate(JSContext *cx, JSObject *obj);
+
+/*
+ * Create an object to iterate over enumerable properties of obj, in arbitrary
+ * property definition order. NB: This differs from longstanding for..in loop
+ * order, which uses order of property definition in obj.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
+
+/*
+ * Return true on success with *idp containing the id of the next enumerable
+ * property to visit using iterobj, or JSVAL_VOID if there is no such property
+ * left to visit. Return false on error.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 index, jsval v);
+
+/************************************************************************/
+
+/*
+ * Security protocol.
+ */
+struct JSPrincipals {
+ char *codebase;
+
+ /* XXX unspecified and unused by Mozilla code -- can we remove these? */
+ void * (* getPrincipalArray)(JSContext *cx, JSPrincipals *);
+ JSBool (* globalPrivilegesEnabled)(JSContext *cx, JSPrincipals *);
+
+ /* Don't call "destroy"; use reference counting macros below. */
+ jsrefcount refcount;
+
+ void (* destroy)(JSContext *cx, JSPrincipals *);
+ JSBool (* subsume)(JSPrincipals *, JSPrincipals *);
+};
+
+#ifdef JS_THREADSAFE
+#define JSPRINCIPALS_HOLD(cx, principals) JS_HoldPrincipals(cx,principals)
+#define JSPRINCIPALS_DROP(cx, principals) JS_DropPrincipals(cx,principals)
+
+extern JS_PUBLIC_API(jsrefcount)
+JS_HoldPrincipals(JSContext *cx, JSPrincipals *principals);
+
+extern JS_PUBLIC_API(jsrefcount)
+JS_DropPrincipals(JSContext *cx, JSPrincipals *principals);
+
+#else
+#define JSPRINCIPALS_HOLD(cx, principals) (++(principals)->refcount)
+#define JSPRINCIPALS_DROP(cx, principals) \
+ ((--(principals)->refcount == 0) \
+ ? ((*(principals)->destroy)((cx), (principals)), 0) \
+ : (principals)->refcount)
+#endif
+
+
+struct JSSecurityCallbacks {
+ JSCheckAccessOp checkObjectAccess;
+ JSPrincipalsTranscoder principalsTranscoder;
+ JSObjectPrincipalsFinder findObjectPrincipals;
+};
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetRuntimeSecurityCallbacks(JSRuntime *rt, JSSecurityCallbacks *callbacks);
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetRuntimeSecurityCallbacks(JSRuntime *rt);
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_SetContextSecurityCallbacks(JSContext *cx, JSSecurityCallbacks *callbacks);
+
+extern JS_PUBLIC_API(JSSecurityCallbacks *)
+JS_GetSecurityCallbacks(JSContext *cx);
+
+/************************************************************************/
+
+/*
+ * Functions and scripts.
+ */
+extern JS_PUBLIC_API(JSFunction *)
+JS_NewFunction(JSContext *cx, JSNative call, uintN nargs, uintN flags,
+ JSObject *parent, const char *name);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFunctionObject(JSFunction *fun);
+
+/*
+ * Deprecated, useful only for diagnostics. Use JS_GetFunctionId instead for
+ * anonymous vs. "anonymous" disambiguation and Unicode fidelity.
+ */
+extern JS_PUBLIC_API(const char *)
+JS_GetFunctionName(JSFunction *fun);
+
+/*
+ * Return the function's identifier as a JSString, or null if fun is unnamed.
+ * The returned string lives as long as fun, so you don't need to root a saved
+ * reference to it if fun is well-connected or rooted, and provided you bound
+ * the use of the saved reference by fun's lifetime.
+ *
+ * Prefer JS_GetFunctionId over JS_GetFunctionName because it returns null for
+ * truly anonymous functions, and because it doesn't chop to ISO-Latin-1 chars
+ * from UTF-16-ish jschars.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_GetFunctionId(JSFunction *fun);
+
+/*
+ * Return JSFUN_* flags for fun.
+ */
+extern JS_PUBLIC_API(uintN)
+JS_GetFunctionFlags(JSFunction *fun);
+
+/*
+ * Return the arity (length) of fun.
+ */
+extern JS_PUBLIC_API(uint16)
+JS_GetFunctionArity(JSFunction *fun);
+
+/*
+ * Infallible predicate to test whether obj is a function object (faster than
+ * comparing obj's class name to "Function", but equivalent unless someone has
+ * overwritten the "Function" identifier with a different constructor and then
+ * created instances using that constructor that might be passed in as obj).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ObjectIsFunction(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DefineFunctions(JSContext *cx, JSObject *obj, JSFunctionSpec *fs);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
+ uintN nargs, uintN attrs);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_DefineUCFunction(JSContext *cx, JSObject *obj,
+ const jschar *name, size_t namelen, JSNative call,
+ uintN nargs, uintN attrs);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
+
+/*
+ * Given a buffer, return JS_FALSE if the buffer might become a valid
+ * javascript statement with the addition of more lines. Otherwise return
+ * JS_TRUE. The intent is to support interactive compilation - accumulate
+ * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
+ * the compiler.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length);
+
+/*
+ * The JSScript objects returned by the following functions refer to string and
+ * other kinds of literals, including doubles and RegExp objects. These
+ * literals are vulnerable to garbage collection; to root script objects and
+ * prevent literals from being collected, create a rootable object using
+ * JS_NewScriptObject, and root the resulting object using JS_Add[Named]Root.
+ */
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileScript(JSContext *cx, JSObject *obj,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
+ FILE *fh);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
+ const char *filename, FILE *fh,
+ JSPrincipals *principals);
+
+/*
+ * NB: you must use JS_NewScriptObject and root a pointer to its return value
+ * in order to keep a JSScript and its atoms safe from garbage collection after
+ * creating the script via JS_Compile* and before a JS_ExecuteScript* call.
+ * E.g., and without error checks:
+ *
+ * JSScript *script = JS_CompileFile(cx, global, filename);
+ * JSObject *scrobj = JS_NewScriptObject(cx, script);
+ * JS_AddNamedRoot(cx, &scrobj, "scrobj");
+ * do {
+ * jsval result;
+ * JS_ExecuteScript(cx, global, script, &result);
+ * JS_GC();
+ * } while (!JSVAL_IS_BOOLEAN(result) || JSVAL_TO_BOOLEAN(result));
+ * JS_RemoveRoot(cx, &scrobj);
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewScriptObject(JSContext *cx, JSScript *script);
+
+/*
+ * Infallible getter for a script's object. If JS_NewScriptObject has not been
+ * called on script yet, the return value will be null.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_GetScriptObject(JSScript *script);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyScript(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const char *bytes, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals, const char *name,
+ uintN nargs, const char **argnames,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JS_PUBLIC_API(JSString *)
+JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
+ uintN indent);
+
+/*
+ * API extension: OR this into indent to avoid pretty-printing the decompiled
+ * source resulting from JS_DecompileFunction{,Body}.
+ */
+#define JS_DONT_PRETTY_PRINT ((uintN)0x8000)
+
+extern JS_PUBLIC_API(JSString *)
+JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent);
+
+extern JS_PUBLIC_API(JSString *)
+JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, uintN indent);
+
+/*
+ * NB: JS_ExecuteScript, JS_ExecuteScriptPart, and the JS_Evaluate*Script*
+ * quadruplets all use the obj parameter as the initial scope chain header,
+ * the 'this' keyword value, and the variables object (ECMA parlance for where
+ * 'var' and 'function' bind names) of the execution context for script.
+ *
+ * Using obj as the variables object is problematic if obj's parent (which is
+ * the scope chain link; see JS_SetParent and JS_NewObject) is not null: in
+ * this case, variables created by 'var x = 0', e.g., go in obj, but variables
+ * created by assignment to an unbound id, 'x = 0', go in the last object on
+ * the scope chain linked by parent.
+ *
+ * ECMA calls that last scoping object the "global object", but note that many
+ * embeddings have several such objects. ECMA requires that "global code" be
+ * executed with the variables object equal to this global object. But these
+ * JS API entry points provide freedom to execute code against a "sub-global",
+ * i.e., a parented or scoped object, in which case the variables object will
+ * differ from the last object on the scope chain, resulting in confusing and
+ * non-ECMA explicit vs. implicit variable creation.
+ *
+ * Caveat embedders: unless you already depend on this buggy variables object
+ * binding behavior, you should call JS_SetOptions(cx, JSOPTION_VAROBJFIX) or
+ * JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_VAROBJFIX) -- the latter if
+ * someone may have set other options on cx already -- for each context in the
+ * application, if you pass parented objects as the obj parameter, or may ever
+ * pass such objects in the future.
+ *
+ * Why a runtime option? The alternative is to add six or so new API entry
+ * points with signatures matching the following six, and that doesn't seem
+ * worth the code bloat cost. Such new entry points would probably have less
+ * obvious names, too, so would not tend to be used. The JS_SetOption call,
+ * OTOH, can be more easily hacked into existing code that does not depend on
+ * the bug; such code can continue to use the familiar JS_EvaluateScript,
+ * etc., entry points.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval);
+
+/*
+ * Execute either the function-defining prolog of a script, or the script's
+ * main body, but not both.
+ */
+typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart;
+
+extern JS_PUBLIC_API(JSBool)
+JS_ExecuteScriptPart(JSContext *cx, JSObject *obj, JSScript *script,
+ JSExecPart part, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateScript(JSContext *cx, JSObject *obj,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
+ JSPrincipals *principals,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc,
+ jsval *argv, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
+ jsval *argv, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
+ jsval *argv, jsval *rval);
+
+/*
+ * The maximum value of the operation limit to pass to JS_SetOperationCallback
+ * and JS_SetOperationLimit.
+ */
+#define JS_MAX_OPERATION_LIMIT ((uint32) 0x7FFFFFFF)
+
+#define JS_OPERATION_WEIGHT_BASE 4096
+
+/*
+ * Set the operation callback that the engine calls periodically after
+ * the internal operation count reaches the specified limit.
+ *
+ * When operationLimit is JS_OPERATION_WEIGHT_BASE, the callback will be
+ * called at least after each backward jump in the interpreter. To minimize
+ * the overhead of the callback invocation we suggest at least
+ *
+ * 100 * JS_OPERATION_WEIGHT_BASE
+ *
+ * as a value for operationLimit.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetOperationCallback(JSContext *cx, JSOperationCallback callback,
+ uint32 operationLimit);
+
+extern JS_PUBLIC_API(void)
+JS_ClearOperationCallback(JSContext *cx);
+
+extern JS_PUBLIC_API(JSOperationCallback)
+JS_GetOperationCallback(JSContext *cx);
+
+/*
+ * Get the operation limit associated with the operation callback. This API
+ * function may be called only when the result of JS_GetOperationCallback(cx)
+ * is not null.
+ */
+extern JS_PUBLIC_API(uint32)
+JS_GetOperationLimit(JSContext *cx);
+
+/*
+ * Change the operation limit associated with the operation callback. This API
+ * function may be called only when the result of JS_GetOperationCallback(cx)
+ * is not null.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetOperationLimit(JSContext *cx, uint32 operationLimit);
+
+/*
+ * Note well: JS_SetBranchCallback is deprecated. It is similar to
+ *
+ * JS_SetOperationCallback(cx, callback, 4096, NULL);
+ *
+ * except that the callback will not be called from a long-running native
+ * function when JSOPTION_NATIVE_BRANCH_CALLBACK is not set and the top-most
+ * frame is native.
+ */
+extern JS_PUBLIC_API(JSBranchCallback)
+JS_SetBranchCallback(JSContext *cx, JSBranchCallback cb);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsRunning(JSContext *cx);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsConstructing(JSContext *cx);
+
+/*
+ * Returns true if a script is executing and its current bytecode is a set
+ * (assignment) operation, even if there are native (no script) stack frames
+ * between the script and the caller to JS_IsAssigning.
+ */
+extern JS_FRIEND_API(JSBool)
+JS_IsAssigning(JSContext *cx);
+
+/*
+ * Set the second return value, which should be a string or int jsval that
+ * identifies a property in the returned object, to form an ECMA reference
+ * type value (obj, id). Only native methods can return reference types,
+ * and if the returned value is used on the left-hand side of an assignment
+ * op, the identified property will be set. If the return value is in an
+ * r-value, the interpreter just gets obj[id]'s value.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetCallReturnValue2(JSContext *cx, jsval v);
+
+/*
+ * Saving and restoring frame chains.
+ *
+ * These two functions are used to set aside cx's call stack while that stack
+ * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no
+ * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack
+ * must be balanced and all nested calls to JS_SaveFrameChain must have had
+ * matching JS_RestoreFrameChain calls.
+ *
+ * JS_SaveFrameChain deals with cx not having any code running on it. A null
+ * return does not signify an error, and JS_RestoreFrameChain handles a null
+ * frame pointer argument safely.
+ */
+extern JS_PUBLIC_API(JSStackFrame *)
+JS_SaveFrameChain(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp);
+
+/************************************************************************/
+
+/*
+ * Strings.
+ *
+ * NB: JS_NewString takes ownership of bytes on success, avoiding a copy; but
+ * on error (signified by null return), it leaves bytes owned by the caller.
+ * So the caller must free bytes in the error case, if it has no use for them.
+ * In contrast, all the JS_New*StringCopy* functions do not take ownership of
+ * the character memory passed to them -- they copy it.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewString(JSContext *cx, char *bytes, size_t length);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewStringCopyN(JSContext *cx, const char *s, size_t n);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewStringCopyZ(JSContext *cx, const char *s);
+
+extern JS_PUBLIC_API(JSString *)
+JS_InternString(JSContext *cx, const char *s);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewUCString(JSContext *cx, jschar *chars, size_t length);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n);
+
+extern JS_PUBLIC_API(JSString *)
+JS_NewUCStringCopyZ(JSContext *cx, const jschar *s);
+
+extern JS_PUBLIC_API(JSString *)
+JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length);
+
+extern JS_PUBLIC_API(JSString *)
+JS_InternUCString(JSContext *cx, const jschar *s);
+
+extern JS_PUBLIC_API(char *)
+JS_GetStringBytes(JSString *str);
+
+extern JS_PUBLIC_API(jschar *)
+JS_GetStringChars(JSString *str);
+
+extern JS_PUBLIC_API(size_t)
+JS_GetStringLength(JSString *str);
+
+extern JS_PUBLIC_API(intN)
+JS_CompareStrings(JSString *str1, JSString *str2);
+
+/*
+ * Mutable string support. A string's characters are never mutable in this JS
+ * implementation, but a growable string has a buffer that can be reallocated,
+ * and a dependent string is a substring of another (growable, dependent, or
+ * immutable) string. The direct data members of the (opaque to API clients)
+ * JSString struct may be changed in a single-threaded way for growable and
+ * dependent strings.
+ *
+ * Therefore mutable strings cannot be used by more than one thread at a time.
+ * You may call JS_MakeStringImmutable to convert the string from a mutable
+ * (growable or dependent) string to an immutable (and therefore thread-safe)
+ * string. The engine takes care of converting growable and dependent strings
+ * to immutable for you if you store strings in multi-threaded objects using
+ * JS_SetProperty or kindred API entry points.
+ *
+ * If you store a JSString pointer in a native data structure that is (safely)
+ * accessible to multiple threads, you must call JS_MakeStringImmutable before
+ * retiring the store.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewGrowableString(JSContext *cx, jschar *chars, size_t length);
+
+/*
+ * Create a dependent string, i.e., a string that owns no character storage,
+ * but that refers to a slice of another string's chars. Dependent strings
+ * are mutable by definition, so the thread safety comments above apply.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_NewDependentString(JSContext *cx, JSString *str, size_t start,
+ size_t length);
+
+/*
+ * Concatenate two strings, resulting in a new growable string. If you create
+ * the left string and pass it to JS_ConcatStrings on a single thread, try to
+ * use JS_NewGrowableString to create the left string -- doing so helps Concat
+ * avoid allocating a new buffer for the result and copying left's chars into
+ * the new buffer. See above for thread safety comments.
+ */
+extern JS_PUBLIC_API(JSString *)
+JS_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
+
+/*
+ * Convert a dependent string into an independent one. This function does not
+ * change the string's mutability, so the thread safety comments above apply.
+ */
+extern JS_PUBLIC_API(const jschar *)
+JS_UndependString(JSContext *cx, JSString *str);
+
+/*
+ * Convert a mutable string (either growable or dependent) into an immutable,
+ * thread-safe one.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_MakeStringImmutable(JSContext *cx, JSString *str);
+
+/*
+ * Return JS_TRUE if C (char []) strings passed via the API and internally
+ * are UTF-8.
+ */
+JS_PUBLIC_API(JSBool)
+JS_CStringsAreUTF8(void);
+
+/*
+ * Update the value to be returned by JS_CStringsAreUTF8(). Once set, it
+ * can never be changed. This API must be called before the first call to
+ * JS_NewRuntime.
+ */
+JS_PUBLIC_API(void)
+JS_SetCStringsAreUTF8(void);
+
+/*
+ * Character encoding support.
+ *
+ * For both JS_EncodeCharacters and JS_DecodeBytes, set *dstlenp to the size
+ * of the destination buffer before the call; on return, *dstlenp contains the
+ * number of bytes (JS_EncodeCharacters) or jschars (JS_DecodeBytes) actually
+ * stored. To determine the necessary destination buffer size, make a sizing
+ * call that passes NULL for dst.
+ *
+ * On errors, the functions report the error. In that case, *dstlenp contains
+ * the number of characters or bytes transferred so far. If cx is NULL, no
+ * error is reported on failure, and the functions simply return JS_FALSE.
+ *
+ * NB: Neither function stores an additional zero byte or jschar after the
+ * transcoded string.
+ *
+ * If JS_CStringsAreUTF8() is true then JS_EncodeCharacters encodes to
+ * UTF-8, and JS_DecodeBytes decodes from UTF-8, which may create additional
+ * errors if the character sequence is malformed. If UTF-8 support is
+ * disabled, the functions deflate and inflate, respectively.
+ */
+JS_PUBLIC_API(JSBool)
+JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
+ size_t *dstlenp);
+
+JS_PUBLIC_API(JSBool)
+JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
+ size_t *dstlenp);
+
+/*
+ * A variation on JS_EncodeCharacters where a null terminated string is
+ * returned that you are expected to call JS_free on when done.
+ */
+JS_PUBLIC_API(char *)
+JS_EncodeString(JSContext *cx, JSString *str);
+
+/************************************************************************/
+/*
+ * JSON functions
+ */
+typedef JSBool (* JSONWriteCallback)(const jschar *buf, uint32 len, void *data);
+
+/*
+ * JSON.stringify as specificed by ES3.1 (draft)
+ */
+JS_PUBLIC_API(JSBool)
+JS_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data);
+
+/*
+ * Retrieve a toJSON function. If found, set vp to its result.
+ */
+JS_PUBLIC_API(JSBool)
+JS_TryJSON(JSContext *cx, jsval *vp);
+
+/*
+ * JSON.parse as specificed by ES3.1 (draft)
+ */
+JS_PUBLIC_API(JSONParser *)
+JS_BeginJSONParse(JSContext *cx, jsval *vp);
+
+JS_PUBLIC_API(JSBool)
+JS_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len);
+
+JS_PUBLIC_API(JSBool)
+JS_FinishJSONParse(JSContext *cx, JSONParser *jp);
+
+/************************************************************************/
+
+/*
+ * Locale specific string conversion and error message callbacks.
+ */
+struct JSLocaleCallbacks {
+ JSLocaleToUpperCase localeToUpperCase;
+ JSLocaleToLowerCase localeToLowerCase;
+ JSLocaleCompare localeCompare;
+ JSLocaleToUnicode localeToUnicode;
+ JSErrorCallback localeGetErrorMessage;
+};
+
+/*
+ * Establish locale callbacks. The pointer must persist as long as the
+ * JSContext. Passing NULL restores the default behaviour.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks);
+
+/*
+ * Return the address of the current locale callbacks struct, which may
+ * be NULL.
+ */
+extern JS_PUBLIC_API(JSLocaleCallbacks *)
+JS_GetLocaleCallbacks(JSContext *cx);
+
+/************************************************************************/
+
+/*
+ * Error reporting.
+ */
+
+/*
+ * Report an exception represented by the sprintf-like conversion of format
+ * and its arguments. This exception message string is passed to a pre-set
+ * JSErrorReporter function (set by JS_SetErrorReporter; see jspubtd.h for
+ * the JSErrorReporter typedef).
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportError(JSContext *cx, const char *format, ...);
+
+/*
+ * Use an errorNumber to retrieve the format string, args are char *
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...);
+
+/*
+ * Use an errorNumber to retrieve the format string, args are jschar *
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
+ void *userRef, const uintN errorNumber, ...);
+
+/*
+ * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
+ * Return true if there was no error trying to issue the warning, and if the
+ * warning was not converted into an error due to the JSOPTION_WERROR option
+ * being set, false otherwise.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ReportWarning(JSContext *cx, const char *format, ...);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumber(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ReportErrorFlagsAndNumberUC(JSContext *cx, uintN flags,
+ JSErrorCallback errorCallback, void *userRef,
+ const uintN errorNumber, ...);
+
+/*
+ * Complain when out of memory.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportOutOfMemory(JSContext *cx);
+
+/*
+ * Complain when an allocation size overflows the maximum supported limit.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportAllocationOverflow(JSContext *cx);
+
+struct JSErrorReport {
+ const char *filename; /* source file name, URL, etc., or null */
+ uintN lineno; /* source line number */
+ const char *linebuf; /* offending source line without final \n */
+ const char *tokenptr; /* pointer to error token in linebuf */
+ const jschar *uclinebuf; /* unicode (original) line buffer */
+ const jschar *uctokenptr; /* unicode (original) token pointer */
+ uintN flags; /* error/warning, etc. */
+ uintN errorNumber; /* the error number, e.g. see js.msg */
+ const jschar *ucmessage; /* the (default) error message */
+ const jschar **messageArgs; /* arguments for the error message */
+};
+
+/*
+ * JSErrorReport flag values. These may be freely composed.
+ */
+#define JSREPORT_ERROR 0x0 /* pseudo-flag for default case */
+#define JSREPORT_WARNING 0x1 /* reported via JS_ReportWarning */
+#define JSREPORT_EXCEPTION 0x2 /* exception was thrown */
+#define JSREPORT_STRICT 0x4 /* error or warning due to strict option */
+
+/*
+ * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
+ * has been thrown for this runtime error, and the host should ignore it.
+ * Exception-aware hosts should also check for JS_IsExceptionPending if
+ * JS_ExecuteScript returns failure, and signal or propagate the exception, as
+ * appropriate.
+ */
+#define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0)
+#define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0)
+#define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0)
+
+extern JS_PUBLIC_API(JSErrorReporter)
+JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
+
+/************************************************************************/
+
+/*
+ * Regular Expressions.
+ */
+#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */
+#define JSREG_GLOB 0x02 /* global exec, creates array of matches */
+#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */
+#define JSREG_STICKY 0x08 /* only match starting at lastIndex */
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewRegExpObject(JSContext *cx, char *bytes, size_t length, uintN flags);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_NewUCRegExpObject(JSContext *cx, jschar *chars, size_t length, uintN flags);
+
+extern JS_PUBLIC_API(void)
+JS_SetRegExpInput(JSContext *cx, JSString *input, JSBool multiline);
+
+extern JS_PUBLIC_API(void)
+JS_ClearRegExpStatics(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_ClearRegExpRoots(JSContext *cx);
+
+/* TODO: compile, exec, get/set other statics... */
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsExceptionPending(JSContext *cx);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPendingException(JSContext *cx, jsval *vp);
+
+extern JS_PUBLIC_API(void)
+JS_SetPendingException(JSContext *cx, jsval v);
+
+extern JS_PUBLIC_API(void)
+JS_ClearPendingException(JSContext *cx);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ReportPendingException(JSContext *cx);
+
+/*
+ * Save the current exception state. This takes a snapshot of cx's current
+ * exception state without making any change to that state.
+ *
+ * The returned state pointer MUST be passed later to JS_RestoreExceptionState
+ * (to restore that saved state, overriding any more recent state) or else to
+ * JS_DropExceptionState (to free the state struct in case it is not correct
+ * or desirable to restore it). Both Restore and Drop free the state struct,
+ * so callers must stop using the pointer returned from Save after calling the
+ * Release or Drop API.
+ */
+extern JS_PUBLIC_API(JSExceptionState *)
+JS_SaveExceptionState(JSContext *cx);
+
+extern JS_PUBLIC_API(void)
+JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state);
+
+extern JS_PUBLIC_API(void)
+JS_DropExceptionState(JSContext *cx, JSExceptionState *state);
+
+/*
+ * If the given value is an exception object that originated from an error,
+ * the exception will contain an error report struct, and this API will return
+ * the address of that struct. Otherwise, it returns NULL. The lifetime of
+ * the error report struct that might be returned is the same as the lifetime
+ * of the exception object.
+ */
+extern JS_PUBLIC_API(JSErrorReport *)
+JS_ErrorFromException(JSContext *cx, jsval v);
+
+/*
+ * Given a reported error's message and JSErrorReport struct pointer, throw
+ * the corresponding exception on cx.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ThrowReportedError(JSContext *cx, const char *message,
+ JSErrorReport *reportp);
+
+/*
+ * Throws a StopIteration exception on cx.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_ThrowStopIteration(JSContext *cx);
+
+/*
+ * Associate the current thread with the given context. This is done
+ * implicitly by JS_NewContext.
+ *
+ * Returns the old thread id for this context, which should be treated as
+ * an opaque value. This value is provided for comparison to 0, which
+ * indicates that ClearContextThread has been called on this context
+ * since the last SetContextThread, or non-0, which indicates the opposite.
+ */
+extern JS_PUBLIC_API(jsword)
+JS_GetContextThread(JSContext *cx);
+
+extern JS_PUBLIC_API(jsword)
+JS_SetContextThread(JSContext *cx);
+
+extern JS_PUBLIC_API(jsword)
+JS_ClearContextThread(JSContext *cx);
+
+/************************************************************************/
+
+#ifdef DEBUG
+#define JS_GC_ZEAL 1
+#endif
+
+#ifdef JS_GC_ZEAL
+extern JS_PUBLIC_API(void)
+JS_SetGCZeal(JSContext *cx, uint8 zeal);
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsapi_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp
new file mode 100644
index 0000000..f632552
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.cpp
@@ -0,0 +1,450 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+
+#ifdef JS_ARENAMETER
+static JSArenaStats *arena_stats_list;
+
+#define COUNT(pool,what) (pool)->stats.what++
+#else
+#define COUNT(pool,what) /* nothing */
+#endif
+
+#define JS_ARENA_DEFAULT_ALIGN sizeof(double)
+
+JS_PUBLIC_API(void)
+JS_INIT_NAMED_ARENA_POOL(JSArenaPool *pool, const char *name, size_t size,
+ size_t align, size_t *quotap)
+{
+ if (align == 0)
+ align = JS_ARENA_DEFAULT_ALIGN;
+ pool->mask = JS_BITMASK(JS_CeilingLog2(align));
+ pool->first.next = NULL;
+ pool->first.base = pool->first.avail = pool->first.limit =
+ JS_ARENA_ALIGN(pool, &pool->first + 1);
+ pool->current = &pool->first;
+ pool->arenasize = size;
+ pool->quotap = quotap;
+#ifdef JS_ARENAMETER
+ memset(&pool->stats, 0, sizeof pool->stats);
+ pool->stats.name = strdup(name);
+ pool->stats.next = arena_stats_list;
+ arena_stats_list = &pool->stats;
+#endif
+}
+
+/*
+ * An allocation that consumes more than pool->arenasize also has a header
+ * pointing back to its previous arena's next member. This header is not
+ * included in [a->base, a->limit), so its space can't be wrongly claimed.
+ *
+ * As the header is a pointer, it must be well-aligned. If pool->mask is
+ * greater than or equal to POINTER_MASK, the header just preceding a->base
+ * for an oversized arena a is well-aligned, because a->base is well-aligned.
+ * However, we may need to add more space to pad the JSArena ** back-pointer
+ * so that it lies just behind a->base, because a might not be aligned such
+ * that (jsuword)(a + 1) is on a pointer boundary.
+ *
+ * By how much must we pad? Let M be the alignment modulus for pool and P
+ * the modulus for a pointer. Given M >= P, the base of an oversized arena
+ * that satisfies M is well-aligned for P.
+ *
+ * On the other hand, if M < P, we must include enough space in the header
+ * size to align the back-pointer on a P boundary so that it can be found by
+ * subtracting P from a->base. This means a->base must be on a P boundary,
+ * even though subsequent allocations from a may be aligned on a lesser (M)
+ * boundary. Given powers of two M and P as above, the extra space needed
+ * when M < P is P-M or POINTER_MASK - pool->mask.
+ *
+ * The size of a header including padding is given by the HEADER_SIZE macro,
+ * below, for any pool (for any value of M).
+ *
+ * The mask to align a->base for any pool is (pool->mask | POINTER_MASK), or
+ * HEADER_BASE_MASK(pool).
+ *
+ * PTR_TO_HEADER computes the address of the back-pointer, given an oversized
+ * allocation at p. By definition, p must be a->base for the arena a that
+ * contains p. GET_HEADER and SET_HEADER operate on an oversized arena a, in
+ * the case of SET_HEADER with back-pointer ap.
+ */
+#define POINTER_MASK ((jsuword)(JS_ALIGN_OF_POINTER - 1))
+#define HEADER_SIZE(pool) (sizeof(JSArena **) \
+ + (((pool)->mask < POINTER_MASK) \
+ ? POINTER_MASK - (pool)->mask \
+ : 0))
+#define HEADER_BASE_MASK(pool) ((pool)->mask | POINTER_MASK)
+#define PTR_TO_HEADER(pool,p) (JS_ASSERT(((jsuword)(p) \
+ & HEADER_BASE_MASK(pool)) \
+ == 0), \
+ (JSArena ***)(p) - 1)
+#define GET_HEADER(pool,a) (*PTR_TO_HEADER(pool, (a)->base))
+#define SET_HEADER(pool,a,ap) (*PTR_TO_HEADER(pool, (a)->base) = (ap))
+
+JS_PUBLIC_API(void *)
+JS_ArenaAllocate(JSArenaPool *pool, size_t nb)
+{
+ JSArena **ap, *a, *b;
+ jsuword extra, hdrsz, gross;
+ void *p;
+
+ /*
+ * Search pool from current forward till we find or make enough space.
+ *
+ * NB: subtract nb from a->limit in the loop condition, instead of adding
+ * nb to a->avail, to avoid overflowing a 32-bit address space (possible
+ * when running a 32-bit program on a 64-bit system where the kernel maps
+ * the heap up against the top of the 32-bit address space).
+ *
+ * Thanks to Juergen Kreileder <jk@blackdown.de>, who brought this up in
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=279273.
+ */
+ JS_ASSERT((nb & pool->mask) == 0);
+ for (a = pool->current; nb > a->limit || a->avail > a->limit - nb;
+ pool->current = a) {
+ ap = &a->next;
+ if (!*ap) {
+ /* Not enough space in pool, so we must malloc. */
+ extra = (nb > pool->arenasize) ? HEADER_SIZE(pool) : 0;
+ hdrsz = sizeof *a + extra + pool->mask;
+ gross = hdrsz + JS_MAX(nb, pool->arenasize);
+ if (gross < nb)
+ return NULL;
+ if (pool->quotap) {
+ if (gross > *pool->quotap)
+ return NULL;
+ b = (JSArena *) malloc(gross);
+ if (!b)
+ return NULL;
+ *pool->quotap -= gross;
+ } else {
+ b = (JSArena *) malloc(gross);
+ if (!b)
+ return NULL;
+ }
+
+ b->next = NULL;
+ b->limit = (jsuword)b + gross;
+ JS_COUNT_ARENA(pool,++);
+ COUNT(pool, nmallocs);
+
+ /* If oversized, store ap in the header, just before a->base. */
+ *ap = a = b;
+ JS_ASSERT(gross <= JS_UPTRDIFF(a->limit, a));
+ if (extra) {
+ a->base = a->avail =
+ ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool);
+ SET_HEADER(pool, a, ap);
+ } else {
+ a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1);
+ }
+ continue;
+ }
+ a = *ap; /* move to next arena */
+ }
+
+ p = (void *)a->avail;
+ a->avail += nb;
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ return p;
+}
+
+JS_PUBLIC_API(void *)
+JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr)
+{
+ JSArena **ap, *a, *b;
+ jsuword boff, aoff, extra, hdrsz, gross, growth;
+
+ /*
+ * Use the oversized-single-allocation header to avoid searching for ap.
+ * See JS_ArenaAllocate, the SET_HEADER call.
+ */
+ if (size > pool->arenasize) {
+ ap = *PTR_TO_HEADER(pool, p);
+ a = *ap;
+ } else {
+ ap = &pool->first.next;
+ while ((a = *ap) != pool->current)
+ ap = &a->next;
+ }
+
+ JS_ASSERT(a->base == (jsuword)p);
+ boff = JS_UPTRDIFF(a->base, a);
+ aoff = JS_ARENA_ALIGN(pool, size + incr);
+ JS_ASSERT(aoff > pool->arenasize);
+ extra = HEADER_SIZE(pool); /* oversized header holds ap */
+ hdrsz = sizeof *a + extra + pool->mask; /* header and alignment slop */
+ gross = hdrsz + aoff;
+ JS_ASSERT(gross > aoff);
+ if (pool->quotap) {
+ growth = gross - (a->limit - (jsuword) a);
+ if (growth > *pool->quotap)
+ return NULL;
+ a = (JSArena *) realloc(a, gross);
+ if (!a)
+ return NULL;
+ *pool->quotap -= growth;
+ } else {
+ a = (JSArena *) realloc(a, gross);
+ if (!a)
+ return NULL;
+ }
+#ifdef JS_ARENAMETER
+ pool->stats.nreallocs++;
+#endif
+
+ if (a != *ap) {
+ /* Oops, realloc moved the allocation: update other pointers to a. */
+ if (pool->current == *ap)
+ pool->current = a;
+ b = a->next;
+ if (b && b->avail - b->base > pool->arenasize) {
+ JS_ASSERT(GET_HEADER(pool, b) == &(*ap)->next);
+ SET_HEADER(pool, b, &a->next);
+ }
+
+ /* Now update *ap, the next link of the arena before a. */
+ *ap = a;
+ }
+
+ a->base = ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool);
+ a->limit = (jsuword)a + gross;
+ a->avail = a->base + aoff;
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+
+ /* Check whether realloc aligned differently, and copy if necessary. */
+ if (boff != JS_UPTRDIFF(a->base, a))
+ memmove((void *)a->base, (char *)a + boff, size);
+
+ /* Store ap in the oversized-load arena header. */
+ SET_HEADER(pool, a, ap);
+ return (void *)a->base;
+}
+
+JS_PUBLIC_API(void *)
+JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr)
+{
+ void *newp;
+
+ /*
+ * If p points to an oversized allocation, it owns an entire arena, so we
+ * can simply realloc the arena.
+ */
+ if (size > pool->arenasize)
+ return JS_ArenaRealloc(pool, p, size, incr);
+
+ JS_ARENA_ALLOCATE(newp, pool, size + incr);
+ if (newp)
+ memcpy(newp, p, size);
+ return newp;
+}
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void
+FreeArenaList(JSArenaPool *pool, JSArena *head)
+{
+ JSArena **ap, *a;
+
+ ap = &head->next;
+ a = *ap;
+ if (!a)
+ return;
+
+#ifdef DEBUG
+ do {
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+ a->avail = a->base;
+ JS_CLEAR_UNUSED(a);
+ } while ((a = a->next) != NULL);
+ a = *ap;
+#endif
+
+ do {
+ *ap = a->next;
+ if (pool->quotap)
+ *pool->quotap += a->limit - (jsuword) a;
+ JS_CLEAR_ARENA(a);
+ JS_COUNT_ARENA(pool,--);
+ free(a);
+ } while ((a = *ap) != NULL);
+
+ pool->current = head;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaRelease(JSArenaPool *pool, char *mark)
+{
+ JSArena *a;
+
+ for (a = &pool->first; a; a = a->next) {
+ JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+
+ if (JS_ARENA_MARK_MATCH(a, mark)) {
+ a->avail = JS_ARENA_ALIGN(pool, mark);
+ JS_ASSERT(a->avail <= a->limit);
+ FreeArenaList(pool, a);
+ return;
+ }
+ }
+}
+
+JS_PUBLIC_API(void)
+JS_FreeArenaPool(JSArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first);
+ COUNT(pool, ndeallocs);
+}
+
+JS_PUBLIC_API(void)
+JS_FinishArenaPool(JSArenaPool *pool)
+{
+ FreeArenaList(pool, &pool->first);
+#ifdef JS_ARENAMETER
+ {
+ JSArenaStats *stats, **statsp;
+
+ if (pool->stats.name) {
+ free(pool->stats.name);
+ pool->stats.name = NULL;
+ }
+ for (statsp = &arena_stats_list; (stats = *statsp) != 0;
+ statsp = &stats->next) {
+ if (stats == &pool->stats) {
+ *statsp = stats->next;
+ return;
+ }
+ }
+ }
+#endif
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaFinish()
+{
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaShutDown(void)
+{
+}
+
+#ifdef JS_ARENAMETER
+JS_PUBLIC_API(void)
+JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb)
+{
+ pool->stats.nallocs++;
+ pool->stats.nbytes += nb;
+ if (nb > pool->stats.maxalloc)
+ pool->stats.maxalloc = nb;
+ pool->stats.variance += nb * nb;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr)
+{
+ pool->stats.ninplace++;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr)
+{
+ pool->stats.ngrows++;
+ pool->stats.nbytes += incr;
+ pool->stats.variance -= size * size;
+ size += incr;
+ if (size > pool->stats.maxalloc)
+ pool->stats.maxalloc = size;
+ pool->stats.variance += size * size;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountRelease(JSArenaPool *pool, char *mark)
+{
+ pool->stats.nreleases++;
+}
+
+JS_PUBLIC_API(void)
+JS_ArenaCountRetract(JSArenaPool *pool, char *mark)
+{
+ pool->stats.nfastrels++;
+}
+
+#include <stdio.h>
+
+JS_PUBLIC_API(void)
+JS_DumpArenaStats(FILE *fp)
+{
+ JSArenaStats *stats;
+ double mean, sigma;
+
+ for (stats = arena_stats_list; stats; stats = stats->next) {
+ mean = JS_MeanAndStdDev(stats->nallocs, stats->nbytes, stats->variance,
+ &sigma);
+
+ fprintf(fp, "\n%s allocation statistics:\n", stats->name);
+ fprintf(fp, " number of arenas: %u\n", stats->narenas);
+ fprintf(fp, " number of allocations: %u\n", stats->nallocs);
+ fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs);
+ fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs);
+ fprintf(fp, " number of allocation growths: %u\n", stats->ngrows);
+ fprintf(fp, " number of in-place growths: %u\n", stats->ninplace);
+ fprintf(fp, " number of realloc'ing growths: %u\n", stats->nreallocs);
+ fprintf(fp, "number of released allocations: %u\n", stats->nreleases);
+ fprintf(fp, " number of fast releases: %u\n", stats->nfastrels);
+ fprintf(fp, " total bytes allocated: %u\n", stats->nbytes);
+ fprintf(fp, " mean allocation size: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
+ }
+}
+#endif /* JS_ARENAMETER */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarena.h b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.h
new file mode 100644
index 0000000..8e99a74
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarena.h
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsarena_h___
+#define jsarena_h___
+/*
+ * Lifetime-based fast allocation, inspired by much prior art, including
+ * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+ * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+ *
+ * Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
+ */
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef struct JSArena JSArena;
+typedef struct JSArenaPool JSArenaPool;
+
+struct JSArena {
+ JSArena *next; /* next arena for this lifetime */
+ jsuword base; /* aligned base address, follows this header */
+ jsuword limit; /* one beyond last byte in arena */
+ jsuword avail; /* points to next available byte */
+};
+
+#ifdef JS_ARENAMETER
+typedef struct JSArenaStats JSArenaStats;
+
+struct JSArenaStats {
+ JSArenaStats *next; /* next in arenaStats list */
+ char *name; /* name for debugging */
+ uint32 narenas; /* number of arenas in pool */
+ uint32 nallocs; /* number of JS_ARENA_ALLOCATE() calls */
+ uint32 nmallocs; /* number of malloc() calls */
+ uint32 ndeallocs; /* number of lifetime deallocations */
+ uint32 ngrows; /* number of JS_ARENA_GROW() calls */
+ uint32 ninplace; /* number of in-place growths */
+ uint32 nreallocs; /* number of arena grow extending reallocs */
+ uint32 nreleases; /* number of JS_ARENA_RELEASE() calls */
+ uint32 nfastrels; /* number of "fast path" releases */
+ size_t nbytes; /* total bytes allocated */
+ size_t maxalloc; /* maximum allocation size in bytes */
+ double variance; /* size variance accumulator */
+};
+#endif
+
+struct JSArenaPool {
+ JSArena first; /* first arena in pool list */
+ JSArena *current; /* arena from which to allocate space */
+ size_t arenasize; /* net exact size of a new arena */
+ jsuword mask; /* alignment mask (power-of-2 - 1) */
+ size_t *quotap; /* pointer to the quota on pool allocation
+ size or null if pool is unlimited */
+#ifdef JS_ARENAMETER
+ JSArenaStats stats;
+#endif
+};
+
+#ifdef JS_ARENAMETER
+#define JS_INIT_NAMED_ARENA_POOL(pool, name, size, align, quotap) \
+ JS_InitArenaPool(pool, name, size, align, quotap)
+#else
+#define JS_INIT_NAMED_ARENA_POOL(pool, name, size, align, quotap) \
+ JS_InitArenaPool(pool, size, align, quotap)
+#endif
+
+/*
+ * If the including .c file uses only one power-of-2 alignment, it may define
+ * JS_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
+ * per ALLOCATE and GROW.
+ */
+#ifdef JS_ARENA_CONST_ALIGN_MASK
+#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + JS_ARENA_CONST_ALIGN_MASK) \
+ & ~(jsuword)JS_ARENA_CONST_ALIGN_MASK)
+
+#define JS_INIT_ARENA_POOL(pool, name, size, quotap) \
+ JS_INIT_NAMED_ARENA_POOL(pool, name, size, JS_ARENA_CONST_ALIGN_MASK + 1, \
+ quotap)
+
+#else
+#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
+
+#define JS_INIT_ARENA_POOL(pool, name, size, align, quotap) \
+ JS_INIT_NAMED_ARENA_POOL(pool, name, size, align, quotap)
+
+#endif
+
+#define JS_ARENA_ALLOCATE(p, pool, nb) \
+ JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb)
+
+#define JS_ARENA_ALLOCATE_TYPE(p, type, pool) \
+ JS_ARENA_ALLOCATE_COMMON(p, type *, pool, sizeof(type), 0)
+
+#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \
+ JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, _nb > _a->limit)
+
+/*
+ * NB: In JS_ARENA_ALLOCATE_CAST and JS_ARENA_GROW_CAST, always subtract _nb
+ * from a->limit rather than adding _nb to _p, to avoid overflowing a 32-bit
+ * address space (possible when running a 32-bit program on a 64-bit system
+ * where the kernel maps the heap up against the top of the 32-bit address
+ * space).
+ *
+ * Thanks to Juergen Kreileder <jk@blackdown.de>, who brought this up in
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=279273.
+ */
+#define JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, guard) \
+ JS_BEGIN_MACRO \
+ JSArena *_a = (pool)->current; \
+ size_t _nb = JS_ARENA_ALIGN(pool, nb); \
+ jsuword _p = _a->avail; \
+ if ((guard) || _p > _a->limit - _nb) \
+ _p = (jsuword)JS_ArenaAllocate(pool, _nb); \
+ else \
+ _a->avail = _p + _nb; \
+ p = (type) _p; \
+ JS_ArenaCountAllocation(pool, nb); \
+ JS_END_MACRO
+
+#define JS_ARENA_GROW(p, pool, size, incr) \
+ JS_ARENA_GROW_CAST(p, void *, pool, size, incr)
+
+#define JS_ARENA_GROW_CAST(p, type, pool, size, incr) \
+ JS_BEGIN_MACRO \
+ JSArena *_a = (pool)->current; \
+ if (_a->avail == (jsuword)(p) + JS_ARENA_ALIGN(pool, size)) { \
+ size_t _nb = (size) + (incr); \
+ _nb = JS_ARENA_ALIGN(pool, _nb); \
+ if (_a->limit >= _nb && (jsuword)(p) <= _a->limit - _nb) { \
+ _a->avail = (jsuword)(p) + _nb; \
+ JS_ArenaCountInplaceGrowth(pool, size, incr); \
+ } else if ((jsuword)(p) == _a->base) { \
+ p = (type) JS_ArenaRealloc(pool, p, size, incr); \
+ } else { \
+ p = (type) JS_ArenaGrow(pool, p, size, incr); \
+ } \
+ } else { \
+ p = (type) JS_ArenaGrow(pool, p, size, incr); \
+ } \
+ JS_ArenaCountGrowth(pool, size, incr); \
+ JS_END_MACRO
+
+#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q))
+
+/*
+ * Check if the mark is inside arena's allocated area.
+ */
+#define JS_ARENA_MARK_MATCH(a, mark) \
+ (JS_UPTRDIFF(mark, (a)->base) <= JS_UPTRDIFF((a)->avail, (a)->base))
+
+#ifdef DEBUG
+#define JS_FREE_PATTERN 0xDA
+#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \
+ memset((void*)(a)->avail, JS_FREE_PATTERN, \
+ (a)->limit - (a)->avail))
+#define JS_CLEAR_ARENA(a) memset((void*)(a), JS_FREE_PATTERN, \
+ (a)->limit - (jsuword)(a))
+#else
+#define JS_CLEAR_UNUSED(a) /* nothing */
+#define JS_CLEAR_ARENA(a) /* nothing */
+#endif
+
+#define JS_ARENA_RELEASE(pool, mark) \
+ JS_BEGIN_MACRO \
+ char *_m = (char *)(mark); \
+ JSArena *_a = (pool)->current; \
+ if (_a != &(pool)->first && JS_ARENA_MARK_MATCH(_a, _m)) { \
+ _a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \
+ JS_ASSERT(_a->avail <= _a->limit); \
+ JS_CLEAR_UNUSED(_a); \
+ JS_ArenaCountRetract(pool, _m); \
+ } else { \
+ JS_ArenaRelease(pool, _m); \
+ } \
+ JS_ArenaCountRelease(pool, _m); \
+ JS_END_MACRO
+
+#ifdef JS_ARENAMETER
+#define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
+#else
+#define JS_COUNT_ARENA(pool,op)
+#endif
+
+#define JS_ARENA_DESTROY(pool, a, pnext) \
+ JS_BEGIN_MACRO \
+ JS_COUNT_ARENA(pool,--); \
+ if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
+ *(pnext) = (a)->next; \
+ JS_CLEAR_ARENA(a); \
+ free(a); \
+ (a) = NULL; \
+ JS_END_MACRO
+
+/*
+ * Initialize an arena pool with a minimum size per arena of size bytes.
+ * Always call JS_SET_ARENA_METER_NAME before calling this or use
+ * JS_INIT_ARENA_POOL macro to provide a name for for debugging and metering.
+ */
+extern JS_PUBLIC_API(void)
+JS_INIT_NAMED_ARENA_POOL(JSArenaPool *pool, const char *name, size_t size,
+ size_t align, size_t *quotap);
+
+/*
+ * Free the arenas in pool. The user may continue to allocate from pool
+ * after calling this function. There is no need to call JS_InitArenaPool()
+ * again unless JS_FinishArenaPool(pool) has been called.
+ */
+extern JS_PUBLIC_API(void)
+JS_FreeArenaPool(JSArenaPool *pool);
+
+/*
+ * Free the arenas in pool and finish using it altogether.
+ */
+extern JS_PUBLIC_API(void)
+JS_FinishArenaPool(JSArenaPool *pool);
+
+/*
+ * Deprecated do-nothing function.
+ */
+extern JS_PUBLIC_API(void)
+JS_ArenaFinish(void);
+
+/*
+ * Deprecated do-nothing function.
+ */
+extern JS_PUBLIC_API(void)
+JS_ArenaShutDown(void);
+
+/*
+ * Friend functions used by the JS_ARENA_*() macros.
+ */
+extern JS_PUBLIC_API(void *)
+JS_ArenaAllocate(JSArenaPool *pool, size_t nb);
+
+extern JS_PUBLIC_API(void *)
+JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void *)
+JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaRelease(JSArenaPool *pool, char *mark);
+
+#ifdef JS_ARENAMETER
+
+#include <stdio.h>
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountRelease(JSArenaPool *pool, char *mark);
+
+extern JS_PUBLIC_API(void)
+JS_ArenaCountRetract(JSArenaPool *pool, char *mark);
+
+extern JS_PUBLIC_API(void)
+JS_DumpArenaStats(FILE *fp);
+
+#else /* !JS_ARENAMETER */
+
+#define JS_ArenaCountAllocation(ap, nb) /* nothing */
+#define JS_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */
+#define JS_ArenaCountGrowth(ap, size, incr) /* nothing */
+#define JS_ArenaCountRelease(ap, mark) /* nothing */
+#define JS_ArenaCountRetract(ap, mark) /* nothing */
+
+#endif /* !JS_ARENAMETER */
+
+JS_END_EXTERN_C
+
+#endif /* jsarena_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp
new file mode 100644
index 0000000..d6a2d83
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.cpp
@@ -0,0 +1,3426 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS array class.
+ *
+ * Array objects begin as "dense" arrays, optimized for numeric-only property
+ * access over a vector of slots (obj->dslots) with high load factor. Array
+ * methods optimize for denseness by testing that the object's class is
+ * &js_ArrayClass, and can then directly manipulate the slots for efficiency.
+ *
+ * We track these pieces of metadata for arrays in dense mode:
+ * - the array's length property as a uint32, in JSSLOT_ARRAY_LENGTH,
+ * - the number of indices that are filled (non-holes), in JSSLOT_ARRAY_COUNT,
+ * - the net number of slots starting at dslots (DENSELEN), in dslots[-1] if
+ * dslots is non-NULL.
+ *
+ * In dense mode, holes in the array are represented by JSVAL_HOLE. The final
+ * slot in fslots (JSSLOT_ARRAY_LOOKUP_HOLDER) is used to store the single jsid
+ * "in use" by a lookupProperty caller.
+ *
+ * Arrays are converted to use js_SlowArrayClass when any of these conditions
+ * are met:
+ * - the load factor (COUNT / DENSELEN) is less than 0.25, and there are
+ * more than MIN_SPARSE_INDEX slots total
+ * - a property is set that is non-numeric (and not "length"); or
+ * - a hole is filled below DENSELEN (possibly implicitly through methods like
+ * |reverse| or |splice|).
+ *
+ * In the latter two cases, property creation order is no longer index order,
+ * which necessitates use of a structure that keeps track of property creation
+ * order. (ES4, due to expectations baked into web script, requires that
+ * enumeration order be the order in which properties were created.)
+ *
+ * An alternative in the latter case (out-of-order index set) would be to
+ * maintain the scope to track property enumeration order, but still use
+ * the fast slot access. That would have the same memory cost as just using
+ * a js_SlowArrayClass, but have the same performance characteristics as
+ * a dense array for slot accesses, at some cost in code complexity.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbit.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h" /* for js_TraceWatchPoints */
+#include "jsdtoa.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsscope.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+
+/* 2^32 - 1 as a number and a string */
+#define MAXINDEX 4294967295u
+#define MAXSTR "4294967295"
+
+/* Small arrays are dense, no matter what. */
+#define MIN_SPARSE_INDEX 32
+
+#define INDEX_TOO_BIG(index) ((index) > JS_BIT(29) - 1)
+#define INDEX_TOO_SPARSE(array, index) \
+ (INDEX_TOO_BIG(index) || \
+ ((index) > ARRAY_DENSE_LENGTH(array) && (index) >= MIN_SPARSE_INDEX && \
+ (index) > (uint32)((array)->fslots[JSSLOT_ARRAY_COUNT] + 1) * 4))
+
+JS_STATIC_ASSERT(sizeof(JSScopeProperty) > 4 * sizeof(jsval));
+
+#define ENSURE_SLOW_ARRAY(cx, obj) \
+ (OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass || js_MakeArraySlow(cx, obj))
+
+/*
+ * Determine if the id represents an array index or an XML property index.
+ *
+ * An id is an array index according to ECMA by (15.4):
+ *
+ * "Array objects give special treatment to a certain class of property names.
+ * A property name P (in the form of a string value) is an array index if and
+ * only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
+ * to 2^32-1."
+ *
+ * In our implementation, it would be sufficient to check for JSVAL_IS_INT(id)
+ * except that by using signed 32-bit integers we miss the top half of the
+ * valid range. This function checks the string representation itself; note
+ * that calling a standard conversion routine might allow strings such as
+ * "08" or "4.0" as array indices, which they are not.
+ */
+JSBool
+js_IdIsIndex(jsval id, jsuint *indexp)
+{
+ JSString *str;
+ jschar *cp;
+
+ if (JSVAL_IS_INT(id)) {
+ jsint i;
+ i = JSVAL_TO_INT(id);
+ if (i < 0)
+ return JS_FALSE;
+ *indexp = (jsuint)i;
+ return JS_TRUE;
+ }
+
+ /* NB: id should be a string, but jsxml.c may call us with an object id. */
+ if (!JSVAL_IS_STRING(id))
+ return JS_FALSE;
+
+ str = JSVAL_TO_STRING(id);
+ cp = JSSTRING_CHARS(str);
+ if (JS7_ISDEC(*cp) && JSSTRING_LENGTH(str) < sizeof(MAXSTR)) {
+ jsuint index = JS7_UNDEC(*cp++);
+ jsuint oldIndex = 0;
+ jsuint c = 0;
+ if (index != 0) {
+ while (JS7_ISDEC(*cp)) {
+ oldIndex = index;
+ c = JS7_UNDEC(*cp);
+ index = 10*index + c;
+ cp++;
+ }
+ }
+
+ /* Ensure that all characters were consumed and we didn't overflow. */
+ if (*cp == 0 &&
+ (oldIndex < (MAXINDEX / 10) ||
+ (oldIndex == (MAXINDEX / 10) && c < (MAXINDEX % 10))))
+ {
+ *indexp = index;
+ return JS_TRUE;
+ }
+ }
+ return JS_FALSE;
+}
+
+static jsuint
+ValueIsLength(JSContext *cx, jsval* vp)
+{
+ jsint i;
+ jsdouble d;
+ jsuint length;
+
+ if (JSVAL_IS_INT(*vp)) {
+ i = JSVAL_TO_INT(*vp);
+ if (i < 0)
+ goto error;
+ return (jsuint) i;
+ }
+
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ goto error;
+
+ if (JSDOUBLE_IS_NaN(d))
+ goto error;
+ length = (jsuint) d;
+ if (d != (jsdouble) length)
+ goto error;
+ return length;
+
+ error:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_ARRAY_LENGTH);
+ *vp = JSVAL_NULL;
+ return 0;
+}
+
+JSBool
+js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ JSTempValueRooter tvr;
+ jsid id;
+ JSBool ok;
+ jsint i;
+
+ if (OBJ_IS_ARRAY(cx, obj)) {
+ *lengthp = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ return JS_TRUE;
+ }
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
+ if (ok) {
+ if (JSVAL_IS_INT(tvr.u.value)) {
+ i = JSVAL_TO_INT(tvr.u.value);
+ *lengthp = (jsuint)i; /* jsuint cast does ToUint32 */
+ } else {
+ *lengthp = js_ValueToECMAUint32(cx, &tvr.u.value);
+ ok = !JSVAL_IS_NULL(tvr.u.value);
+ }
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+IndexToValue(JSContext *cx, jsuint index, jsval *vp)
+{
+ if (index <= JSVAL_INT_MAX) {
+ *vp = INT_TO_JSVAL(index);
+ return JS_TRUE;
+ }
+ return JS_NewDoubleValue(cx, (jsdouble)index, vp);
+}
+
+JSBool JS_FASTCALL
+js_IndexToId(JSContext *cx, jsuint index, jsid *idp)
+{
+ JSString *str;
+
+ if (index <= JSVAL_INT_MAX) {
+ *idp = INT_TO_JSID(index);
+ return JS_TRUE;
+ }
+ str = js_NumberToString(cx, index);
+ if (!str)
+ return JS_FALSE;
+ return js_ValueToStringId(cx, STRING_TO_JSVAL(str), idp);
+}
+
+static JSBool
+BigIndexToId(JSContext *cx, JSObject *obj, jsuint index, JSBool createAtom,
+ jsid *idp)
+{
+ jschar buf[10], *start;
+ JSClass *clasp;
+ JSAtom *atom;
+ JS_STATIC_ASSERT((jsuint)-1 == 4294967295U);
+
+ JS_ASSERT(index > JSVAL_INT_MAX);
+
+ start = JS_ARRAY_END(buf);
+ do {
+ --start;
+ *start = (jschar)('0' + index % 10);
+ index /= 10;
+ } while (index != 0);
+
+ /*
+ * Skip the atomization if the class is known to store atoms corresponding
+ * to big indexes together with elements. In such case we know that the
+ * array does not have an element at the given index if its atom does not
+ * exist. Fast arrays (clasp == &js_ArrayClass) don't use atoms for
+ * any indexes, though it would be rare to see them have a big index
+ * in any case.
+ */
+ if (!createAtom &&
+ ((clasp = OBJ_GET_CLASS(cx, obj)) == &js_SlowArrayClass ||
+ clasp == &js_ArgumentsClass ||
+ clasp == &js_ObjectClass)) {
+ atom = js_GetExistingStringAtom(cx, start, JS_ARRAY_END(buf) - start);
+ if (!atom) {
+ *idp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ } else {
+ atom = js_AtomizeChars(cx, start, JS_ARRAY_END(buf) - start, 0);
+ if (!atom)
+ return JS_FALSE;
+ }
+
+ *idp = ATOM_TO_JSID(atom);
+ return JS_TRUE;
+}
+
+static JSBool
+ResizeSlots(JSContext *cx, JSObject *obj, uint32 oldlen, uint32 len)
+{
+ jsval *slots, *newslots;
+
+ if (len == 0) {
+ if (obj->dslots) {
+ JS_free(cx, obj->dslots - 1);
+ obj->dslots = NULL;
+ }
+ return JS_TRUE;
+ }
+
+ if (len > ~(uint32)0 / sizeof(jsval)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ slots = obj->dslots ? obj->dslots - 1 : NULL;
+ newslots = (jsval *) JS_realloc(cx, slots, sizeof (jsval) * (len + 1));
+ if (!newslots)
+ return JS_FALSE;
+
+ obj->dslots = newslots + 1;
+ ARRAY_SET_DENSE_LENGTH(obj, len);
+
+ for (slots = obj->dslots + oldlen; slots < obj->dslots + len; slots++)
+ *slots = JSVAL_HOLE;
+
+ return JS_TRUE;
+}
+
+static JSBool
+EnsureLength(JSContext *cx, JSObject *obj, uint32 len)
+{
+ uint32 oldlen = ARRAY_DENSE_LENGTH(obj);
+
+ if (len > oldlen) {
+ return ResizeSlots(cx, obj, oldlen,
+ len + ARRAY_GROWBY - (len % ARRAY_GROWBY));
+ }
+ return JS_TRUE;
+}
+
+/*
+ * If the property at the given index exists, get its value into location
+ * pointed by vp and set *hole to false. Otherwise set *hole to true and *vp
+ * to JSVAL_VOID. This function assumes that the location pointed by vp is
+ * properly rooted and can be used as GC-protected storage for temporaries.
+ */
+static JSBool
+GetArrayElement(JSContext *cx, JSObject *obj, jsuint index, JSBool *hole,
+ jsval *vp)
+{
+ jsid id;
+ JSObject *obj2;
+ JSProperty *prop;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && index < ARRAY_DENSE_LENGTH(obj) &&
+ (*vp = obj->dslots[index]) != JSVAL_HOLE) {
+ *hole = JS_FALSE;
+ return JS_TRUE;
+ }
+
+ if (index <= JSVAL_INT_MAX) {
+ id = INT_TO_JSID(index);
+ } else {
+ if (!BigIndexToId(cx, obj, index, JS_FALSE, &id))
+ return JS_FALSE;
+ if (JSVAL_IS_VOID(id)) {
+ *hole = JS_TRUE;
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ }
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ *hole = JS_TRUE;
+ *vp = JSVAL_VOID;
+ } else {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, vp))
+ return JS_FALSE;
+ *hole = JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Set the value of the property at the given index to v assuming v is rooted.
+ */
+static JSBool
+SetArrayElement(JSContext *cx, JSObject *obj, jsuint index, jsval v)
+{
+ jsid id;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ /* Predicted/prefeched code should favor the remains-dense case. */
+ if (!INDEX_TOO_SPARSE(obj, index)) {
+ if (!EnsureLength(cx, obj, index + 1))
+ return JS_FALSE;
+ if (index >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
+ if (obj->dslots[index] == JSVAL_HOLE)
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ obj->dslots[index] = v;
+ return JS_TRUE;
+ }
+
+ if (!js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ }
+
+ if (index <= JSVAL_INT_MAX) {
+ id = INT_TO_JSID(index);
+ } else {
+ if (!BigIndexToId(cx, obj, index, JS_TRUE, &id))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_VOID(id));
+ }
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+static JSBool
+DeleteArrayElement(JSContext *cx, JSObject *obj, jsuint index)
+{
+ jsid id;
+ jsval junk;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ if (index < ARRAY_DENSE_LENGTH(obj)) {
+ if (obj->dslots[index] != JSVAL_HOLE)
+ obj->fslots[JSSLOT_ARRAY_COUNT]--;
+ obj->dslots[index] = JSVAL_HOLE;
+ }
+ return JS_TRUE;
+ }
+
+ if (index <= JSVAL_INT_MAX) {
+ id = INT_TO_JSID(index);
+ } else {
+ if (!BigIndexToId(cx, obj, index, JS_FALSE, &id))
+ return JS_FALSE;
+ if (JSVAL_IS_VOID(id))
+ return JS_TRUE;
+ }
+ return OBJ_DELETE_PROPERTY(cx, obj, id, &junk);
+}
+
+/*
+ * When hole is true, delete the property at the given index. Otherwise set
+ * its value to v assuming v is rooted.
+ */
+static JSBool
+SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, jsuint index,
+ JSBool hole, jsval v)
+{
+ if (hole) {
+ JS_ASSERT(JSVAL_IS_VOID(v));
+ return DeleteArrayElement(cx, obj, index);
+ }
+ return SetArrayElement(cx, obj, index, v);
+}
+
+JSBool
+js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length)
+{
+ jsval v;
+ jsid id;
+
+ if (!IndexToValue(cx, length, &v))
+ return JS_FALSE;
+ id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+JSBool
+js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
+{
+ JSErrorReporter older;
+ JSTempValueRooter tvr;
+ jsid id;
+ JSBool ok;
+
+ older = JS_SetErrorReporter(cx, NULL);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
+ JS_SetErrorReporter(cx, older);
+ if (ok) {
+ *lengthp = ValueIsLength(cx, &tvr.u.value);
+ ok = !JSVAL_IS_NULL(tvr.u.value);
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+JSBool
+js_IsArrayLike(JSContext *cx, JSObject *obj, JSBool *answerp, jsuint *lengthp)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ *answerp = (clasp == &js_ArgumentsClass || clasp == &js_ArrayClass ||
+ clasp == &js_SlowArrayClass);
+ if (!*answerp) {
+ *lengthp = 0;
+ return JS_TRUE;
+ }
+ return js_GetLengthProperty(cx, obj, lengthp);
+}
+
+/*
+ * The 'length' property of all native Array instances is a shared permanent
+ * property of Array.prototype, so it appears to be a direct property of each
+ * array instance delegating to that Array.prototype. It accesses the private
+ * slot reserved by js_ArrayClass.
+ *
+ * Since SpiderMonkey supports cross-class prototype-based delegation, we have
+ * to be careful about the length getter and setter being called on an object
+ * not of Array class. For the getter, we search obj's prototype chain for the
+ * array that caused this getter to be invoked. In the setter case to overcome
+ * the JSPROP_SHARED attribute, we must define a shadowing length property.
+ */
+static JSBool
+array_length_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ do {
+ if (OBJ_IS_ARRAY(cx, obj))
+ return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
+ } while ((obj = OBJ_GET_PROTO(cx, obj)) != NULL);
+ return JS_TRUE;
+}
+
+static JSBool
+array_length_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsuint newlen, oldlen, gap, index;
+ jsval junk;
+ JSObject *iter;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ if (!OBJ_IS_ARRAY(cx, obj)) {
+ jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
+
+ return OBJ_DEFINE_PROPERTY(cx, obj, lengthId, *vp, NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ }
+
+ newlen = ValueIsLength(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return JS_FALSE;
+ oldlen = obj->fslots[JSSLOT_ARRAY_LENGTH];
+
+ if (oldlen == newlen)
+ return JS_TRUE;
+
+ if (!IndexToValue(cx, newlen, vp))
+ return JS_FALSE;
+
+ if (oldlen < newlen) {
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
+ return JS_TRUE;
+ }
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ if (ARRAY_DENSE_LENGTH(obj) && !ResizeSlots(cx, obj, oldlen, newlen))
+ return JS_FALSE;
+ } else if (oldlen - newlen < (1 << 24)) {
+ do {
+ --oldlen;
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !DeleteArrayElement(cx, obj, oldlen)) {
+ return JS_FALSE;
+ }
+ } while (oldlen != newlen);
+ } else {
+ /*
+ * We are going to remove a lot of indexes in a presumably sparse
+ * array. So instead of looping through indexes between newlen and
+ * oldlen, we iterate through all properties and remove those that
+ * correspond to indexes in the half-open range [newlen, oldlen). See
+ * bug 322135.
+ */
+ iter = JS_NewPropertyIterator(cx, obj);
+ if (!iter)
+ return JS_FALSE;
+
+ /* Protect iter against GC in OBJ_DELETE_PROPERTY. */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, iter, &tvr);
+ gap = oldlen - newlen;
+ for (;;) {
+ ok = (JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ JS_NextProperty(cx, iter, &id));
+ if (!ok)
+ break;
+ if (JSVAL_IS_VOID(id))
+ break;
+ if (js_IdIsIndex(id, &index) && index - newlen < gap) {
+ ok = OBJ_DELETE_PROPERTY(cx, obj, id, &junk);
+ if (!ok)
+ break;
+ }
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = newlen;
+ return JS_TRUE;
+}
+
+static JSBool
+array_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ uint32 i;
+ union { JSProperty *p; jsval *v; } u;
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_LookupProperty(cx, obj, id, objp, propp);
+
+ /*
+ * We have only indexed properties up to DENSELEN (excepting holes), plus
+ * the length property. For all else, we delegate to the prototype.
+ */
+ if (id != ATOM_TO_JSID(cx->runtime->atomState.lengthAtom) &&
+ (!js_IdIsIndex(id, &i) ||
+ obj->fslots[JSSLOT_ARRAY_LENGTH] == 0 ||
+ i >= ARRAY_DENSE_LENGTH(obj) ||
+ obj->dslots[i] == JSVAL_HOLE))
+ {
+ JSObject *proto = STOBJ_GET_PROTO(obj);
+
+ if (!proto) {
+ *objp = NULL;
+ *propp = NULL;
+ return JS_TRUE;
+ }
+
+ return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
+ }
+
+ /* FIXME 417501: threadsafety: could race with a lookup on another thread.
+ * If we can only have a single lookup active per context, we could
+ * pigeonhole this on the context instead. */
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER]));
+ obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER] = (jsval) id;
+ u.v = &(obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER]);
+ *propp = u.p;
+ *objp = obj;
+ return JS_TRUE;
+}
+
+static void
+array_dropProperty(JSContext *cx, JSObject *obj, JSProperty *prop)
+{
+ JS_ASSERT_IF(OBJ_IS_DENSE_ARRAY(cx, obj),
+ !JSVAL_IS_VOID(obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER]));
+#ifdef DEBUG
+ obj->fslots[JSSLOT_ARRAY_LOOKUP_HOLDER] = JSVAL_VOID;
+#endif
+}
+
+static JSBool
+array_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ uint32 i;
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
+ return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], vp);
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.protoAtom)) {
+ *vp = STOBJ_GET_SLOT(obj, JSSLOT_PROTO);
+ return JS_TRUE;
+ }
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_GetProperty(cx, obj, id, vp);
+
+ if (!js_IdIsIndex(ID_TO_VALUE(id), &i) || i >= ARRAY_DENSE_LENGTH(obj) ||
+ obj->dslots[i] == JSVAL_HOLE) {
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ JSObject *proto = STOBJ_GET_PROTO(obj);
+ if (!proto) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ *vp = JSVAL_VOID;
+ if (js_LookupPropertyWithFlags(cx, proto, id, cx->resolveFlags,
+ &obj2, &prop) < 0)
+ return JS_FALSE;
+
+ if (prop) {
+ if (OBJ_IS_NATIVE(obj2)) {
+ sprop = (JSScopeProperty *) prop;
+ if (!js_NativeGet(cx, obj, obj2, sprop, vp))
+ return JS_FALSE;
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+ return JS_TRUE;
+ }
+
+ *vp = obj->dslots[i];
+ return JS_TRUE;
+}
+
+static JSBool
+slowarray_addProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsuint index, length;
+
+ if (!js_IdIsIndex(id, &index))
+ return JS_TRUE;
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (index >= length)
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = index + 1;
+ return JS_TRUE;
+}
+
+static void
+slowarray_trace(JSTracer *trc, JSObject *obj)
+{
+ uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_SlowArrayClass);
+
+ /*
+ * Move JSSLOT_ARRAY_LENGTH aside to prevent the GC from treating
+ * untagged integer values as objects or strings.
+ */
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = JSVAL_VOID;
+ js_TraceObject(trc, obj);
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
+}
+
+static JSObjectOps js_SlowArrayObjectOps;
+
+static JSObjectOps *
+slowarray_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_SlowArrayObjectOps;
+}
+
+static JSBool
+array_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ uint32 i;
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
+ return array_length_setter(cx, obj, id, vp);
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_SetProperty(cx, obj, id, vp);
+
+ if (!js_IdIsIndex(id, &i) || INDEX_TOO_SPARSE(obj, i)) {
+ if (!js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ return js_SetProperty(cx, obj, id, vp);
+ }
+
+ if (!EnsureLength(cx, obj, i + 1))
+ return JS_FALSE;
+
+ if (i >= (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
+ if (obj->dslots[i] == JSVAL_HOLE)
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ obj->dslots[i] = *vp;
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+JSBool FASTCALL
+js_Array_dense_setelem(JSContext* cx, JSObject* obj, jsint i, jsval v)
+{
+ JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
+
+ do {
+ jsuint length = ARRAY_DENSE_LENGTH(obj);
+ if ((jsuint)i < length) {
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ if (cx->runtime->anyArrayProtoHasElement)
+ break;
+ if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ }
+ obj->dslots[i] = v;
+ return JS_TRUE;
+ }
+ } while (0);
+ return OBJ_SET_PROPERTY(cx, obj, INT_TO_JSID(i), &v);
+}
+#endif
+
+static JSBool
+array_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp)
+{
+ uint32 i;
+ JSBool isIndex;
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))
+ return JS_TRUE;
+
+ isIndex = js_IdIsIndex(ID_TO_VALUE(id), &i);
+ if (!isIndex || attrs != JSPROP_ENUMERATE) {
+ if (!ENSURE_SLOW_ARRAY(cx, obj))
+ return JS_FALSE;
+ if (isIndex && STOBJ_IS_DELEGATE(obj))
+ cx->runtime->anyArrayProtoHasElement = JS_TRUE;
+ return js_DefineProperty(cx, obj, id, value, getter, setter, attrs, propp);
+ }
+
+ return array_setProperty(cx, obj, id, &value);
+}
+
+static JSBool
+array_getAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ *attrsp = id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)
+ ? JSPROP_PERMANENT : JSPROP_ENUMERATE;
+ return JS_TRUE;
+}
+
+static JSBool
+array_setAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_SET_ARRAY_ATTRS);
+ return JS_FALSE;
+}
+
+static JSBool
+array_deleteProperty(JSContext *cx, JSObject *obj, jsval id, jsval *rval)
+{
+ uint32 i;
+
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ return js_DeleteProperty(cx, obj, id, rval);
+
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
+ *rval = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ if (js_IdIsIndex(id, &i) && i < ARRAY_DENSE_LENGTH(obj) &&
+ obj->dslots[i] != JSVAL_HOLE) {
+ obj->fslots[JSSLOT_ARRAY_COUNT]--;
+ obj->dslots[i] = JSVAL_HOLE;
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+}
+
+/*
+ * JSObjectOps.enumerate implementation.
+ *
+ * For a fast array, JSENUMERATE_INIT captures in the enumeration state both
+ * the length of the array and the bitmap indicating the positions of holes in
+ * the array. This ensures that adding or deleting array elements does not
+ * affect the sequence of indexes JSENUMERATE_NEXT returns.
+ *
+ * For a common case of an array without holes, to represent the state we pack
+ * the (nextEnumerationIndex, arrayLength) pair as a pseudo-boolean jsval.
+ * This is possible when length <= PACKED_UINT_PAIR_BITS. For arrays with
+ * greater length or holes we allocate the JSIndexIterState structure and
+ * store it as an int-tagged private pointer jsval. For a slow array we
+ * delegate the enumeration implementation to js_Enumerate in
+ * slowarray_enumerate.
+ *
+ * Array mutations can turn a fast array into a slow one after the enumeration
+ * starts. When this happens, slowarray_enumerate receives a state created
+ * when the array was fast. To distinguish such fast state from a slow state,
+ * which is an int-tagged pointer that js_Enumerate creates, we set not one
+ * but two lowest bits when tagging a JSIndexIterState pointer -- see
+ * INDEX_ITER_TAG usage below. Thus, when slowarray_enumerate receives a state
+ * tagged with JSVAL_BOOLEAN or with two lowest bits set, it knows that this
+ * is a fast state so it calls array_enumerate to continue enumerating the
+ * indexes present in the original fast array.
+ */
+
+#define PACKED_UINT_PAIR_BITS 14
+#define PACKED_UINT_PAIR_MASK JS_BITMASK(PACKED_UINT_PAIR_BITS)
+
+#define UINT_PAIR_TO_BOOLEAN_JSVAL(i,j) \
+ (JS_ASSERT((uint32) (i) <= PACKED_UINT_PAIR_MASK), \
+ JS_ASSERT((uint32) (j) <= PACKED_UINT_PAIR_MASK), \
+ ((jsval) (i) << (PACKED_UINT_PAIR_BITS + JSVAL_TAGBITS)) | \
+ ((jsval) (j) << (JSVAL_TAGBITS)) | \
+ (jsval) JSVAL_BOOLEAN)
+
+#define BOOLEAN_JSVAL_TO_UINT_PAIR(v,i,j) \
+ (JS_ASSERT(JSVAL_TAG(v) == JSVAL_BOOLEAN), \
+ (i) = (uint32) ((v) >> (PACKED_UINT_PAIR_BITS + JSVAL_TAGBITS)), \
+ (j) = (uint32) ((v) >> JSVAL_TAGBITS) & PACKED_UINT_PAIR_MASK, \
+ JS_ASSERT((i) <= PACKED_UINT_PAIR_MASK))
+
+JS_STATIC_ASSERT(PACKED_UINT_PAIR_BITS * 2 + JSVAL_TAGBITS <= JS_BITS_PER_WORD);
+
+typedef struct JSIndexIterState {
+ uint32 index;
+ uint32 length;
+ JSBool hasHoles;
+
+ /*
+ * Variable-length bitmap representing array's holes. It must not be
+ * accessed when hasHoles is false.
+ */
+ jsbitmap holes[1];
+} JSIndexIterState;
+
+#define INDEX_ITER_TAG 3
+
+JS_STATIC_ASSERT(JSVAL_INT == 1);
+
+static JSBool
+array_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ uint32 length, i;
+ JSIndexIterState *ii;
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
+ length = ARRAY_DENSE_LENGTH(obj);
+ if (idp)
+ *idp = INT_TO_JSVAL(obj->fslots[JSSLOT_ARRAY_COUNT]);
+ ii = NULL;
+ for (i = 0; i != length; ++i) {
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ if (!ii) {
+ ii = (JSIndexIterState *)
+ JS_malloc(cx, offsetof(JSIndexIterState, holes) +
+ JS_BITMAP_SIZE(length));
+ if (!ii)
+ return JS_FALSE;
+ ii->hasHoles = JS_TRUE;
+ memset(ii->holes, 0, JS_BITMAP_SIZE(length));
+ }
+ JS_SET_BIT(ii->holes, i);
+ }
+ }
+ if (!ii) {
+ /* Array has no holes. */
+ if (length <= PACKED_UINT_PAIR_MASK) {
+ *statep = UINT_PAIR_TO_BOOLEAN_JSVAL(0, length);
+ break;
+ }
+ ii = (JSIndexIterState *)
+ JS_malloc(cx, offsetof(JSIndexIterState, holes));
+ if (!ii)
+ return JS_FALSE;
+ ii->hasHoles = JS_FALSE;
+ }
+ ii->index = 0;
+ ii->length = length;
+ *statep = (jsval) ii | INDEX_ITER_TAG;
+ JS_ASSERT(*statep & JSVAL_INT);
+ break;
+
+ case JSENUMERATE_NEXT:
+ if (JSVAL_TAG(*statep) == JSVAL_BOOLEAN) {
+ BOOLEAN_JSVAL_TO_UINT_PAIR(*statep, i, length);
+ if (i != length) {
+ *idp = INT_TO_JSID(i);
+ *statep = UINT_PAIR_TO_BOOLEAN_JSVAL(i + 1, length);
+ break;
+ }
+ } else {
+ JS_ASSERT((*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG);
+ ii = (JSIndexIterState *) (*statep & ~INDEX_ITER_TAG);
+ i = ii->index;
+ if (i != ii->length) {
+ /* Skip holes if any. */
+ if (ii->hasHoles) {
+ while (JS_TEST_BIT(ii->holes, i) && ++i != ii->length)
+ continue;
+ }
+ if (i != ii->length) {
+ ii->index = i + 1;
+ return js_IndexToId(cx, i, idp);
+ }
+ }
+ }
+ /* FALL THROUGH */
+
+ case JSENUMERATE_DESTROY:
+ if (JSVAL_TAG(*statep) != JSVAL_BOOLEAN) {
+ JS_ASSERT((*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG);
+ ii = (JSIndexIterState *) (*statep & ~INDEX_ITER_TAG);
+ JS_free(cx, ii);
+ }
+ *statep = JSVAL_NULL;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+slowarray_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSBool ok;
+
+ /* Are we continuing an enumeration that started when we were dense? */
+ if (enum_op != JSENUMERATE_INIT) {
+ if (JSVAL_TAG(*statep) == JSVAL_BOOLEAN ||
+ (*statep & INDEX_ITER_TAG) == INDEX_ITER_TAG) {
+ return array_enumerate(cx, obj, enum_op, statep, idp);
+ }
+ JS_ASSERT((*statep & INDEX_ITER_TAG) == JSVAL_INT);
+ }
+ ok = js_Enumerate(cx, obj, enum_op, statep, idp);
+ JS_ASSERT(*statep == JSVAL_NULL || (*statep & INDEX_ITER_TAG) == JSVAL_INT);
+ return ok;
+}
+
+static void
+array_finalize(JSContext *cx, JSObject *obj)
+{
+ if (obj->dslots)
+ JS_free(cx, obj->dslots - 1);
+ obj->dslots = NULL;
+}
+
+static void
+array_trace(JSTracer *trc, JSObject *obj)
+{
+ uint32 length;
+ size_t i;
+ jsval v;
+
+ JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj));
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ for (i = 0; i < length; i++) {
+ v = obj->dslots[i];
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_INDEX(trc, "array_dslots", i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+
+ for (i = JSSLOT_PROTO; i <= JSSLOT_PARENT; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+}
+
+static JSObjectMap *
+array_newObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj)
+{
+#ifdef DEBUG
+ extern JSClass js_ArrayClass;
+ extern JSObjectOps js_ArrayObjectOps;
+#endif
+ JSObjectMap *map = (JSObjectMap *) JS_malloc(cx, sizeof(*map));
+ if (!map)
+ return NULL;
+
+ map->nrefs = nrefs;
+ JS_ASSERT(ops == &js_ArrayObjectOps);
+ map->ops = ops;
+ JS_ASSERT(clasp == &js_ArrayClass);
+ map->freeslot = JSSLOT_FREE(clasp);
+
+ return map;
+}
+
+void
+array_destroyObjectMap(JSContext *cx, JSObjectMap *map)
+{
+ JS_free(cx, map);
+}
+
+JSObjectOps js_ArrayObjectOps = {
+ array_newObjectMap, array_destroyObjectMap,
+ array_lookupProperty, array_defineProperty,
+ array_getProperty, array_setProperty,
+ array_getAttributes, array_setAttributes,
+ array_deleteProperty, js_DefaultValue,
+ array_enumerate, js_CheckAccess,
+ NULL, array_dropProperty,
+ NULL, NULL,
+ NULL, js_HasInstance,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ array_trace, NULL,
+ NULL, NULL
+};
+
+static JSObjectOps *
+array_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_ArrayObjectOps;
+}
+
+JSClass js_ArrayClass = {
+ "Array",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array) |
+ JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_NEW_ENUMERATE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, array_finalize,
+ array_getObjectOps, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+JSClass js_SlowArrayClass = {
+ "Array",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Array),
+ slowarray_addProperty, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, js_TryValueOf, JS_FinalizeStub,
+ slowarray_getObjectOps, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+/*
+ * Convert an array object from fast-and-dense to slow-and-flexible.
+ */
+JSBool
+js_MakeArraySlow(JSContext *cx, JSObject *obj)
+{
+ JSObjectMap *map, *oldmap;
+ uint32 i, length;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
+
+ /* Create a native scope. */
+ map = js_NewObjectMap(cx, obj->map->nrefs, &js_SlowArrayObjectOps,
+ &js_SlowArrayClass, obj);
+ if (!map)
+ return JS_FALSE;
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ if (length) {
+ map->freeslot = STOBJ_NSLOTS(obj) + JS_INITIAL_NSLOTS;
+ obj->dslots[-1] = JS_INITIAL_NSLOTS + length;
+ } else {
+ map->freeslot = STOBJ_NSLOTS(obj);
+ }
+
+ /* Create new properties pointing to existing values in dslots */
+ for (i = 0; i < length; i++) {
+ jsid id;
+ JSScopeProperty *sprop;
+
+ if (!JS_ValueToId(cx, INT_TO_JSVAL(i), &id))
+ goto out_bad;
+
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ obj->dslots[i] = JSVAL_VOID;
+ continue;
+ }
+
+ sprop = js_AddScopeProperty(cx, (JSScope *)map, id, NULL, NULL,
+ i + JS_INITIAL_NSLOTS, JSPROP_ENUMERATE,
+ 0, 0);
+ if (!sprop)
+ goto out_bad;
+ }
+
+ /*
+ * Render our formerly-reserved count property GC-safe. If length fits in
+ * a jsval, set our slow/sparse COUNT to the current length as a jsval, so
+ * we can tell when only named properties have been added to a dense array
+ * to make it slow-but-not-sparse.
+ */
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ obj->fslots[JSSLOT_ARRAY_COUNT] = INT_FITS_IN_JSVAL(length)
+ ? INT_TO_JSVAL(length)
+ : JSVAL_VOID;
+
+ /* Make sure we preserve any flags borrowing bits in classword. */
+ obj->classword ^= (jsuword) &js_ArrayClass;
+ obj->classword |= (jsuword) &js_SlowArrayClass;
+
+ /* Swap in our new map. */
+ oldmap = obj->map;
+ obj->map = map;
+ array_destroyObjectMap(cx, oldmap);
+
+ return JS_TRUE;
+
+out_bad:
+ js_DestroyObjectMap(cx, map);
+ return JS_FALSE;
+}
+
+enum ArrayToStringOp {
+ TO_STRING,
+ TO_LOCALE_STRING,
+ TO_SOURCE
+};
+
+/*
+ * When op is TO_STRING or TO_LOCALE_STRING sep indicates a separator to use
+ * or "," when sep is NULL.
+ * When op is TO_SOURCE sep must be NULL.
+ */
+static JSBool
+array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op,
+ JSString *sep, jsval *rval)
+{
+ JSBool ok, hole;
+ jsuint length, index;
+ jschar *chars, *ochars;
+ size_t nchars, growth, seplen, tmplen, extratail;
+ const jschar *sepstr;
+ JSString *str;
+ JSHashEntry *he;
+ JSAtom *atom;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ ok = js_GetLengthProperty(cx, obj, &length);
+ if (!ok)
+ return JS_FALSE;
+
+ he = js_EnterSharpObject(cx, obj, NULL, &chars);
+ if (!he)
+ return JS_FALSE;
+#ifdef DEBUG
+ growth = (size_t) -1;
+#endif
+
+ if (op == TO_SOURCE) {
+ if (IS_SHARP(he)) {
+#if JS_HAS_SHARP_VARS
+ nchars = js_strlen(chars);
+#else
+ chars[0] = '[';
+ chars[1] = ']';
+ chars[2] = 0;
+ nchars = 2;
+#endif
+ goto make_string;
+ }
+
+ /*
+ * Always allocate 2 extra chars for closing ']' and terminating 0
+ * and then preallocate 1 + extratail to include starting '['.
+ */
+ extratail = 2;
+ growth = (1 + extratail) * sizeof(jschar);
+ if (!chars) {
+ nchars = 0;
+ chars = (jschar *) malloc(growth);
+ if (!chars)
+ goto done;
+ } else {
+ MAKE_SHARP(he);
+ nchars = js_strlen(chars);
+ growth += nchars * sizeof(jschar);
+ chars = (jschar *)realloc((ochars = chars), growth);
+ if (!chars) {
+ free(ochars);
+ goto done;
+ }
+ }
+ chars[nchars++] = '[';
+ JS_ASSERT(sep == NULL);
+ sepstr = NULL; /* indicates to use ", " as separator */
+ seplen = 2;
+ } else {
+ /*
+ * Free any sharp variable definition in chars. Normally, we would
+ * MAKE_SHARP(he) so that only the first sharp variable annotation is
+ * a definition, and all the rest are references, but in the current
+ * case of (op != TO_SOURCE), we don't need chars at all.
+ */
+ if (chars)
+ JS_free(cx, chars);
+ chars = NULL;
+ nchars = 0;
+ extratail = 1; /* allocate extra char for terminating 0 */
+
+ /* Return the empty string on a cycle as well as on empty join. */
+ if (IS_BUSY(he) || length == 0) {
+ js_LeaveSharpObject(cx, NULL);
+ *rval = JS_GetEmptyStringValue(cx);
+ return ok;
+ }
+
+ /* Flag he as BUSY so we can distinguish a cycle from a join-point. */
+ MAKE_BUSY(he);
+
+ if (sep) {
+ JSSTRING_CHARS_AND_LENGTH(sep, sepstr, seplen);
+ } else {
+ sepstr = NULL; /* indicates to use "," as separator */
+ seplen = 1;
+ }
+ }
+
+ /* Use rval to locally root each element value as we loop and convert. */
+ for (index = 0; index < length; index++) {
+ ok = (JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, index, &hole, rval));
+ if (!ok)
+ goto done;
+ if (hole ||
+ (op != TO_SOURCE &&
+ (JSVAL_IS_VOID(*rval) || JSVAL_IS_NULL(*rval)))) {
+ str = cx->runtime->emptyString;
+ } else {
+ if (op == TO_LOCALE_STRING) {
+ JSObject *robj;
+
+ atom = cx->runtime->atomState.toLocaleStringAtom;
+ ok = js_ValueToObject(cx, *rval, &robj);
+ if (ok) {
+ /* Re-use *rval to protect robj temporarily. */
+ *rval = OBJECT_TO_JSVAL(robj);
+ ok = js_TryMethod(cx, robj, atom, 0, NULL, rval);
+ }
+ if (!ok)
+ goto done;
+ str = js_ValueToString(cx, *rval);
+ } else if (op == TO_STRING) {
+ str = js_ValueToString(cx, *rval);
+ } else {
+ JS_ASSERT(op == TO_SOURCE);
+ str = js_ValueToSource(cx, *rval);
+ }
+ if (!str) {
+ ok = JS_FALSE;
+ goto done;
+ }
+ }
+
+ /*
+ * Do not append separator after the last element unless it is a hole
+ * and we are in toSource. In that case we append single ",".
+ */
+ if (index + 1 == length)
+ seplen = (hole && op == TO_SOURCE) ? 1 : 0;
+
+ /* Allocate 1 at end for closing bracket and zero. */
+ tmplen = JSSTRING_LENGTH(str);
+ growth = nchars + tmplen + seplen + extratail;
+ if (nchars > growth || tmplen > growth ||
+ growth > (size_t)-1 / sizeof(jschar)) {
+ if (chars) {
+ free(chars);
+ chars = NULL;
+ }
+ goto done;
+ }
+ growth *= sizeof(jschar);
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ if (!chars) {
+ chars = (jschar *) malloc(growth);
+ if (!chars)
+ goto done;
+ } else {
+ chars = (jschar *) realloc((ochars = chars), growth);
+ if (!chars) {
+ free(ochars);
+ goto done;
+ }
+ }
+
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(str), tmplen);
+ nchars += tmplen;
+
+ if (seplen) {
+ if (sepstr) {
+ js_strncpy(&chars[nchars], sepstr, seplen);
+ } else {
+ JS_ASSERT(seplen == 1 || seplen == 2);
+ chars[nchars] = ',';
+ if (seplen == 2)
+ chars[nchars + 1] = ' ';
+ }
+ nchars += seplen;
+ }
+ }
+
+ done:
+ if (op == TO_SOURCE) {
+ if (chars)
+ chars[nchars++] = ']';
+ } else {
+ CLEAR_BUSY(he);
+ }
+ js_LeaveSharpObject(cx, NULL);
+ if (!ok) {
+ if (chars)
+ free(chars);
+ return ok;
+ }
+
+ make_string:
+ if (!chars) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ chars[nchars] = 0;
+ JS_ASSERT(growth == (size_t)-1 || (nchars + 1) * sizeof(jschar) == growth);
+ str = js_NewString(cx, chars, nchars);
+ if (!str) {
+ free(chars);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+array_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_GET_CLASS(cx, obj) != &js_SlowArrayClass &&
+ !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
+ return JS_FALSE;
+ }
+ return array_join_sub(cx, obj, TO_SOURCE, NULL, vp);
+}
+#endif
+
+static JSBool
+array_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_GET_CLASS(cx, obj) != &js_SlowArrayClass &&
+ !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
+ return JS_FALSE;
+ }
+ return array_join_sub(cx, obj, TO_STRING, NULL, vp);
+}
+
+static JSBool
+array_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_GET_CLASS(cx, obj) != &js_SlowArrayClass &&
+ !JS_InstanceOf(cx, obj, &js_ArrayClass, vp + 2)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * Passing comma here as the separator. Need a way to get a
+ * locale-specific version.
+ */
+ return array_join_sub(cx, obj, TO_LOCALE_STRING, NULL, vp);
+}
+
+static JSBool
+InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint end,
+ jsval *vector)
+{
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ if (!EnsureLength(cx, obj, end))
+ return JS_FALSE;
+
+ if (end > (uint32)obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = end;
+
+ memcpy(obj->dslots + start, vector, sizeof(jsval) * (end - start));
+ return JS_TRUE;
+ }
+
+ while (start != end) {
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !SetArrayElement(cx, obj, start++, *vector++)) {
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector,
+ JSBool holey = JS_FALSE)
+{
+ JS_ASSERT(OBJ_IS_ARRAY(cx, obj));
+
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = length;
+
+ if (vector) {
+ if (!EnsureLength(cx, obj, length))
+ return JS_FALSE;
+
+ jsuint count = length;
+ if (!holey) {
+ memcpy(obj->dslots, vector, length * sizeof (jsval));
+ } else {
+ for (jsuint i = 0; i < length; i++) {
+ if (vector[i] == JSVAL_HOLE)
+ --count;
+ obj->dslots[i] = vector[i];
+ }
+ }
+ obj->fslots[JSSLOT_ARRAY_COUNT] = count;
+ } else {
+ obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
+ }
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+Array_p_join(JSContext* cx, JSObject* obj, JSString *str)
+{
+ jsval v;
+ if (!array_join_sub(cx, obj, TO_STRING, str, &v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+static JSString* FASTCALL
+Array_p_toString(JSContext* cx, JSObject* obj)
+{
+ jsval v;
+ if (!array_join_sub(cx, obj, TO_STRING, NULL, &v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+#endif
+
+/*
+ * Perl-inspired join, reverse, and sort.
+ */
+static JSBool
+array_join(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ JSObject *obj;
+
+ if (argc == 0 || JSVAL_IS_VOID(vp[2])) {
+ str = NULL;
+ } else {
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+ }
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && array_join_sub(cx, obj, TO_STRING, str, vp);
+}
+
+static JSBool
+array_reverse(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSTempValueRooter tvr;
+ jsuint len, half, i;
+ JSBool ok, hole, hole2;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &len))
+ return JS_FALSE;
+
+ ok = JS_TRUE;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ half = len / 2;
+ for (i = 0; i < half; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, i, &hole, &tvr.u.value) &&
+ GetArrayElement(cx, obj, len - i - 1, &hole2, vp) &&
+ SetOrDeleteArrayElement(cx, obj, len - i - 1, hole, tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, i, hole2, *vp);
+ if (!ok)
+ break;
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ *vp = OBJECT_TO_JSVAL(obj);
+ return ok;
+}
+
+typedef struct MSortArgs {
+ size_t elsize;
+ JSComparator cmp;
+ void *arg;
+ JSBool fastcopy;
+} MSortArgs;
+
+/* Helper function for js_MergeSort. */
+static JSBool
+MergeArrays(MSortArgs *msa, void *src, void *dest, size_t run1, size_t run2)
+{
+ void *arg, *a, *b, *c;
+ size_t elsize, runtotal;
+ int cmp_result;
+ JSComparator cmp;
+ JSBool fastcopy;
+
+ runtotal = run1 + run2;
+
+ elsize = msa->elsize;
+ cmp = msa->cmp;
+ arg = msa->arg;
+ fastcopy = msa->fastcopy;
+
+#define CALL_CMP(a, b) \
+ if (!cmp(arg, (a), (b), &cmp_result)) return JS_FALSE;
+
+ /* Copy runs already in sorted order. */
+ b = (char *)src + run1 * elsize;
+ a = (char *)b - elsize;
+ CALL_CMP(a, b);
+ if (cmp_result <= 0) {
+ memcpy(dest, src, runtotal * elsize);
+ return JS_TRUE;
+ }
+
+#define COPY_ONE(p,q,n) \
+ (fastcopy ? (void)(*(jsval*)(p) = *(jsval*)(q)) : (void)memcpy(p, q, n))
+
+ a = src;
+ c = dest;
+ for (; runtotal != 0; runtotal--) {
+ JSBool from_a = run2 == 0;
+ if (!from_a && run1 != 0) {
+ CALL_CMP(a,b);
+ from_a = cmp_result <= 0;
+ }
+
+ if (from_a) {
+ COPY_ONE(c, a, elsize);
+ run1--;
+ a = (char *)a + elsize;
+ } else {
+ COPY_ONE(c, b, elsize);
+ run2--;
+ b = (char *)b + elsize;
+ }
+ c = (char *)c + elsize;
+ }
+#undef COPY_ONE
+#undef CALL_CMP
+
+ return JS_TRUE;
+}
+
+/*
+ * This sort is stable, i.e. sequence of equal elements is preserved.
+ * See also bug #224128.
+ */
+JSBool
+js_MergeSort(void *src, size_t nel, size_t elsize,
+ JSComparator cmp, void *arg, void *tmp)
+{
+ void *swap, *vec1, *vec2;
+ MSortArgs msa;
+ size_t i, j, lo, hi, run;
+ JSBool fastcopy;
+ int cmp_result;
+
+ /* Avoid memcpy overhead for word-sized and word-aligned elements. */
+ fastcopy = (elsize == sizeof(jsval) &&
+ (((jsuword) src | (jsuword) tmp) & JSVAL_ALIGN) == 0);
+#define COPY_ONE(p,q,n) \
+ (fastcopy ? (void)(*(jsval*)(p) = *(jsval*)(q)) : (void)memcpy(p, q, n))
+#define CALL_CMP(a, b) \
+ if (!cmp(arg, (a), (b), &cmp_result)) return JS_FALSE;
+#define INS_SORT_INT 4
+
+ /*
+ * Apply insertion sort to small chunks to reduce the number of merge
+ * passes needed.
+ */
+ for (lo = 0; lo < nel; lo += INS_SORT_INT) {
+ hi = lo + INS_SORT_INT;
+ if (hi >= nel)
+ hi = nel;
+ for (i = lo + 1; i < hi; i++) {
+ vec1 = (char *)src + i * elsize;
+ vec2 = (char *)vec1 - elsize;
+ for (j = i; j > lo; j--) {
+ CALL_CMP(vec2, vec1);
+ /* "<=" instead of "<" insures the sort is stable */
+ if (cmp_result <= 0) {
+ break;
+ }
+
+ /* Swap elements, using "tmp" as tmp storage */
+ COPY_ONE(tmp, vec2, elsize);
+ COPY_ONE(vec2, vec1, elsize);
+ COPY_ONE(vec1, tmp, elsize);
+ vec1 = vec2;
+ vec2 = (char *)vec1 - elsize;
+ }
+ }
+ }
+#undef CALL_CMP
+#undef COPY_ONE
+
+ msa.elsize = elsize;
+ msa.cmp = cmp;
+ msa.arg = arg;
+ msa.fastcopy = fastcopy;
+
+ vec1 = src;
+ vec2 = tmp;
+ for (run = INS_SORT_INT; run < nel; run *= 2) {
+ for (lo = 0; lo < nel; lo += 2 * run) {
+ hi = lo + run;
+ if (hi >= nel) {
+ memcpy((char *)vec2 + lo * elsize, (char *)vec1 + lo * elsize,
+ (nel - lo) * elsize);
+ break;
+ }
+ if (!MergeArrays(&msa, (char *)vec1 + lo * elsize,
+ (char *)vec2 + lo * elsize, run,
+ hi + run > nel ? nel - hi : run)) {
+ return JS_FALSE;
+ }
+ }
+ swap = vec1;
+ vec1 = vec2;
+ vec2 = swap;
+ }
+ if (src != vec1)
+ memcpy(src, tmp, nel * elsize);
+
+ return JS_TRUE;
+}
+
+typedef struct CompareArgs {
+ JSContext *context;
+ jsval fval;
+ jsval *elemroot; /* stack needed for js_Invoke */
+} CompareArgs;
+
+static JSBool
+sort_compare(void *arg, const void *a, const void *b, int *result)
+{
+ jsval av = *(const jsval *)a, bv = *(const jsval *)b;
+ CompareArgs *ca = (CompareArgs *) arg;
+ JSContext *cx = ca->context;
+ jsval *invokevp, *sp;
+ jsdouble cmp;
+
+ /**
+ * array_sort deals with holes and undefs on its own and they should not
+ * come here.
+ */
+ JS_ASSERT(!JSVAL_IS_VOID(av));
+ JS_ASSERT(!JSVAL_IS_VOID(bv));
+
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP))
+ return JS_FALSE;
+
+ invokevp = ca->elemroot;
+ sp = invokevp;
+ *sp++ = ca->fval;
+ *sp++ = JSVAL_NULL;
+ *sp++ = av;
+ *sp++ = bv;
+
+ if (!js_Invoke(cx, 2, invokevp, 0))
+ return JS_FALSE;
+
+ cmp = js_ValueToNumber(cx, invokevp);
+ if (JSVAL_IS_NULL(*invokevp))
+ return JS_FALSE;
+
+ /* Clamp cmp to -1, 0, 1. */
+ *result = 0;
+ if (!JSDOUBLE_IS_NaN(cmp) && cmp != 0)
+ *result = cmp > 0 ? 1 : -1;
+
+ /*
+ * XXX else report some kind of error here? ECMA talks about 'consistent
+ * compare functions' that don't return NaN, but is silent about what the
+ * result should be. So we currently ignore it.
+ */
+
+ return JS_TRUE;
+}
+
+static int
+sort_compare_strings(void *arg, const void *a, const void *b, int *result)
+{
+ jsval av = *(const jsval *)a, bv = *(const jsval *)b;
+
+ JS_ASSERT(JSVAL_IS_STRING(av));
+ JS_ASSERT(JSVAL_IS_STRING(bv));
+ if (!JS_CHECK_OPERATION_LIMIT((JSContext *)arg, JSOW_JUMP))
+ return JS_FALSE;
+
+ *result = (int) js_CompareStrings(JSVAL_TO_STRING(av), JSVAL_TO_STRING(bv));
+ return JS_TRUE;
+}
+
+/*
+ * The array_sort function below assumes JSVAL_NULL is zero in order to
+ * perform initialization using memset. Other parts of SpiderMonkey likewise
+ * "know" that JSVAL_NULL is zero; this static assertion covers all cases.
+ */
+JS_STATIC_ASSERT(JSVAL_NULL == 0);
+
+static JSBool
+array_sort(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv, fval, *vec, *mergesort_tmp, v;
+ JSObject *obj;
+ CompareArgs ca;
+ jsuint len, newlen, i, undefs;
+ JSTempValueRooter tvr;
+ JSBool hole;
+ bool ok;
+ size_t elemsize;
+ JSString *str;
+
+ /*
+ * Optimize the default compare function case if all of obj's elements
+ * have values of type string.
+ */
+ JSBool all_strings;
+
+ argv = JS_ARGV(cx, vp);
+ if (argc > 0) {
+ if (JSVAL_IS_PRIMITIVE(argv[0])) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SORT_ARG);
+ return JS_FALSE;
+ }
+ fval = argv[0]; /* non-default compare function */
+ } else {
+ fval = JSVAL_NULL;
+ }
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &len))
+ return JS_FALSE;
+ if (len == 0) {
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+
+ /*
+ * We need a temporary array of 2 * len jsvals to hold the array elements
+ * and the scratch space for merge sort. Check that its size does not
+ * overflow size_t, which would allow for indexing beyond the end of the
+ * malloc'd vector.
+ */
+#if JS_BITS_PER_WORD == 32
+ if ((size_t)len > ~(size_t)0 / (2 * sizeof(jsval))) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+#endif
+ vec = (jsval *) JS_malloc(cx, 2 * (size_t) len * sizeof(jsval));
+ if (!vec)
+ return JS_FALSE;
+
+ /*
+ * Initialize vec as a root. We will clear elements of vec one by
+ * one while increasing tvr.count when we know that the property at
+ * the corresponding index exists and its value must be rooted.
+ *
+ * In this way when sorting a huge mostly sparse array we will not
+ * access the tail of vec corresponding to properties that do not
+ * exist, allowing OS to avoiding committing RAM. See bug 330812.
+ *
+ * After this point control must flow through label out: to exit.
+ */
+ JS_PUSH_TEMP_ROOT(cx, 0, vec, &tvr);
+
+ /*
+ * By ECMA 262, 15.4.4.11, a property that does not exist (which we
+ * call a "hole") is always greater than an existing property with
+ * value undefined and that is always greater than any other property.
+ * Thus to sort holes and undefs we simply count them, sort the rest
+ * of elements, append undefs after them and then make holes after
+ * undefs.
+ */
+ undefs = 0;
+ newlen = 0;
+ all_strings = JS_TRUE;
+ for (i = 0; i < len; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP);
+ if (!ok)
+ goto out;
+
+ /* Clear vec[newlen] before including it in the rooted set. */
+ vec[newlen] = JSVAL_NULL;
+ tvr.count = newlen + 1;
+ ok = GetArrayElement(cx, obj, i, &hole, &vec[newlen]);
+ if (!ok)
+ goto out;
+
+ if (hole)
+ continue;
+
+ if (JSVAL_IS_VOID(vec[newlen])) {
+ ++undefs;
+ continue;
+ }
+
+ /* We know JSVAL_IS_STRING yields 0 or 1, so avoid a branch via &=. */
+ all_strings &= JSVAL_IS_STRING(vec[newlen]);
+
+ ++newlen;
+ }
+
+ if (newlen == 0) {
+ /* The array has only holes and undefs. */
+ ok = JS_TRUE;
+ goto out;
+ }
+
+ /*
+ * The first newlen elements of vec are copied from the array object
+ * (above). The remaining newlen positions are used as GC-rooted scratch
+ * space for mergesort. We must clear the space before including it to
+ * the root set covered by tvr.count. We assume JSVAL_NULL==0 to optimize
+ * initialization using memset.
+ */
+ mergesort_tmp = vec + newlen;
+ memset(mergesort_tmp, 0, newlen * sizeof(jsval));
+ tvr.count = newlen * 2;
+
+ /* Here len == 2 * (newlen + undefs + number_of_holes). */
+ if (fval == JSVAL_NULL) {
+ /*
+ * Sort using the default comparator converting all elements to
+ * strings.
+ */
+ if (all_strings) {
+ elemsize = sizeof(jsval);
+ } else {
+ /*
+ * To avoid string conversion on each compare we do it only once
+ * prior to sorting. But we also need the space for the original
+ * values to recover the sorting result. To reuse
+ * sort_compare_strings we move the original values to the odd
+ * indexes in vec, put the string conversion results in the even
+ * indexes and pass 2 * sizeof(jsval) as an element size to the
+ * sorting function. In this way sort_compare_strings will only
+ * see the string values when it casts the compare arguments as
+ * pointers to jsval.
+ *
+ * This requires doubling the temporary storage including the
+ * scratch space for the merge sort. Since vec already contains
+ * the rooted scratch space for newlen elements at the tail, we
+ * can use it to rearrange and convert to strings first and try
+ * realloc only when we know that we successfully converted all
+ * the elements.
+ */
+#if JS_BITS_PER_WORD == 32
+ if ((size_t)newlen > ~(size_t)0 / (4 * sizeof(jsval))) {
+ js_ReportAllocationOverflow(cx);
+ ok = JS_FALSE;
+ goto out;
+ }
+#endif
+
+ /*
+ * Rearrange and string-convert the elements of the vector from
+ * the tail here and, after sorting, move the results back
+ * starting from the start to prevent overwrite the existing
+ * elements.
+ */
+ i = newlen;
+ do {
+ --i;
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP);
+ if (!ok)
+ goto out;
+ v = vec[i];
+ str = js_ValueToString(cx, v);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ vec[2 * i] = STRING_TO_JSVAL(str);
+ vec[2 * i + 1] = v;
+ } while (i != 0);
+
+ JS_ASSERT(tvr.u.array == vec);
+ vec = (jsval *) JS_realloc(cx, vec,
+ 4 * (size_t) newlen * sizeof(jsval));
+ if (!vec) {
+ vec = tvr.u.array;
+ ok = JS_FALSE;
+ goto out;
+ }
+ tvr.u.array = vec;
+ mergesort_tmp = vec + 2 * newlen;
+ memset(mergesort_tmp, 0, newlen * 2 * sizeof(jsval));
+ tvr.count = newlen * 4;
+ elemsize = 2 * sizeof(jsval);
+ }
+ ok = js_MergeSort(vec, (size_t) newlen, elemsize,
+ sort_compare_strings, cx, mergesort_tmp);
+ if (!ok)
+ goto out;
+ if (!all_strings) {
+ /*
+ * We want to make the following loop fast and to unroot the
+ * cached results of toString invocations before the operation
+ * callback has a chance to run the GC. For this reason we do
+ * not call JS_CHECK_OPERATION_LIMIT in the loop.
+ */
+ i = 0;
+ do {
+ vec[i] = vec[2 * i + 1];
+ } while (++i != newlen);
+ }
+ } else {
+ void *mark;
+
+ ca.context = cx;
+ ca.fval = fval;
+ ca.elemroot = js_AllocStack(cx, 2 + 2, &mark);
+ if (!ca.elemroot) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ ok = js_MergeSort(vec, (size_t) newlen, sizeof(jsval),
+ sort_compare, &ca, mergesort_tmp);
+ js_FreeStack(cx, mark);
+ if (!ok)
+ goto out;
+ }
+
+ /*
+ * We no longer need to root the scratch space for the merge sort, so
+ * unroot it now to make the job of a potential GC under InitArrayElements
+ * easier.
+ */
+ tvr.count = newlen;
+ ok = InitArrayElements(cx, obj, 0, newlen, vec);
+ if (!ok)
+ goto out;
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ JS_free(cx, vec);
+ if (!ok)
+ return JS_FALSE;
+
+ /* Set undefs that sorted after the rest of elements. */
+ while (undefs != 0) {
+ --undefs;
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !SetArrayElement(cx, obj, newlen++, JSVAL_VOID)) {
+ return JS_FALSE;
+ }
+ }
+
+ /* Re-create any holes that sorted to the end of the array. */
+ while (len > newlen) {
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !DeleteArrayElement(cx, obj, --len)) {
+ return JS_FALSE;
+ }
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/*
+ * Perl-inspired push, pop, shift, unshift, and splice methods.
+ */
+static JSBool
+array_push_slowly(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsuint length, newlength;
+
+ if (!js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ newlength = length + argc;
+ if (!InitArrayElements(cx, obj, length, newlength, argv))
+ return JS_FALSE;
+
+ /* Per ECMA-262, return the new array length. */
+ if (!IndexToValue(cx, newlength, rval))
+ return JS_FALSE;
+ return js_SetLengthProperty(cx, obj, newlength);
+}
+
+static JSBool
+array_push1_dense(JSContext* cx, JSObject* obj, jsval v, jsval *rval)
+{
+ uint32 length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (INDEX_TOO_SPARSE(obj, length)) {
+ if (!js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ return array_push_slowly(cx, obj, 1, &v, rval);
+ }
+
+ if (!EnsureLength(cx, obj, length + 1))
+ return JS_FALSE;
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = length + 1;
+
+ JS_ASSERT(obj->dslots[length] == JSVAL_HOLE);
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ obj->dslots[length] = v;
+ return IndexToValue(cx, obj->fslots[JSSLOT_ARRAY_LENGTH], rval);
+}
+
+#ifdef JS_TRACER
+static jsval FASTCALL
+Array_p_push1(JSContext* cx, JSObject* obj, jsval v)
+{
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)
+ ? array_push1_dense(cx, obj, v, &v)
+ : array_push_slowly(cx, obj, 1, &v, &v)) {
+ return v;
+ }
+ return JSVAL_ERROR_COOKIE;
+}
+#endif
+
+static JSBool
+array_push(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ /* Insist on one argument and obj of the expected class. */
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ if (argc != 1 || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return array_push_slowly(cx, obj, argc, vp + 2, vp);
+
+ return array_push1_dense(cx, obj, vp[2], vp);
+}
+
+static JSBool
+array_pop_slowly(JSContext *cx, JSObject* obj, jsval *vp)
+{
+ jsuint index;
+ JSBool hole;
+
+ if (!js_GetLengthProperty(cx, obj, &index))
+ return JS_FALSE;
+ if (index == 0) {
+ *vp = JSVAL_VOID;
+ } else {
+ index--;
+
+ /* Get the to-be-deleted property's value into vp. */
+ if (!GetArrayElement(cx, obj, index, &hole, vp))
+ return JS_FALSE;
+ if (!hole && !DeleteArrayElement(cx, obj, index))
+ return JS_FALSE;
+ }
+ return js_SetLengthProperty(cx, obj, index);
+}
+
+static JSBool
+array_pop_dense(JSContext *cx, JSObject* obj, jsval *vp)
+{
+ jsuint index;
+ JSBool hole;
+
+ index = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (index == 0) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ index--;
+ if (!GetArrayElement(cx, obj, index, &hole, vp))
+ return JS_FALSE;
+ if (!hole && !DeleteArrayElement(cx, obj, index))
+ return JS_FALSE;
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = index;
+ return JS_TRUE;
+
+}
+
+#ifdef JS_TRACER
+static jsval FASTCALL
+Array_p_pop(JSContext* cx, JSObject* obj)
+{
+ jsval v;
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)
+ ? array_pop_dense(cx, obj, &v)
+ : array_pop_slowly(cx, obj, &v)) {
+ return v;
+ }
+ return JSVAL_ERROR_COOKIE;
+}
+#endif
+
+static JSBool
+array_pop(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ if (OBJ_IS_DENSE_ARRAY(cx, obj))
+ return array_pop_dense(cx, obj, vp);
+ return array_pop_slowly(cx, obj, vp);
+}
+
+static JSBool
+array_shift(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsuint length, i;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ if (length == 0) {
+ *vp = JSVAL_VOID;
+ } else {
+ length--;
+
+ /* Get the to-be-deleted property's value into vp ASAP. */
+ if (!GetArrayElement(cx, obj, 0, &hole, vp))
+ return JS_FALSE;
+
+ /* Slide down the array above the first element. */
+ ok = JS_TRUE;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ for (i = 0; i != length; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, i + 1, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, i, hole, tvr.u.value);
+ if (!ok)
+ break;
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+
+ /* Delete the only or last element when it exist. */
+ if (!hole && !DeleteArrayElement(cx, obj, length))
+ return JS_FALSE;
+ }
+ return js_SetLengthProperty(cx, obj, length);
+}
+
+static JSBool
+array_unshift(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv;
+ jsuint length, last;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ if (argc > 0) {
+ /* Slide up the array to make room for argc at the bottom. */
+ argv = JS_ARGV(cx, vp);
+ if (length > 0) {
+ last = length;
+ ok = JS_TRUE;
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ do {
+ --last;
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, last + argc, hole,
+ tvr.u.value);
+ if (!ok)
+ break;
+ } while (last != 0);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+ }
+
+ /* Copy from argv to the bottom of the array. */
+ if (!InitArrayElements(cx, obj, 0, argc, argv))
+ return JS_FALSE;
+
+ length += argc;
+ if (!js_SetLengthProperty(cx, obj, length))
+ return JS_FALSE;
+ }
+
+ /* Follow Perl by returning the new array length. */
+ return IndexToValue(cx, length, vp);
+}
+
+static JSBool
+array_splice(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ JSObject *obj;
+ jsuint length, begin, end, count, delta, last;
+ jsdouble d;
+ JSBool hole, ok;
+ JSObject *obj2;
+ JSTempValueRooter tvr;
+
+ /*
+ * Create a new array value to return. Our ECMA v2 proposal specs
+ * that splice always returns an array value, even when given no
+ * arguments. We think this is best because it eliminates the need
+ * for callers to do an extra test to handle the empty splice case.
+ */
+ obj2 = js_NewArrayObject(cx, 0, NULL);
+ if (!obj2)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(obj2);
+
+ /* Nothing to do if no args. Otherwise get length. */
+ if (argc == 0)
+ return JS_TRUE;
+ argv = JS_ARGV(cx, vp);
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+
+ /* Convert the first argument into a starting index. */
+ d = js_ValueToNumber(cx, argv);
+ if (JSVAL_IS_NULL(*argv))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ d = 0;
+ } else if (d > length) {
+ d = length;
+ }
+ begin = (jsuint)d; /* d has been clamped to uint32 */
+ argc--;
+ argv++;
+
+ /* Convert the second argument from a count into a fencepost index. */
+ delta = length - begin;
+ if (argc == 0) {
+ count = delta;
+ end = length;
+ } else {
+ d = js_ValueToNumber(cx, argv);
+ if (JSVAL_IS_NULL(*argv))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0)
+ d = 0;
+ else if (d > delta)
+ d = delta;
+ count = (jsuint)d;
+ end = begin + count;
+ argc--;
+ argv++;
+ }
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ /* If there are elements to remove, put them into the return value. */
+ if (count > 0) {
+ for (last = begin; last < end; last++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value);
+ if (!ok)
+ goto out;
+
+ /* Copy tvr.u.value to new array unless it's a hole. */
+ if (!hole) {
+ ok = SetArrayElement(cx, obj2, last - begin, tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ }
+
+ ok = js_SetLengthProperty(cx, obj2, end - begin);
+ if (!ok)
+ goto out;
+ }
+
+ /* Find the direction (up or down) to copy and make way for argv. */
+ if (argc > count) {
+ delta = (jsuint)argc - count;
+ last = length;
+ /* (uint) end could be 0, so can't use vanilla >= test */
+ while (last-- > end) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, last + delta, hole,
+ tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ length += delta;
+ } else if (argc < count) {
+ delta = count - (jsuint)argc;
+ for (last = end; last < length; last++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, last, &hole, &tvr.u.value) &&
+ SetOrDeleteArrayElement(cx, obj, last - delta, hole,
+ tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ length -= delta;
+ }
+
+ /* Copy from argv into the hole to complete the splice. */
+ ok = InitArrayElements(cx, obj, begin, begin + argc, argv);
+ if (!ok)
+ goto out;
+
+ /* Update length in case we deleted elements from the end. */
+ ok = js_SetLengthProperty(cx, obj, length);
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+/*
+ * Python-esque sequence operations.
+ */
+static JSBool
+array_concat(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv, v;
+ JSObject *aobj, *nobj;
+ jsuint length, alength, slot;
+ uintN i;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ /* Treat our |this| object as the first argument; see ECMA 15.4.4.4. */
+ argv = JS_ARGV(cx, vp) - 1;
+ JS_ASSERT(JS_THIS_OBJECT(cx, vp) == JSVAL_TO_OBJECT(argv[0]));
+
+ /* Create a new Array object and root it using *vp. */
+ aobj = JS_THIS_OBJECT(cx, vp);
+ if (OBJ_IS_DENSE_ARRAY(cx, aobj)) {
+ /*
+ * Clone aobj but pass the minimum of its length and capacity (aka
+ * "dense length"), to handle a = [1,2,3]; a.length = 10000 "dense"
+ * cases efficiently. In such a case we'll pass 8 (not 3) due to the
+ * ARRAY_GROWBY over-allocation policy, which will cause nobj to be
+ * over-allocated to 16. But in the normal case where length is <=
+ * capacity, nobj and aobj will have the same dense length.
+ */
+ length = aobj->fslots[JSSLOT_ARRAY_LENGTH];
+ jsuint capacity = ARRAY_DENSE_LENGTH(aobj);
+ nobj = js_NewArrayObject(cx, JS_MIN(length, capacity), aobj->dslots,
+ aobj->fslots[JSSLOT_ARRAY_COUNT] !=
+ (jsval) length);
+ if (!nobj)
+ return JS_FALSE;
+ nobj->fslots[JSSLOT_ARRAY_LENGTH] = length;
+ *vp = OBJECT_TO_JSVAL(nobj);
+ if (argc == 0)
+ return JS_TRUE;
+ argc--;
+ argv++;
+ } else {
+ nobj = js_NewArrayObject(cx, 0, NULL);
+ if (!nobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(nobj);
+ length = 0;
+ }
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ /* Loop over [0, argc] to concat args into nobj, expanding all Arrays. */
+ for (i = 0; i <= argc; i++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP);
+ if (!ok)
+ goto out;
+ v = argv[i];
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ JSObject *wobj;
+
+ aobj = JSVAL_TO_OBJECT(v);
+ wobj = js_GetWrappedObject(cx, aobj);
+ if (OBJ_IS_ARRAY(cx, wobj)) {
+ ok = OBJ_GET_PROPERTY(cx, aobj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .lengthAtom),
+ &tvr.u.value);
+ if (!ok)
+ goto out;
+ alength = ValueIsLength(cx, &tvr.u.value);
+ ok = !JSVAL_IS_NULL(tvr.u.value);
+ if (!ok)
+ goto out;
+ for (slot = 0; slot < alength; slot++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, aobj, slot, &hole,
+ &tvr.u.value);
+ if (!ok)
+ goto out;
+
+ /*
+ * Per ECMA 262, 15.4.4.4, step 9, ignore non-existent
+ * properties.
+ */
+ if (!hole) {
+ ok = SetArrayElement(cx, nobj, length + slot,
+ tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ }
+ length += alength;
+ continue;
+ }
+ }
+
+ ok = SetArrayElement(cx, nobj, length, v);
+ if (!ok)
+ goto out;
+ length++;
+ }
+
+ ok = js_SetLengthProperty(cx, nobj, length);
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+array_slice(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ JSObject *nobj, *obj;
+ jsuint length, begin, end, slot;
+ jsdouble d;
+ JSBool hole, ok;
+ JSTempValueRooter tvr;
+
+ argv = JS_ARGV(cx, vp);
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ begin = 0;
+ end = length;
+
+ if (argc > 0) {
+ d = js_ValueToNumber(cx, &argv[0]);
+ if (JSVAL_IS_NULL(argv[0]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ d = 0;
+ } else if (d > length) {
+ d = length;
+ }
+ begin = (jsuint)d;
+
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &argv[1]);
+ if (JSVAL_IS_NULL(argv[1]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0) {
+ d += length;
+ if (d < 0)
+ d = 0;
+ } else if (d > length) {
+ d = length;
+ }
+ end = (jsuint)d;
+ }
+ }
+
+ if (begin > end)
+ begin = end;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && end <= ARRAY_DENSE_LENGTH(obj)) {
+ nobj = js_NewArrayObject(cx, end - begin, obj->dslots + begin,
+ obj->fslots[JSSLOT_ARRAY_COUNT] !=
+ obj->fslots[JSSLOT_ARRAY_LENGTH]);
+ if (!nobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(nobj);
+ return JS_TRUE;
+ }
+
+ /* Create a new Array object and root it using *vp. */
+ nobj = js_NewArrayObject(cx, 0, NULL);
+ if (!nobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(nobj);
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ for (slot = begin; slot < end; slot++) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, slot, &hole, &tvr.u.value);
+ if (!ok)
+ goto out;
+ if (!hole) {
+ ok = SetArrayElement(cx, nobj, slot - begin, tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ }
+ ok = js_SetLengthProperty(cx, nobj, end - begin);
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+#if JS_HAS_ARRAY_EXTRAS
+
+static JSBool
+array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsuint length, i, stop;
+ jsval tosearch;
+ jsint direction;
+ JSBool hole;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ if (length == 0)
+ goto not_found;
+
+ if (argc <= 1) {
+ i = isLast ? length - 1 : 0;
+ tosearch = (argc != 0) ? vp[2] : JSVAL_VOID;
+ } else {
+ jsdouble start;
+
+ tosearch = vp[2];
+ start = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ start = js_DoubleToInteger(start);
+ if (start < 0) {
+ start += length;
+ if (start < 0) {
+ if (isLast)
+ goto not_found;
+ i = 0;
+ } else {
+ i = (jsuint)start;
+ }
+ } else if (start >= length) {
+ if (!isLast)
+ goto not_found;
+ i = length - 1;
+ } else {
+ i = (jsuint)start;
+ }
+ }
+
+ if (isLast) {
+ stop = 0;
+ direction = -1;
+ } else {
+ stop = length - 1;
+ direction = 1;
+ }
+
+ for (;;) {
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) ||
+ !GetArrayElement(cx, obj, (jsuint)i, &hole, vp)) {
+ return JS_FALSE;
+ }
+ if (!hole && js_StrictlyEqual(cx, *vp, tosearch))
+ return js_NewNumberInRootedValue(cx, i, vp);
+ if (i == stop)
+ goto not_found;
+ i += direction;
+ }
+
+ not_found:
+ *vp = INT_TO_JSVAL(-1);
+ return JS_TRUE;
+}
+
+static JSBool
+array_indexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_indexOfHelper(cx, JS_FALSE, argc, vp);
+}
+
+static JSBool
+array_lastIndexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_indexOfHelper(cx, JS_TRUE, argc, vp);
+}
+
+/* Order is important; extras that take a predicate funarg must follow MAP. */
+typedef enum ArrayExtraMode {
+ FOREACH,
+ REDUCE,
+ REDUCE_RIGHT,
+ MAP,
+ FILTER,
+ SOME,
+ EVERY
+} ArrayExtraMode;
+
+#define REDUCE_MODE(mode) ((mode) == REDUCE || (mode) == REDUCE_RIGHT)
+
+static JSBool
+array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsuint length, newlen;
+ jsval *argv, *elemroot, *invokevp, *sp;
+ JSBool ok, cond, hole;
+ JSObject *callable, *thisp, *newarr;
+ jsint start, end, step, i;
+ void *mark;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+
+ /*
+ * First, get or compute our callee, so that we error out consistently
+ * when passed a non-callable object.
+ */
+ if (argc == 0) {
+ js_ReportMissingArg(cx, vp, 0);
+ return JS_FALSE;
+ }
+ argv = vp + 2;
+ callable = js_ValueToCallableObject(cx, &argv[0], JSV2F_SEARCH_STACK);
+ if (!callable)
+ return JS_FALSE;
+
+ /*
+ * Set our initial return condition, used for zero-length array cases
+ * (and pre-size our map return to match our known length, for all cases).
+ */
+#ifdef __GNUC__ /* quell GCC overwarning */
+ newlen = 0;
+ newarr = NULL;
+#endif
+ start = 0, end = length, step = 1;
+
+ switch (mode) {
+ case REDUCE_RIGHT:
+ start = length - 1, end = -1, step = -1;
+ /* FALL THROUGH */
+ case REDUCE:
+ if (length == 0 && argc == 1) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_EMPTY_ARRAY_REDUCE);
+ return JS_FALSE;
+ }
+ if (argc >= 2) {
+ *vp = argv[1];
+ } else {
+ do {
+ if (!GetArrayElement(cx, obj, start, &hole, vp))
+ return JS_FALSE;
+ start += step;
+ } while (hole && start != end);
+
+ if (hole && start == end) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_EMPTY_ARRAY_REDUCE);
+ return JS_FALSE;
+ }
+ }
+ break;
+ case MAP:
+ case FILTER:
+ newlen = (mode == MAP) ? length : 0;
+ newarr = js_NewArrayObject(cx, newlen, NULL);
+ if (!newarr)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(newarr);
+ break;
+ case SOME:
+ *vp = JSVAL_FALSE;
+ break;
+ case EVERY:
+ *vp = JSVAL_TRUE;
+ break;
+ case FOREACH:
+ *vp = JSVAL_VOID;
+ break;
+ }
+
+ if (length == 0)
+ return JS_TRUE;
+
+ if (argc > 1 && !REDUCE_MODE(mode)) {
+ if (!js_ValueToObject(cx, argv[1], &thisp))
+ return JS_FALSE;
+ argv[1] = OBJECT_TO_JSVAL(thisp);
+ } else {
+ thisp = NULL;
+ }
+
+ /*
+ * For all but REDUCE, we call with 3 args (value, index, array). REDUCE
+ * requires 4 args (accum, value, index, array).
+ */
+ argc = 3 + REDUCE_MODE(mode);
+ elemroot = js_AllocStack(cx, 1 + 2 + argc, &mark);
+ if (!elemroot)
+ return JS_FALSE;
+
+ MUST_FLOW_THROUGH("out");
+ ok = JS_TRUE;
+ invokevp = elemroot + 1;
+
+ for (i = start; i != end; i += step) {
+ ok = JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) &&
+ GetArrayElement(cx, obj, i, &hole, elemroot);
+ if (!ok)
+ goto out;
+ if (hole)
+ continue;
+
+ /*
+ * Push callable and 'this', then args. We must do this for every
+ * iteration around the loop since js_Invoke uses spbase[0] for return
+ * value storage, while some native functions use spbase[1] for local
+ * rooting.
+ */
+ sp = invokevp;
+ *sp++ = OBJECT_TO_JSVAL(callable);
+ *sp++ = OBJECT_TO_JSVAL(thisp);
+ if (REDUCE_MODE(mode))
+ *sp++ = *vp;
+ *sp++ = *elemroot;
+ *sp++ = INT_TO_JSVAL(i);
+ *sp++ = OBJECT_TO_JSVAL(obj);
+
+ /* Do the call. */
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ if (!ok)
+ break;
+
+ if (mode > MAP)
+ cond = js_ValueToBoolean(*invokevp);
+#ifdef __GNUC__ /* quell GCC overwarning */
+ else
+ cond = JS_FALSE;
+#endif
+
+ switch (mode) {
+ case FOREACH:
+ break;
+ case REDUCE:
+ case REDUCE_RIGHT:
+ *vp = *invokevp;
+ break;
+ case MAP:
+ ok = SetArrayElement(cx, newarr, i, *invokevp);
+ if (!ok)
+ goto out;
+ break;
+ case FILTER:
+ if (!cond)
+ break;
+ /* The filter passed *elemroot, so push it onto our result. */
+ ok = SetArrayElement(cx, newarr, newlen++, *elemroot);
+ if (!ok)
+ goto out;
+ break;
+ case SOME:
+ if (cond) {
+ *vp = JSVAL_TRUE;
+ goto out;
+ }
+ break;
+ case EVERY:
+ if (!cond) {
+ *vp = JSVAL_FALSE;
+ goto out;
+ }
+ break;
+ }
+ }
+
+ out:
+ js_FreeStack(cx, mark);
+ if (ok && mode == FILTER)
+ ok = js_SetLengthProperty(cx, newarr, newlen);
+ return ok;
+}
+
+static JSBool
+array_forEach(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, FOREACH, argc, vp);
+}
+
+static JSBool
+array_map(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, MAP, argc, vp);
+}
+
+static JSBool
+array_reduce(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, REDUCE, argc, vp);
+}
+
+static JSBool
+array_reduceRight(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, REDUCE_RIGHT, argc, vp);
+}
+
+static JSBool
+array_filter(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, FILTER, argc, vp);
+}
+
+static JSBool
+array_some(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, SOME, argc, vp);
+}
+
+static JSBool
+array_every(JSContext *cx, uintN argc, jsval *vp)
+{
+ return array_extra(cx, EVERY, argc, vp);
+}
+#endif
+
+static JSPropertySpec array_props[] = {
+ {js_length_str, -1, JSPROP_SHARED | JSPROP_PERMANENT,
+ array_length_getter, array_length_setter},
+ {0,0,0,0,0}
+};
+
+JS_DEFINE_TRCINFO_1(array_toString,
+ (2, (static, STRING_FAIL, Array_p_toString, CONTEXT, THIS, 0, 0)))
+JS_DEFINE_TRCINFO_1(array_join,
+ (3, (static, STRING_FAIL, Array_p_join, CONTEXT, THIS, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(array_push,
+ (3, (static, JSVAL_FAIL, Array_p_push1, CONTEXT, THIS, JSVAL, 0, 0)))
+JS_DEFINE_TRCINFO_1(array_pop,
+ (2, (static, JSVAL_FAIL, Array_p_pop, CONTEXT, THIS, 0, 0)))
+
+static JSFunctionSpec array_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, array_toSource, 0,0),
+#endif
+ JS_TN(js_toString_str, array_toString, 0,0, array_toString_trcinfo),
+ JS_FN(js_toLocaleString_str,array_toLocaleString,0,0),
+
+ /* Perl-ish methods. */
+ JS_TN("join", array_join, 1,JSFUN_GENERIC_NATIVE, array_join_trcinfo),
+ JS_FN("reverse", array_reverse, 0,JSFUN_GENERIC_NATIVE),
+ JS_FN("sort", array_sort, 1,JSFUN_GENERIC_NATIVE),
+ JS_TN("push", array_push, 1,JSFUN_GENERIC_NATIVE, array_push_trcinfo),
+ JS_TN("pop", array_pop, 0,JSFUN_GENERIC_NATIVE, array_pop_trcinfo),
+ JS_FN("shift", array_shift, 0,JSFUN_GENERIC_NATIVE),
+ JS_FN("unshift", array_unshift, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("splice", array_splice, 2,JSFUN_GENERIC_NATIVE),
+
+ /* Pythonic sequence methods. */
+ JS_FN("concat", array_concat, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("slice", array_slice, 2,JSFUN_GENERIC_NATIVE),
+
+#if JS_HAS_ARRAY_EXTRAS
+ JS_FN("indexOf", array_indexOf, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("lastIndexOf", array_lastIndexOf, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("forEach", array_forEach, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("map", array_map, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("reduce", array_reduce, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("reduceRight", array_reduceRight, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("filter", array_filter, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("some", array_some, 1,JSFUN_GENERIC_NATIVE),
+ JS_FN("every", array_every, 1,JSFUN_GENERIC_NATIVE),
+#endif
+
+ JS_FS_END
+};
+
+JSBool
+js_Array(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsuint length;
+ jsval *vector;
+
+ /* If called without new, replace obj with a new Array object. */
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ if (argc == 0) {
+ length = 0;
+ vector = NULL;
+ } else if (argc > 1) {
+ length = (jsuint) argc;
+ vector = argv;
+ } else if (!JSVAL_IS_NUMBER(argv[0])) {
+ length = 1;
+ vector = argv;
+ } else {
+ length = ValueIsLength(cx, &argv[0]);
+ if (JSVAL_IS_NULL(argv[0]))
+ return JS_FALSE;
+ vector = NULL;
+ }
+ return InitArrayObject(cx, obj, length, vector);
+}
+
+JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_ARRAY_LENGTH);
+JS_STATIC_ASSERT(JSSLOT_ARRAY_LENGTH + 1 == JSSLOT_ARRAY_COUNT);
+
+#ifdef JS_TRACER
+
+JSObject* FASTCALL
+js_FastNewArray(JSContext* cx, JSObject* proto)
+{
+ JS_ASSERT(OBJ_IS_ARRAY(cx, proto));
+
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
+ if (!obj)
+ return NULL;
+
+ JSClass* clasp = &js_ArrayClass;
+ obj->classword = jsuword(clasp);
+
+ obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
+ obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
+
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
+ obj->fslots[JSSLOT_ARRAY_COUNT] = 0;
+ for (unsigned i = JSSLOT_ARRAY_COUNT + 1; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+ JSObjectOps* ops = clasp->getObjectOps(cx, clasp);
+ obj->map = ops->newObjectMap(cx, 1, ops, clasp, obj);
+ if (!obj->map)
+ return NULL;
+ obj->dslots = NULL;
+ return obj;
+}
+
+JSObject* FASTCALL
+js_Array_1int(JSContext* cx, JSObject* proto, int32 i)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = js_FastNewArray(cx, proto);
+ if (obj)
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i;
+ return obj;
+}
+
+#define ARRAY_CTOR_GUTS(exact_len, newslots_code) \
+ JS_ASSERT(JS_ON_TRACE(cx)); \
+ JSObject* obj = js_FastNewArray(cx, proto); \
+ if (obj) { \
+ const uint32 len = ARRAY_GROWBY; \
+ jsval* newslots = (jsval*) JS_malloc(cx, sizeof (jsval) * (len + 1)); \
+ if (newslots) { \
+ obj->dslots = newslots + 1; \
+ ARRAY_SET_DENSE_LENGTH(obj, len); \
+ {newslots_code} \
+ while (++newslots < obj->dslots + len) \
+ *newslots = JSVAL_HOLE; \
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = (exact_len); \
+ return obj; \
+ } \
+ } \
+ return NULL;
+
+JSObject* FASTCALL
+js_Array_1str(JSContext* cx, JSObject* proto, JSString *str)
+{
+ ARRAY_CTOR_GUTS(1, *++newslots = STRING_TO_JSVAL(str);)
+}
+
+JSObject* FASTCALL
+js_Array_2obj(JSContext* cx, JSObject* proto, JSObject *obj1, JSObject* obj2)
+{
+ ARRAY_CTOR_GUTS(2,
+ *++newslots = OBJECT_TO_JSVAL(obj1);
+ *++newslots = OBJECT_TO_JSVAL(obj2);)
+}
+
+JSObject* FASTCALL
+js_Array_3num(JSContext* cx, JSObject* proto, jsdouble n1, jsdouble n2, jsdouble n3)
+{
+ ARRAY_CTOR_GUTS(3,
+ if (!js_NewDoubleInRootedValue(cx, n1, ++newslots))
+ return NULL;
+ if (!js_NewDoubleInRootedValue(cx, n2, ++newslots))
+ return NULL;
+ if (!js_NewDoubleInRootedValue(cx, n3, ++newslots))
+ return NULL;)
+}
+
+#endif /* JS_TRACER */
+
+JSObject *
+js_InitArrayClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ /* Initialize the ops structure used by slow arrays */
+ memcpy(&js_SlowArrayObjectOps, &js_ObjectOps, sizeof(JSObjectOps));
+ js_SlowArrayObjectOps.trace = slowarray_trace;
+ js_SlowArrayObjectOps.enumerate = slowarray_enumerate;
+ js_SlowArrayObjectOps.call = NULL;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_ArrayClass, js_Array, 1,
+ array_props, array_methods, NULL, NULL);
+
+ /* Initialize the Array prototype object so it gets a length property. */
+ if (!proto || !InitArrayObject(cx, proto, 0, NULL))
+ return NULL;
+ return proto;
+}
+
+JSObject *
+js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector, JSBool holey)
+{
+ JSTempValueRooter tvr;
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_ArrayClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+ if (!InitArrayObject(cx, obj, length, vector, holey))
+ obj = NULL;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ /* Set/clear newborn root, in case we lost it. */
+ cx->weakRoots.newborn[GCX_OBJECT] = obj;
+ return obj;
+}
+
+JSObject *
+js_NewSlowArrayObject(JSContext *cx)
+{
+ JSObject *obj = js_NewObject(cx, &js_SlowArrayClass, NULL, NULL, 0);
+ if (obj)
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = 0;
+ return obj;
+}
+
+#ifdef DEBUG_ARRAYS
+JSBool
+js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uintN i;
+ JSObject *array;
+
+ for (i = 0; i < argc; i++) {
+ char *bytes;
+
+ bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, argv[i],
+ NULL);
+ if (!bytes)
+ return JS_FALSE;
+ if (JSVAL_IS_PRIMITIVE(argv[i]) ||
+ !OBJ_IS_ARRAY(cx, (array = JSVAL_TO_OBJECT(argv[i])))) {
+ fprintf(stderr, "%s: not array\n", bytes);
+ JS_free(cx, bytes);
+ continue;
+ }
+ fprintf(stderr, "%s: %s (len %lu", bytes,
+ OBJ_IS_DENSE_ARRAY(cx, array) ? "dense" : "sparse",
+ array->fslots[JSSLOT_ARRAY_LENGTH]);
+ if (OBJ_IS_DENSE_ARRAY(cx, array)) {
+ fprintf(stderr, ", count %lu, denselen %lu",
+ array->fslots[JSSLOT_ARRAY_COUNT],
+ ARRAY_DENSE_LENGTH(array));
+ }
+ fputs(")\n", stderr);
+ JS_free(cx, bytes);
+ }
+ return JS_TRUE;
+}
+#endif
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint8 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsint vi;
+
+ JSUint8 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v) || (vi = JSVAL_TO_INT(v)) < 0)
+ return JS_FALSE;
+
+ *dp++ = (JSUint8) vi;
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint16 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsint vi;
+
+ JSUint16 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v) || (vi = JSVAL_TO_INT(v)) < 0)
+ return JS_FALSE;
+
+ *dp++ = (JSUint16) vi;
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint32 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsint vi;
+
+ JSUint32 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v) || (vi = JSVAL_TO_INT(v)) < 0)
+ return JS_FALSE;
+
+ *dp++ = (JSUint32) vi;
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt8 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ JSInt8 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v))
+ return JS_FALSE;
+
+ *dp++ = (JSInt8) JSVAL_TO_INT(v);
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt16 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ JSInt16 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v))
+ return JS_FALSE;
+
+ *dp++ = (JSInt16) JSVAL_TO_INT(v);
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt32 *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ JSInt32 *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (!JSVAL_IS_INT(v))
+ return JS_FALSE;
+
+ *dp++ = (JSInt32) JSVAL_TO_INT(v);
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSDoubleBuffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ jsdouble *dest)
+{
+ uint32 length;
+
+ if (!obj || !OBJ_IS_DENSE_ARRAY(cx, obj))
+ return JS_FALSE;
+
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length < offset + count)
+ return JS_FALSE;
+
+ jsval v;
+ jsdouble *dp = dest;
+ for (uintN i = offset; i < offset+count; i++) {
+ v = obj->dslots[i];
+ if (JSVAL_IS_INT(v))
+ *dp++ = (jsdouble) JSVAL_TO_INT(v);
+ else if (JSVAL_IS_DOUBLE(v))
+ *dp++ = *(JSVAL_TO_DOUBLE(v));
+ else
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+JS_DEFINE_CALLINFO_4(extern, BOOL, js_Array_dense_setelem, CONTEXT, OBJECT, INT32, JSVAL, 0, 0)
+JS_DEFINE_CALLINFO_2(extern, OBJECT, js_FastNewArray, CONTEXT, OBJECT, 0, 0)
+JS_DEFINE_CALLINFO_3(extern, OBJECT, js_Array_1int, CONTEXT, OBJECT, INT32, 0, 0)
+JS_DEFINE_CALLINFO_3(extern, OBJECT, js_Array_1str, CONTEXT, OBJECT, STRING, 0, 0)
+JS_DEFINE_CALLINFO_4(extern, OBJECT, js_Array_2obj, CONTEXT, OBJECT, OBJECT, OBJECT, 0, 0)
+JS_DEFINE_CALLINFO_5(extern, OBJECT, js_Array_3num, CONTEXT, OBJECT, DOUBLE, DOUBLE, DOUBLE, 0, 0)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsarray.h b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.h
new file mode 100644
index 0000000..ef10316
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsarray.h
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsarray_h___
+#define jsarray_h___
+/*
+ * JS Array interface.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/* Generous sanity-bound on length (in elements) of array initialiser. */
+#define ARRAY_INIT_LIMIT JS_BIT(24)
+
+extern JSBool
+js_IdIsIndex(jsval id, jsuint *indexp);
+
+extern JSClass js_ArrayClass, js_SlowArrayClass;
+
+#define OBJ_IS_DENSE_ARRAY(cx,obj) (OBJ_GET_CLASS(cx, obj) == &js_ArrayClass)
+
+#define OBJ_IS_ARRAY(cx,obj) (OBJ_IS_DENSE_ARRAY(cx, obj) || \
+ OBJ_GET_CLASS(cx, obj) == &js_SlowArrayClass)
+
+extern JSObject *
+js_InitArrayClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector,
+ JSBool holey = JS_FALSE);
+
+/* Create an array object that starts out already made slow/sparse. */
+extern JSObject *
+js_NewSlowArrayObject(JSContext *cx);
+
+extern JSBool
+js_MakeArraySlow(JSContext *cx, JSObject *obj);
+
+#define JSSLOT_ARRAY_LENGTH JSSLOT_PRIVATE
+#define JSSLOT_ARRAY_COUNT (JSSLOT_ARRAY_LENGTH + 1)
+#define JSSLOT_ARRAY_LOOKUP_HOLDER (JSSLOT_ARRAY_COUNT + 1)
+
+#define ARRAY_DENSE_LENGTH(obj) \
+ (JS_ASSERT(OBJ_IS_DENSE_ARRAY(cx, obj)), \
+ (obj)->dslots ? (uint32)(obj)->dslots[-1] : 0)
+
+#define ARRAY_SET_DENSE_LENGTH(obj, max) \
+ (JS_ASSERT((obj)->dslots), (obj)->dslots[-1] = (jsval)(max))
+
+#define ARRAY_GROWBY 8
+
+extern JSBool
+js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JSBool
+js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length);
+
+extern JSBool
+js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
+
+extern JSBool JS_FASTCALL
+js_IndexToId(JSContext *cx, jsuint index, jsid *idp);
+
+/*
+ * Test whether an object is "array-like". Currently this means whether obj
+ * is an Array or an arguments object. We would like an API, and probably a
+ * way in the language, to bless other objects as array-like: having indexed
+ * properties, and a 'length' property of uint32 value equal to one more than
+ * the greatest index.
+ */
+extern JSBool
+js_IsArrayLike(JSContext *cx, JSObject *obj, JSBool *answerp, jsuint *lengthp);
+
+/*
+ * JS-specific merge sort function.
+ */
+typedef JSBool (*JSComparator)(void *arg, const void *a, const void *b,
+ int *result);
+/*
+ * NB: vec is the array to be sorted, tmp is temporary space at least as big
+ * as vec. Both should be GC-rooted if appropriate.
+ *
+ * The sorted result is in vec. vec may be in an inconsistent state if the
+ * comparator function cmp returns an error inside a comparison, so remember
+ * to check the return value of this function.
+ */
+extern JSBool
+js_MergeSort(void *vec, size_t nel, size_t elsize, JSComparator cmp,
+ void *arg, void *tmp);
+
+#ifdef DEBUG_ARRAYS
+extern JSBool
+js_ArrayInfo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+#endif
+
+/*
+ * Fast dense-array-to-buffer conversions.
+ *
+ * If the array is a dense array, fill [offset..offset+count] values
+ * into destination, assuming that types are consistent. Return
+ * JS_TRUE if successful, otherwise JS_FALSE -- note that the
+ * destination buffer may be modified even if JS_FALSE is returned
+ * (e.g. due to finding an inappropriate type later on in the array).
+ * If JS_FALSE is returned, no error conditions or exceptions are set
+ * on the context.
+ *
+ * For ArrayToJSUint8, ArrayToJSUint16, and ArrayToJSUint32, each element
+ * in the array a) must be an integer; b) must be >= 0. Integers
+ * are clamped to fit in the destination size. Only JSVAL_IS_INT values
+ * are considered to be valid, so for JSUint32, the maximum value that
+ * can be fast-converted is less than the full unsigned 32-bit range.
+ *
+ * For ArrayToJSInt8, ArrayToJSInt16, ArrayToJSInt32, each element in
+ * the array must be an integer. Integers are clamped to fit in the
+ * destination size. Only JSVAL_IS_INT values are considered to be
+ * valid, so for JSInt32, the maximum value that can be
+ * fast-converted is less than the full signed 32-bit range.
+ *
+ * For ArrayToJSDouble, each element in the array must be an
+ * integer -or- a double (JSVAL_IS_NUMBER).
+ */
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint8 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint16 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSUint32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSUint32 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt8Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt8 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt16Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt16 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSInt32Buffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ JSInt32 *dest);
+
+JS_FRIEND_API(JSBool)
+js_ArrayToJSDoubleBuffer(JSContext *cx, JSObject *obj, jsuint offset, jsuint count,
+ jsdouble *dest);
+
+JS_END_EXTERN_C
+
+#endif /* jsarray_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp
new file mode 100644
index 0000000..7bcfeca
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.cpp
@@ -0,0 +1,1064 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS atom table.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsscan.h"
+#include "jsstr.h"
+
+const char *
+js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
+{
+ return js_ValueToPrintableString(cx, ATOM_KEY(atom));
+}
+
+#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+/*
+ * String constants for common atoms defined in JSAtomState starting from
+ * JSAtomState.emptyAtom until JSAtomState.lazy.
+ *
+ * The elements of the array after the first empty string define strings
+ * corresponding to the two boolean literals, false and true, followed by the
+ * JSType enumerators from jspubtd.h starting with "undefined" for JSTYPE_VOID
+ * (which is pseudo-boolean 2) and continuing as initialized below. The static
+ * asserts check these relations.
+ */
+JS_STATIC_ASSERT(JSTYPE_LIMIT == 8);
+JS_STATIC_ASSERT(JSVAL_TO_BOOLEAN(JSVAL_VOID) == 2);
+JS_STATIC_ASSERT(JSTYPE_VOID == 0);
+
+const char *const js_common_atom_names[] = {
+ "", /* emptyAtom */
+ js_false_str, /* booleanAtoms[0] */
+ js_true_str, /* booleanAtoms[1] */
+ js_undefined_str, /* typeAtoms[JSTYPE_VOID] */
+ js_object_str, /* typeAtoms[JSTYPE_OBJECT] */
+ js_function_str, /* typeAtoms[JSTYPE_FUNCTION] */
+ "string", /* typeAtoms[JSTYPE_STRING] */
+ "number", /* typeAtoms[JSTYPE_NUMBER] */
+ "boolean", /* typeAtoms[JSTYPE_BOOLEAN] */
+ js_null_str, /* typeAtoms[JSTYPE_NULL] */
+ "xml", /* typeAtoms[JSTYPE_XML] */
+ js_null_str, /* nullAtom */
+
+#define JS_PROTO(name,code,init) js_##name##_str,
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+ js_anonymous_str, /* anonymousAtom */
+ js_apply_str, /* applyAtom */
+ js_arguments_str, /* argumentsAtom */
+ js_arity_str, /* arityAtom */
+ js_call_str, /* callAtom */
+ js_callee_str, /* calleeAtom */
+ js_caller_str, /* callerAtom */
+ js_class_prototype_str, /* classPrototypeAtom */
+ js_constructor_str, /* constructorAtom */
+ js_count_str, /* countAtom */
+ js_each_str, /* eachAtom */
+ js_eval_str, /* evalAtom */
+ js_fileName_str, /* fileNameAtom */
+ js_get_str, /* getAtom */
+ js_getter_str, /* getterAtom */
+ js_index_str, /* indexAtom */
+ js_input_str, /* inputAtom */
+ js_iterator_str, /* iteratorAtom */
+ js_length_str, /* lengthAtom */
+ js_lineNumber_str, /* lineNumberAtom */
+ js_message_str, /* messageAtom */
+ js_name_str, /* nameAtom */
+ js_next_str, /* nextAtom */
+ js_noSuchMethod_str, /* noSuchMethodAtom */
+ js_parent_str, /* parentAtom */
+ js_proto_str, /* protoAtom */
+ js_set_str, /* setAtom */
+ js_setter_str, /* setterAtom */
+ js_stack_str, /* stackAtom */
+ js_toLocaleString_str, /* toLocaleStringAtom */
+ js_toSource_str, /* toSourceAtom */
+ js_toString_str, /* toStringAtom */
+ js_valueOf_str, /* valueOfAtom */
+ js_toJSON_str, /* toJSONAtom */
+ "(void 0)", /* void0Atom */
+
+#if JS_HAS_XML_SUPPORT
+ js_etago_str, /* etagoAtom */
+ js_namespace_str, /* namespaceAtom */
+ js_ptagc_str, /* ptagcAtom */
+ js_qualifier_str, /* qualifierAtom */
+ js_space_str, /* spaceAtom */
+ js_stago_str, /* stagoAtom */
+ js_star_str, /* starAtom */
+ js_starQualifier_str, /* starQualifierAtom */
+ js_tagc_str, /* tagcAtom */
+ js_xml_str, /* xmlAtom */
+#endif
+
+#ifdef NARCISSUS
+ js___call___str, /* __call__Atom */
+ js___construct___str, /* __construct__Atom */
+ js___hasInstance___str, /* __hasInstance__Atom */
+ js_ExecutionContext_str, /* ExecutionContextAtom */
+ js_current_str, /* currentAtom */
+#endif
+};
+
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) * sizeof(JSAtom *) ==
+ LAZY_ATOM_OFFSET_START - ATOM_OFFSET_START);
+
+/*
+ * Interpreter macros called by the trace recorder assume common atom indexes
+ * fit in one byte of immediate operand.
+ */
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(js_common_atom_names) < 256);
+
+const size_t js_common_atom_count = JS_ARRAY_LENGTH(js_common_atom_names);
+
+const char js_anonymous_str[] = "anonymous";
+const char js_apply_str[] = "apply";
+const char js_arguments_str[] = "arguments";
+const char js_arity_str[] = "arity";
+const char js_call_str[] = "call";
+const char js_callee_str[] = "callee";
+const char js_caller_str[] = "caller";
+const char js_class_prototype_str[] = "prototype";
+const char js_constructor_str[] = "constructor";
+const char js_count_str[] = "__count__";
+const char js_each_str[] = "each";
+const char js_eval_str[] = "eval";
+const char js_fileName_str[] = "fileName";
+const char js_get_str[] = "get";
+const char js_getter_str[] = "getter";
+const char js_index_str[] = "index";
+const char js_input_str[] = "input";
+const char js_iterator_str[] = "__iterator__";
+const char js_length_str[] = "length";
+const char js_lineNumber_str[] = "lineNumber";
+const char js_message_str[] = "message";
+const char js_name_str[] = "name";
+const char js_next_str[] = "next";
+const char js_noSuchMethod_str[] = "__noSuchMethod__";
+const char js_object_str[] = "object";
+const char js_parent_str[] = "__parent__";
+const char js_proto_str[] = "__proto__";
+const char js_setter_str[] = "setter";
+const char js_set_str[] = "set";
+const char js_stack_str[] = "stack";
+const char js_toSource_str[] = "toSource";
+const char js_toString_str[] = "toString";
+const char js_toLocaleString_str[] = "toLocaleString";
+const char js_undefined_str[] = "undefined";
+const char js_valueOf_str[] = "valueOf";
+const char js_toJSON_str[] = "toJSON";
+
+#if JS_HAS_XML_SUPPORT
+const char js_etago_str[] = "</";
+const char js_namespace_str[] = "namespace";
+const char js_ptagc_str[] = "/>";
+const char js_qualifier_str[] = "::";
+const char js_space_str[] = " ";
+const char js_stago_str[] = "<";
+const char js_star_str[] = "*";
+const char js_starQualifier_str[] = "*::";
+const char js_tagc_str[] = ">";
+const char js_xml_str[] = "xml";
+#endif
+
+#if JS_HAS_GENERATORS
+const char js_close_str[] = "close";
+const char js_send_str[] = "send";
+#endif
+
+#ifdef NARCISSUS
+const char js___call___str[] = "__call__";
+const char js___construct___str[] = "__construct__";
+const char js___hasInstance___str[] = "__hasInstance__";
+const char js_ExecutionContext_str[] = "ExecutionContext";
+const char js_current_str[] = "current";
+#endif
+
+/*
+ * JSAtomState.doubleAtoms and JSAtomState.stringAtoms hashtable entry. To
+ * support pinned and interned string atoms, we use the lowest bits of the
+ * keyAndFlags field to store ATOM_PINNED and ATOM_INTERNED flags.
+ */
+typedef struct JSAtomHashEntry {
+ JSDHashEntryHdr hdr;
+ jsuword keyAndFlags;
+} JSAtomHashEntry;
+
+#define ATOM_ENTRY_FLAG_MASK (ATOM_PINNED | ATOM_INTERNED)
+
+JS_STATIC_ASSERT(ATOM_ENTRY_FLAG_MASK < JSVAL_ALIGN);
+
+/*
+ * Helper macros to access and modify JSAtomHashEntry.
+ */
+#define TO_ATOM_ENTRY(hdr) ((JSAtomHashEntry *) hdr)
+#define ATOM_ENTRY_KEY(entry) \
+ ((void *)((entry)->keyAndFlags & ~ATOM_ENTRY_FLAG_MASK))
+#define ATOM_ENTRY_FLAGS(entry) \
+ ((uintN)((entry)->keyAndFlags & ATOM_ENTRY_FLAG_MASK))
+#define INIT_ATOM_ENTRY(entry, key) \
+ ((void)((entry)->keyAndFlags = (jsuword)(key)))
+#define ADD_ATOM_ENTRY_FLAGS(entry, flags) \
+ ((void)((entry)->keyAndFlags |= (jsuword)(flags)))
+#define CLEAR_ATOM_ENTRY_FLAGS(entry, flags) \
+ ((void)((entry)->keyAndFlags &= ~(jsuword)(flags)))
+
+static JSDHashNumber
+HashDouble(JSDHashTable *table, const void *key);
+
+static JSBool
+MatchDouble(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key);
+
+static JSDHashNumber
+HashString(JSDHashTable *table, const void *key);
+
+static JSBool
+MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key);
+
+static const JSDHashTableOps DoubleHashOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ HashDouble,
+ MatchDouble,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+static const JSDHashTableOps StringHashOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ HashString,
+ MatchString,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+#define IS_DOUBLE_TABLE(table) ((table)->ops == &DoubleHashOps)
+#define IS_STRING_TABLE(table) ((table)->ops == &StringHashOps)
+
+#define IS_INITIALIZED_STATE(state) IS_DOUBLE_TABLE(&(state)->doubleAtoms)
+
+static JSDHashNumber
+HashDouble(JSDHashTable *table, const void *key)
+{
+ jsdouble d;
+
+ JS_ASSERT(IS_DOUBLE_TABLE(table));
+ d = *(jsdouble *)key;
+ return JSDOUBLE_HI32(d) ^ JSDOUBLE_LO32(d);
+}
+
+static JSDHashNumber
+HashString(JSDHashTable *table, const void *key)
+{
+ JS_ASSERT(IS_STRING_TABLE(table));
+ return js_HashString((JSString *)key);
+}
+
+static JSBool
+MatchDouble(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ jsdouble d1, d2;
+
+ JS_ASSERT(IS_DOUBLE_TABLE(table));
+ if (entry->keyAndFlags == 0) {
+ /* See comments in MatchString. */
+ return JS_FALSE;
+ }
+
+ d1 = *(jsdouble *)ATOM_ENTRY_KEY(entry);
+ d2 = *(jsdouble *)key;
+ if (JSDOUBLE_IS_NaN(d1))
+ return JSDOUBLE_IS_NaN(d2);
+#if defined(XP_WIN)
+ /* XXX MSVC miscompiles such that (NaN == 0) */
+ if (JSDOUBLE_IS_NaN(d2))
+ return JS_FALSE;
+#endif
+ return d1 == d2;
+}
+
+static JSBool
+MatchString(JSDHashTable *table, const JSDHashEntryHdr *hdr, const void *key)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+
+ JS_ASSERT(IS_STRING_TABLE(table));
+ if (entry->keyAndFlags == 0) {
+ /*
+ * This happens when js_AtomizeString adds a new hash entry and
+ * releases the lock but before it takes the lock the second time to
+ * initialize keyAndFlags for the entry.
+ *
+ * We always return false for such entries so JS_DHashTableOperate
+ * never finds them. We clean them during GC's sweep phase.
+ *
+ * It means that with a contested lock or when GC is triggered outside
+ * the lock we may end up adding two entries, but this is a price for
+ * simpler code.
+ */
+ return JS_FALSE;
+ }
+ return js_EqualStrings((JSString *)ATOM_ENTRY_KEY(entry), (JSString *)key);
+}
+
+/*
+ * For a browser build from 2007-08-09 after the browser starts up there are
+ * just 55 double atoms, but over 15000 string atoms. Not to penalize more
+ * economical embeddings allocating too much memory initially we initialize
+ * atomized strings with just 1K entries.
+ */
+#define JS_STRING_HASH_COUNT 1024
+#define JS_DOUBLE_HASH_COUNT 64
+
+JSBool
+js_InitAtomState(JSRuntime *rt)
+{
+ JSAtomState *state = &rt->atomState;
+
+ /*
+ * The caller must zero the state before calling this function.
+ */
+ JS_ASSERT(!state->stringAtoms.ops);
+ JS_ASSERT(!state->doubleAtoms.ops);
+
+ if (!JS_DHashTableInit(&state->stringAtoms, &StringHashOps,
+ NULL, sizeof(JSAtomHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(JS_STRING_HASH_COUNT))) {
+ state->stringAtoms.ops = NULL;
+ return JS_FALSE;
+ }
+ JS_ASSERT(IS_STRING_TABLE(&state->stringAtoms));
+
+ if (!JS_DHashTableInit(&state->doubleAtoms, &DoubleHashOps,
+ NULL, sizeof(JSAtomHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(JS_DOUBLE_HASH_COUNT))) {
+ state->doubleAtoms.ops = NULL;
+ JS_DHashTableFinish(&state->stringAtoms);
+ state->stringAtoms.ops = NULL;
+ return JS_FALSE;
+ }
+ JS_ASSERT(IS_DOUBLE_TABLE(&state->doubleAtoms));
+
+#ifdef JS_THREADSAFE
+ js_InitLock(&state->lock);
+#endif
+ JS_ASSERT(IS_INITIALIZED_STATE(state));
+ return JS_TRUE;
+}
+
+static JSDHashOperator
+js_string_uninterner(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSRuntime *rt = (JSRuntime *)arg;
+ JSString *str;
+
+ /*
+ * Any string entry that remains at this point must be initialized, as the
+ * last GC should clean any uninitialized ones.
+ */
+ JS_ASSERT(IS_STRING_TABLE(table));
+ JS_ASSERT(entry->keyAndFlags != 0);
+ str = (JSString *)ATOM_ENTRY_KEY(entry);
+
+ /* Pass null as context. */
+ js_FinalizeStringRT(rt, str, js_GetExternalStringGCType(str), NULL);
+ return JS_DHASH_NEXT;
+}
+
+void
+js_FinishAtomState(JSRuntime *rt)
+{
+ JSAtomState *state = &rt->atomState;
+
+ if (!IS_INITIALIZED_STATE(state)) {
+ /*
+ * We are called with uninitialized state when JS_NewRuntime fails and
+ * calls JS_DestroyRuntime on a partially initialized runtime.
+ */
+ return;
+ }
+
+ JS_DHashTableEnumerate(&state->stringAtoms, js_string_uninterner, rt);
+ JS_DHashTableFinish(&state->stringAtoms);
+ JS_DHashTableFinish(&state->doubleAtoms);
+
+#ifdef JS_THREADSAFE
+ js_FinishLock(&state->lock);
+#endif
+#ifdef DEBUG
+ memset(state, JS_FREE_PATTERN, sizeof *state);
+#endif
+}
+
+JSBool
+js_InitCommonAtoms(JSContext *cx)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+ uintN i;
+ JSAtom **atoms;
+
+ atoms = COMMON_ATOMS_START(state);
+ for (i = 0; i < JS_ARRAY_LENGTH(js_common_atom_names); i++, atoms++) {
+ *atoms = js_Atomize(cx, js_common_atom_names[i],
+ strlen(js_common_atom_names[i]), ATOM_PINNED);
+ if (!*atoms)
+ return JS_FALSE;
+ }
+ JS_ASSERT((uint8 *)atoms - (uint8 *)state == LAZY_ATOM_OFFSET_START);
+ memset(atoms, 0, ATOM_OFFSET_LIMIT - LAZY_ATOM_OFFSET_START);
+
+ return JS_TRUE;
+}
+
+static JSDHashOperator
+js_atom_unpinner(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JS_ASSERT(IS_STRING_TABLE(table));
+ CLEAR_ATOM_ENTRY_FLAGS(TO_ATOM_ENTRY(hdr), ATOM_PINNED);
+ return JS_DHASH_NEXT;
+}
+
+void
+js_FinishCommonAtoms(JSContext *cx)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+
+ JS_DHashTableEnumerate(&state->stringAtoms, js_atom_unpinner, NULL);
+#ifdef DEBUG
+ memset(COMMON_ATOMS_START(state), JS_FREE_PATTERN,
+ ATOM_OFFSET_LIMIT - ATOM_OFFSET_START);
+#endif
+}
+
+static JSDHashOperator
+js_locked_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSTracer *trc = (JSTracer *)arg;
+
+ if (entry->keyAndFlags == 0) {
+ /* Ignore uninitialized entries during tracing. */
+ return JS_DHASH_NEXT;
+ }
+ JS_SET_TRACING_INDEX(trc, "locked_atom", (size_t)number);
+ JS_CallTracer(trc, ATOM_ENTRY_KEY(entry),
+ IS_STRING_TABLE(table) ? JSTRACE_STRING : JSTRACE_DOUBLE);
+ return JS_DHASH_NEXT;
+}
+
+static JSDHashOperator
+js_pinned_atom_tracer(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSTracer *trc = (JSTracer *)arg;
+ uintN flags = ATOM_ENTRY_FLAGS(entry);
+
+ JS_ASSERT(IS_STRING_TABLE(table));
+ if (flags & (ATOM_PINNED | ATOM_INTERNED)) {
+ JS_SET_TRACING_INDEX(trc,
+ flags & ATOM_PINNED
+ ? "pinned_atom"
+ : "interned_atom",
+ (size_t)number);
+ JS_CallTracer(trc, ATOM_ENTRY_KEY(entry), JSTRACE_STRING);
+ }
+ return JS_DHASH_NEXT;
+}
+
+void
+js_TraceAtomState(JSTracer *trc, JSBool allAtoms)
+{
+ JSAtomState *state;
+
+ state = &trc->context->runtime->atomState;
+ if (allAtoms) {
+ JS_DHashTableEnumerate(&state->doubleAtoms, js_locked_atom_tracer, trc);
+ JS_DHashTableEnumerate(&state->stringAtoms, js_locked_atom_tracer, trc);
+ } else {
+ JS_DHashTableEnumerate(&state->stringAtoms, js_pinned_atom_tracer, trc);
+ }
+}
+
+static JSDHashOperator
+js_atom_sweeper(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ JSContext *cx = (JSContext *)arg;
+
+ /* Remove uninitialized entries. */
+ if (entry->keyAndFlags == 0)
+ return JS_DHASH_REMOVE;
+
+ if (ATOM_ENTRY_FLAGS(entry) & (ATOM_PINNED | ATOM_INTERNED)) {
+ /* Pinned or interned key cannot be finalized. */
+ JS_ASSERT(!js_IsAboutToBeFinalized(cx, ATOM_ENTRY_KEY(entry)));
+ } else if (js_IsAboutToBeFinalized(cx, ATOM_ENTRY_KEY(entry))) {
+ /* Remove entries with things about to be GC'ed. */
+ return JS_DHASH_REMOVE;
+ }
+ return JS_DHASH_NEXT;
+}
+
+void
+js_SweepAtomState(JSContext *cx)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+
+ JS_DHashTableEnumerate(&state->doubleAtoms, js_atom_sweeper, cx);
+ JS_DHashTableEnumerate(&state->stringAtoms, js_atom_sweeper, cx);
+
+ /*
+ * Optimize for simplicity and mutate table generation numbers even if the
+ * sweeper has not removed any entries.
+ */
+ state->doubleAtoms.generation++;
+ state->stringAtoms.generation++;
+}
+
+JSAtom *
+js_AtomizeDouble(JSContext *cx, jsdouble d)
+{
+ JSAtomState *state;
+ JSDHashTable *table;
+ JSAtomHashEntry *entry;
+ uint32 gen;
+ jsdouble *key;
+ jsval v;
+
+ state = &cx->runtime->atomState;
+ table = &state->doubleAtoms;
+
+ JS_LOCK(cx, &state->lock);
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, &d, JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags == 0) {
+ gen = ++table->generation;
+ JS_UNLOCK(cx, &state->lock);
+
+ key = js_NewWeaklyRootedDouble(cx, d);
+ if (!key)
+ return NULL;
+
+ JS_LOCK(cx, &state->lock);
+ if (table->generation == gen) {
+ JS_ASSERT(entry->keyAndFlags == 0);
+ } else {
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key,
+ JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags != 0)
+ goto finish;
+ ++table->generation;
+ }
+ INIT_ATOM_ENTRY(entry, key);
+ }
+
+ finish:
+ v = DOUBLE_TO_JSVAL((jsdouble *)ATOM_ENTRY_KEY(entry));
+ cx->weakRoots.lastAtom = v;
+ JS_UNLOCK(cx, &state->lock);
+
+ return (JSAtom *)v;
+
+ failed_hash_add:
+ JS_UNLOCK(cx, &state->lock);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+JSAtom *
+js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
+{
+ jsval v;
+ JSAtomState *state;
+ JSDHashTable *table;
+ JSAtomHashEntry *entry;
+ JSString *key;
+ uint32 gen;
+
+ JS_ASSERT(!(flags & ~(ATOM_PINNED|ATOM_INTERNED|ATOM_TMPSTR|ATOM_NOCOPY)));
+ JS_ASSERT_IF(flags & ATOM_NOCOPY, flags & ATOM_TMPSTR);
+
+ state = &cx->runtime->atomState;
+ table = &state->stringAtoms;
+
+ JS_LOCK(cx, &state->lock);
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, str, JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags != 0) {
+ key = (JSString *)ATOM_ENTRY_KEY(entry);
+ } else {
+ /*
+ * We created a new hashtable entry. Unless str is already allocated
+ * from the GC heap and flat, we have to release state->lock as
+ * string construction is a complex operation. For example, it can
+ * trigger GC which may rehash the table and make the entry invalid.
+ */
+ ++table->generation;
+ if (!(flags & ATOM_TMPSTR) && JSSTRING_IS_FLAT(str)) {
+ JSFLATSTR_CLEAR_MUTABLE(str);
+ key = str;
+ } else {
+ gen = table->generation;
+ JS_UNLOCK(cx, &state->lock);
+
+ if (flags & ATOM_TMPSTR) {
+ if (flags & ATOM_NOCOPY) {
+ key = js_NewString(cx, JSFLATSTR_CHARS(str),
+ JSFLATSTR_LENGTH(str));
+ if (!key)
+ return NULL;
+
+ /* Finish handing off chars to the GC'ed key string. */
+ str->u.chars = NULL;
+ } else {
+ key = js_NewStringCopyN(cx, JSFLATSTR_CHARS(str),
+ JSFLATSTR_LENGTH(str));
+ if (!key)
+ return NULL;
+ }
+ } else {
+ JS_ASSERT(JSSTRING_IS_DEPENDENT(str));
+ if (!js_UndependString(cx, str))
+ return NULL;
+ key = str;
+ }
+
+ JS_LOCK(cx, &state->lock);
+ if (table->generation == gen) {
+ JS_ASSERT(entry->keyAndFlags == 0);
+ } else {
+ entry = TO_ATOM_ENTRY(JS_DHashTableOperate(table, key,
+ JS_DHASH_ADD));
+ if (!entry)
+ goto failed_hash_add;
+ if (entry->keyAndFlags != 0) {
+ key = (JSString *)ATOM_ENTRY_KEY(entry);
+ goto finish;
+ }
+ ++table->generation;
+ }
+ }
+ INIT_ATOM_ENTRY(entry, key);
+ JSFLATSTR_SET_ATOMIZED(key);
+ }
+
+ finish:
+ ADD_ATOM_ENTRY_FLAGS(entry, flags & (ATOM_PINNED | ATOM_INTERNED));
+ JS_ASSERT(JSSTRING_IS_ATOMIZED(key));
+ v = STRING_TO_JSVAL(key);
+ cx->weakRoots.lastAtom = v;
+ JS_UNLOCK(cx, &state->lock);
+ return (JSAtom *)v;
+
+ failed_hash_add:
+ JS_UNLOCK(cx, &state->lock);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+JSAtom *
+js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags)
+{
+ jschar *chars;
+ JSString str;
+ JSAtom *atom;
+
+ /*
+ * Avoiding the malloc in js_InflateString on shorter strings saves us
+ * over 20,000 malloc calls on mozilla browser startup. This compares to
+ * only 131 calls where the string is longer than a 31 char (net) buffer.
+ * The vast majority of atomized strings are already in the hashtable. So
+ * js_AtomizeString rarely has to copy the temp string we make.
+ */
+#define ATOMIZE_BUF_MAX 32
+ jschar inflated[ATOMIZE_BUF_MAX];
+ size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
+
+ if (length < ATOMIZE_BUF_MAX) {
+ js_InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
+ inflated[inflatedLength] = 0;
+ chars = inflated;
+ } else {
+ inflatedLength = length;
+ chars = js_InflateString(cx, bytes, &inflatedLength);
+ if (!chars)
+ return NULL;
+ flags |= ATOM_NOCOPY;
+ }
+
+ JSFLATSTR_INIT(&str, (jschar *)chars, inflatedLength);
+ atom = js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
+ if (chars != inflated && str.u.chars)
+ JS_free(cx, chars);
+ return atom;
+}
+
+JSAtom *
+js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
+{
+ JSString str;
+
+ JSFLATSTR_INIT(&str, (jschar *)chars, length);
+ return js_AtomizeString(cx, &str, ATOM_TMPSTR | flags);
+}
+
+JSAtom *
+js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
+{
+ JSString str, *str2;
+ JSAtomState *state;
+ JSDHashEntryHdr *hdr;
+
+ JSFLATSTR_INIT(&str, (jschar *)chars, length);
+ state = &cx->runtime->atomState;
+
+ JS_LOCK(cx, &state->lock);
+ hdr = JS_DHashTableOperate(&state->stringAtoms, &str, JS_DHASH_LOOKUP);
+ str2 = JS_DHASH_ENTRY_IS_BUSY(hdr)
+ ? (JSString *)ATOM_ENTRY_KEY(TO_ATOM_ENTRY(hdr))
+ : NULL;
+ JS_UNLOCK(cx, &state->lock);
+
+ return str2 ? (JSAtom *)STRING_TO_JSVAL(str2) : NULL;
+}
+
+JSBool
+js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp)
+{
+ JSAtom *atom;
+
+ if (JSVAL_IS_STRING(v)) {
+ atom = js_AtomizeString(cx, JSVAL_TO_STRING(v), 0);
+ if (!atom)
+ return JS_FALSE;
+ } else if (JSVAL_IS_DOUBLE(v)) {
+ atom = js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(v));
+ if (!atom)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_BOOLEAN(v) ||
+ JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v));
+ atom = (JSAtom *)v;
+ }
+ *atomp = atom;
+ return JS_TRUE;
+}
+
+JSBool
+js_ValueToStringId(JSContext *cx, jsval v, jsid *idp)
+{
+ JSString *str;
+ JSAtom *atom;
+
+ /*
+ * Optimize for the common case where v is an already-atomized string. The
+ * comment in jsstr.h before the JSSTRING_SET_ATOMIZED macro's definition
+ * explains why this is thread-safe. The extra rooting via lastAtom (which
+ * would otherwise be done in js_js_AtomizeString) ensures the caller that
+ * the resulting id at is least weakly rooted.
+ */
+ if (JSVAL_IS_STRING(v)) {
+ str = JSVAL_TO_STRING(v);
+ if (JSSTRING_IS_ATOMIZED(str)) {
+ cx->weakRoots.lastAtom = v;
+ *idp = ATOM_TO_JSID((JSAtom *) v);
+ return JS_TRUE;
+ }
+ } else {
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+ }
+ atom = js_AtomizeString(cx, str, 0);
+ if (!atom)
+ return JS_FALSE;
+ *idp = ATOM_TO_JSID(atom);
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static JSDHashOperator
+atom_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSAtomHashEntry *entry = TO_ATOM_ENTRY(hdr);
+ FILE *fp = (FILE *)arg;
+ void *key;
+ uintN flags;
+
+ fprintf(fp, "%3u %08x ", number, (uintN)entry->hdr.keyHash);
+ if (entry->keyAndFlags == 0) {
+ fputs("<uninitialized>", fp);
+ } else {
+ key = ATOM_ENTRY_KEY(entry);
+ if (IS_DOUBLE_TABLE(table)) {
+ fprintf(fp, "%.16g", *(jsdouble *)key);
+ } else {
+ JS_ASSERT(IS_STRING_TABLE(table));
+ js_FileEscapedString(fp, (JSString *)key, '"');
+ }
+ flags = ATOM_ENTRY_FLAGS(entry);
+ if (flags != 0) {
+ fputs((flags & (ATOM_PINNED | ATOM_INTERNED))
+ ? " pinned | interned"
+ : (flags & ATOM_PINNED) ? " pinned" : " interned",
+ fp);
+ }
+ }
+ putc('\n', fp);
+ return JS_DHASH_NEXT;
+}
+
+JS_FRIEND_API(void)
+js_DumpAtoms(JSContext *cx, FILE *fp)
+{
+ JSAtomState *state = &cx->runtime->atomState;
+
+ fprintf(fp, "stringAtoms table contents:\n");
+ JS_DHashTableEnumerate(&state->stringAtoms, atom_dumper, fp);
+#ifdef JS_DHASHMETER
+ JS_DHashTableDumpMeter(&state->stringAtoms, atom_dumper, fp);
+#endif
+ putc('\n', fp);
+
+ fprintf(fp, "doubleAtoms table contents:\n");
+ JS_DHashTableEnumerate(&state->doubleAtoms, atom_dumper, fp);
+#ifdef JS_DHASHMETER
+ JS_DHashTableDumpMeter(&state->doubleAtoms, atom_dumper, fp);
+#endif
+ putc('\n', fp);
+}
+
+#endif
+
+static JSHashNumber
+js_hash_atom_ptr(const void *key)
+{
+ const JSAtom *atom = (const JSAtom *) key;
+ return ATOM_HASH(atom);
+}
+
+static void *
+js_alloc_temp_space(void *priv, size_t size)
+{
+ JSContext *cx = (JSContext *) priv;
+ void *space;
+
+ JS_ARENA_ALLOCATE(space, &cx->tempPool, size);
+ if (!space)
+ js_ReportOutOfScriptQuota(cx);
+ return space;
+}
+
+static void
+js_free_temp_space(void *priv, void *item)
+{
+}
+
+static JSHashEntry *
+js_alloc_temp_entry(void *priv, const void *key)
+{
+ JSContext *cx = (JSContext *) priv;
+ JSAtomListElement *ale;
+
+ JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool);
+ if (!ale) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ return &ale->entry;
+}
+
+static void
+js_free_temp_entry(void *priv, JSHashEntry *he, uintN flag)
+{
+}
+
+static JSHashAllocOps temp_alloc_ops = {
+ js_alloc_temp_space, js_free_temp_space,
+ js_alloc_temp_entry, js_free_temp_entry
+};
+
+JSAtomListElement *
+js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al)
+{
+ JSAtomListElement *ale, *ale2, *next;
+ JSHashEntry **hep;
+
+ ATOM_LIST_LOOKUP(ale, hep, al, atom);
+ if (!ale) {
+ if (al->count < 10) {
+ /* Few enough for linear search, no hash table needed. */
+ JS_ASSERT(!al->table);
+ ale = (JSAtomListElement *)js_alloc_temp_entry(cx, atom);
+ if (!ale)
+ return NULL;
+ ALE_SET_ATOM(ale, atom);
+ ale->entry.next = al->list;
+ al->list = &ale->entry;
+ } else {
+ /* We want to hash. Have we already made a hash table? */
+ if (!al->table) {
+ /* No hash table yet, so hep had better be null! */
+ JS_ASSERT(!hep);
+ al->table = JS_NewHashTable(al->count + 1, js_hash_atom_ptr,
+ JS_CompareValues, JS_CompareValues,
+ &temp_alloc_ops, cx);
+ if (!al->table)
+ return NULL;
+
+ /*
+ * Set ht->nentries explicitly, because we are moving entries
+ * from al to ht, not calling JS_HashTable(Raw|)Add.
+ */
+ al->table->nentries = al->count;
+
+ /* Insert each ale on al->list into the new hash table. */
+ for (ale2 = (JSAtomListElement *)al->list; ale2; ale2 = next) {
+ next = ALE_NEXT(ale2);
+ ale2->entry.keyHash = ATOM_HASH(ALE_ATOM(ale2));
+ hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash,
+ ale2->entry.key);
+ ale2->entry.next = *hep;
+ *hep = &ale2->entry;
+ }
+ al->list = NULL;
+
+ /* Set hep for insertion of atom's ale, immediately below. */
+ hep = JS_HashTableRawLookup(al->table, ATOM_HASH(atom), atom);
+ }
+
+ /* Finally, add an entry for atom into the hash bucket at hep. */
+ ale = (JSAtomListElement *)
+ JS_HashTableRawAdd(al->table, hep, ATOM_HASH(atom), atom,
+ NULL);
+ if (!ale)
+ return NULL;
+ }
+
+ ALE_SET_INDEX(ale, al->count++);
+ }
+ return ale;
+}
+
+static intN
+js_map_atom(JSHashEntry *he, intN i, void *arg)
+{
+ JSAtomListElement *ale = (JSAtomListElement *)he;
+ JSAtom **vector = (JSAtom **) arg;
+
+ vector[ALE_INDEX(ale)] = ALE_ATOM(ale);
+ return HT_ENUMERATE_NEXT;
+}
+
+#ifdef DEBUG
+static jsrefcount js_atom_map_count;
+static jsrefcount js_atom_map_hash_table_count;
+#endif
+
+void
+js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
+{
+ JSAtom **vector;
+ JSAtomListElement *ale;
+ uint32 count;
+
+ /* Map length must already be initialized. */
+ JS_ASSERT(al->count == map->length);
+#ifdef DEBUG
+ JS_ATOMIC_INCREMENT(&js_atom_map_count);
+#endif
+ ale = (JSAtomListElement *)al->list;
+ if (!ale && !al->table) {
+ JS_ASSERT(!map->vector);
+ return;
+ }
+
+ count = al->count;
+ vector = map->vector;
+ if (al->table) {
+#ifdef DEBUG
+ JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count);
+#endif
+ JS_HashTableEnumerateEntries(al->table, js_map_atom, vector);
+ } else {
+ do {
+ vector[ALE_INDEX(ale)] = ALE_ATOM(ale);
+ } while ((ale = ALE_NEXT(ale)) != NULL);
+ }
+ ATOM_LIST_INIT(al);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsatom.h b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.h
new file mode 100644
index 0000000..76dd5c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsatom.h
@@ -0,0 +1,458 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsatom_h___
+#define jsatom_h___
+/*
+ * JS atom table.
+ */
+#include <stddef.h>
+#include "jsversion.h"
+#include "jstypes.h"
+#include "jshash.h" /* Added by JSIFY */
+#include "jsdhash.h"
+#include "jsapi.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jslock.h"
+
+JS_BEGIN_EXTERN_C
+
+#define ATOM_PINNED 0x1 /* atom is pinned against GC */
+#define ATOM_INTERNED 0x2 /* pinned variant for JS_Intern* API */
+#define ATOM_NOCOPY 0x4 /* don't copy atom string bytes */
+#define ATOM_TMPSTR 0x8 /* internal, to avoid extra string */
+
+#define ATOM_KEY(atom) ((jsval)(atom))
+#define ATOM_IS_DOUBLE(atom) JSVAL_IS_DOUBLE(ATOM_KEY(atom))
+#define ATOM_TO_DOUBLE(atom) JSVAL_TO_DOUBLE(ATOM_KEY(atom))
+#define ATOM_IS_STRING(atom) JSVAL_IS_STRING(ATOM_KEY(atom))
+#define ATOM_TO_STRING(atom) JSVAL_TO_STRING(ATOM_KEY(atom))
+
+JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
+JS_STATIC_ASSERT(sizeof(JSAtom *) == JS_BYTES_PER_WORD);
+
+#if JS_BYTES_PER_WORD == 4
+# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
+#elif JS_BYTES_PER_WORD == 8
+# define ATOM_HASH(atom) (((JSHashNumber)(jsuword)(atom) >> 3) ^ \
+ (JSHashNumber)((jsuword)(atom) >> 32))
+#else
+# error "Unsupported configuration"
+#endif
+
+/*
+ * Return a printable, lossless char[] representation of a string-type atom.
+ * The lifetime of the result extends at least until the next GC activation,
+ * longer if cx's string newborn root is not overwritten.
+ */
+extern const char *
+js_AtomToPrintableString(JSContext *cx, JSAtom *atom);
+
+struct JSAtomListElement {
+ JSHashEntry entry;
+};
+
+#define ALE_ATOM(ale) ((JSAtom *) (ale)->entry.key)
+#define ALE_INDEX(ale) ((jsatomid) JS_PTR_TO_UINT32((ale)->entry.value))
+#define ALE_JSOP(ale) ((JSOp) JS_PTR_TO_UINT32((ale)->entry.value))
+#define ALE_VALUE(ale) ((jsval) (ale)->entry.value)
+#define ALE_NEXT(ale) ((JSAtomListElement *) (ale)->entry.next)
+
+#define ALE_SET_ATOM(ale,atom) ((ale)->entry.key = (const void *)(atom))
+#define ALE_SET_INDEX(ale,index)((ale)->entry.value = JS_UINT32_TO_PTR(index))
+#define ALE_SET_JSOP(ale,op) ((ale)->entry.value = JS_UINT32_TO_PTR(op))
+#define ALE_SET_VALUE(ale, v) ((ale)->entry.value = (void *)(v))
+
+struct JSAtomList {
+ JSHashEntry *list; /* literals indexed for mapping */
+ JSHashTable *table; /* hash table if list gets too long */
+ jsuint count; /* count of indexed literals */
+};
+
+#define ATOM_LIST_INIT(al) ((al)->list = NULL, (al)->table = NULL, \
+ (al)->count = 0)
+
+#define ATOM_LIST_SEARCH(_ale,_al,_atom) \
+ JS_BEGIN_MACRO \
+ JSHashEntry **_hep; \
+ ATOM_LIST_LOOKUP(_ale, _hep, _al, _atom); \
+ JS_END_MACRO
+
+#define ATOM_LIST_LOOKUP(_ale,_hep,_al,_atom) \
+ JS_BEGIN_MACRO \
+ if ((_al)->table) { \
+ _hep = JS_HashTableRawLookup((_al)->table, ATOM_HASH(_atom), \
+ _atom); \
+ _ale = *_hep ? (JSAtomListElement *) *_hep : NULL; \
+ } else { \
+ JSHashEntry **_alep = &(_al)->list; \
+ _hep = NULL; \
+ while ((_ale = (JSAtomListElement *)*_alep) != NULL) { \
+ if (ALE_ATOM(_ale) == (_atom)) { \
+ /* Hit, move atom's element to the front of the list. */ \
+ *_alep = (_ale)->entry.next; \
+ (_ale)->entry.next = (_al)->list; \
+ (_al)->list = &_ale->entry; \
+ break; \
+ } \
+ _alep = &_ale->entry.next; \
+ } \
+ } \
+ JS_END_MACRO
+
+struct JSAtomMap {
+ JSAtom **vector; /* array of ptrs to indexed atoms */
+ jsatomid length; /* count of (to-be-)indexed atoms */
+};
+
+struct JSAtomState {
+ JSDHashTable stringAtoms; /* hash table with shared strings */
+ JSDHashTable doubleAtoms; /* hash table with shared doubles */
+#ifdef JS_THREADSAFE
+ JSThinLock lock;
+#endif
+
+ /*
+ * From this point until the end of struct definition the struct must
+ * contain only JSAtom fields. We use this to access the storage occupied
+ * by the common atoms in js_FinishCommonAtoms.
+ *
+ * js_common_atom_names defined in jsatom.c contains C strings for atoms
+ * in the order of atom fields here. Therefore you must update that array
+ * if you change member order here.
+ */
+
+ /* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */
+ JSAtom *emptyAtom;
+
+ /*
+ * Literal value and type names.
+ * NB: booleanAtoms must come right before typeAtoms!
+ */
+ JSAtom *booleanAtoms[2];
+ JSAtom *typeAtoms[JSTYPE_LIMIT];
+ JSAtom *nullAtom;
+
+ /* Standard class constructor or prototype names. */
+ JSAtom *classAtoms[JSProto_LIMIT];
+
+ /* Various built-in or commonly-used atoms, pinned on first context. */
+ JSAtom *anonymousAtom;
+ JSAtom *applyAtom;
+ JSAtom *argumentsAtom;
+ JSAtom *arityAtom;
+ JSAtom *callAtom;
+ JSAtom *calleeAtom;
+ JSAtom *callerAtom;
+ JSAtom *classPrototypeAtom;
+ JSAtom *constructorAtom;
+ JSAtom *countAtom;
+ JSAtom *eachAtom;
+ JSAtom *evalAtom;
+ JSAtom *fileNameAtom;
+ JSAtom *getAtom;
+ JSAtom *getterAtom;
+ JSAtom *indexAtom;
+ JSAtom *inputAtom;
+ JSAtom *iteratorAtom;
+ JSAtom *lengthAtom;
+ JSAtom *lineNumberAtom;
+ JSAtom *messageAtom;
+ JSAtom *nameAtom;
+ JSAtom *nextAtom;
+ JSAtom *noSuchMethodAtom;
+ JSAtom *parentAtom;
+ JSAtom *protoAtom;
+ JSAtom *setAtom;
+ JSAtom *setterAtom;
+ JSAtom *stackAtom;
+ JSAtom *toLocaleStringAtom;
+ JSAtom *toSourceAtom;
+ JSAtom *toStringAtom;
+ JSAtom *valueOfAtom;
+ JSAtom *toJSONAtom;
+ JSAtom *void0Atom;
+
+#if JS_HAS_XML_SUPPORT
+ JSAtom *etagoAtom;
+ JSAtom *namespaceAtom;
+ JSAtom *ptagcAtom;
+ JSAtom *qualifierAtom;
+ JSAtom *spaceAtom;
+ JSAtom *stagoAtom;
+ JSAtom *starAtom;
+ JSAtom *starQualifierAtom;
+ JSAtom *tagcAtom;
+ JSAtom *xmlAtom;
+#endif
+
+#ifdef NARCISSUS
+ JSAtom *__call__Atom;
+ JSAtom *__construct__Atom;
+ JSAtom *__hasInstance__Atom;
+ JSAtom *ExecutionContextAtom;
+ JSAtom *currentAtom;
+#endif
+
+ /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
+ struct {
+ JSAtom *InfinityAtom;
+ JSAtom *NaNAtom;
+ JSAtom *XMLListAtom;
+ JSAtom *decodeURIAtom;
+ JSAtom *decodeURIComponentAtom;
+ JSAtom *defineGetterAtom;
+ JSAtom *defineSetterAtom;
+ JSAtom *encodeURIAtom;
+ JSAtom *encodeURIComponentAtom;
+ JSAtom *escapeAtom;
+ JSAtom *functionNamespaceURIAtom;
+ JSAtom *hasOwnPropertyAtom;
+ JSAtom *isFiniteAtom;
+ JSAtom *isNaNAtom;
+ JSAtom *isPrototypeOfAtom;
+ JSAtom *isXMLNameAtom;
+ JSAtom *lookupGetterAtom;
+ JSAtom *lookupSetterAtom;
+ JSAtom *parseFloatAtom;
+ JSAtom *parseIntAtom;
+ JSAtom *propertyIsEnumerableAtom;
+ JSAtom *unescapeAtom;
+ JSAtom *unevalAtom;
+ JSAtom *unwatchAtom;
+ JSAtom *watchAtom;
+ } lazy;
+};
+
+#define ATOM_OFFSET_START offsetof(JSAtomState, emptyAtom)
+#define LAZY_ATOM_OFFSET_START offsetof(JSAtomState, lazy)
+#define ATOM_OFFSET_LIMIT (sizeof(JSAtomState))
+
+#define COMMON_ATOMS_START(state) \
+ ((JSAtom **)((uint8 *)(state) + ATOM_OFFSET_START))
+#define COMMON_ATOM_INDEX(name) \
+ ((offsetof(JSAtomState, name##Atom) - ATOM_OFFSET_START) \
+ / sizeof(JSAtom*))
+#define COMMON_TYPE_ATOM_INDEX(type) \
+ ((offsetof(JSAtomState, typeAtoms[type]) - ATOM_OFFSET_START) \
+ / sizeof(JSAtom*))
+
+/* Start and limit offsets should correspond to atoms. */
+JS_STATIC_ASSERT(ATOM_OFFSET_START % sizeof(JSAtom *) == 0);
+JS_STATIC_ASSERT(ATOM_OFFSET_LIMIT % sizeof(JSAtom *) == 0);
+
+#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
+#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
+#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState,classAtoms[JSProto_##name])
+
+#define CLASS_ATOM(cx,name) \
+ ((cx)->runtime->atomState.classAtoms[JSProto_##name])
+
+extern const char *const js_common_atom_names[];
+extern const size_t js_common_atom_count;
+
+/*
+ * Macros to access C strings for JSType and boolean literals together with
+ * checks that boolean names start from index 1 and type names from 1+2.
+ */
+#define JS_BOOLEAN_STR(type) (js_common_atom_names[1 + (type)])
+#define JS_TYPE_STR(type) (js_common_atom_names[1 + 2 + (type)])
+
+JS_STATIC_ASSERT(1 * sizeof(JSAtom *) ==
+ offsetof(JSAtomState, booleanAtoms) - ATOM_OFFSET_START);
+JS_STATIC_ASSERT((1 + 2) * sizeof(JSAtom *) ==
+ offsetof(JSAtomState, typeAtoms) - ATOM_OFFSET_START);
+
+/* Well-known predefined C strings. */
+#define JS_PROTO(name,code,init) extern const char js_##name##_str[];
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+extern const char js_anonymous_str[];
+extern const char js_apply_str[];
+extern const char js_arguments_str[];
+extern const char js_arity_str[];
+extern const char js_call_str[];
+extern const char js_callee_str[];
+extern const char js_caller_str[];
+extern const char js_class_prototype_str[];
+extern const char js_close_str[];
+extern const char js_constructor_str[];
+extern const char js_count_str[];
+extern const char js_etago_str[];
+extern const char js_each_str[];
+extern const char js_eval_str[];
+extern const char js_fileName_str[];
+extern const char js_get_str[];
+extern const char js_getter_str[];
+extern const char js_index_str[];
+extern const char js_input_str[];
+extern const char js_iterator_str[];
+extern const char js_length_str[];
+extern const char js_lineNumber_str[];
+extern const char js_message_str[];
+extern const char js_name_str[];
+extern const char js_namespace_str[];
+extern const char js_next_str[];
+extern const char js_noSuchMethod_str[];
+extern const char js_object_str[];
+extern const char js_parent_str[];
+extern const char js_proto_str[];
+extern const char js_ptagc_str[];
+extern const char js_qualifier_str[];
+extern const char js_send_str[];
+extern const char js_setter_str[];
+extern const char js_set_str[];
+extern const char js_space_str[];
+extern const char js_stack_str[];
+extern const char js_stago_str[];
+extern const char js_star_str[];
+extern const char js_starQualifier_str[];
+extern const char js_tagc_str[];
+extern const char js_toSource_str[];
+extern const char js_toString_str[];
+extern const char js_toLocaleString_str[];
+extern const char js_undefined_str[];
+extern const char js_valueOf_str[];
+extern const char js_toJSON_str[];
+extern const char js_xml_str[];
+
+#ifdef NARCISSUS
+extern const char js___call___str[];
+extern const char js___construct___str[];
+extern const char js___hasInstance___str[];
+extern const char js_ExecutionContext_str[];
+extern const char js_current_str[];
+#endif
+
+/*
+ * Initialize atom state. Return true on success, false on failure to allocate
+ * memory. The caller must zero rt->atomState before calling this function and
+ * only call it after js_InitGC successfully returns.
+ */
+extern JSBool
+js_InitAtomState(JSRuntime *rt);
+
+/*
+ * Free and clear atom state including any interned string atoms. This
+ * function must be called before js_FinishGC.
+ */
+extern void
+js_FinishAtomState(JSRuntime *rt);
+
+/*
+ * Atom tracing and garbage collection hooks.
+ */
+
+extern void
+js_TraceAtomState(JSTracer *trc, JSBool allAtoms);
+
+extern void
+js_SweepAtomState(JSContext *cx);
+
+extern JSBool
+js_InitCommonAtoms(JSContext *cx);
+
+extern void
+js_FinishCommonAtoms(JSContext *cx);
+
+/*
+ * Find or create the atom for a double value. Return null on failure to
+ * allocate memory.
+ */
+extern JSAtom *
+js_AtomizeDouble(JSContext *cx, jsdouble d);
+
+/*
+ * Find or create the atom for a string. Return null on failure to allocate
+ * memory.
+ */
+extern JSAtom *
+js_AtomizeString(JSContext *cx, JSString *str, uintN flags);
+
+extern JSAtom *
+js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags);
+
+extern JSAtom *
+js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags);
+
+/*
+ * Return an existing atom for the given char array or null if the char
+ * sequence is currently not atomized.
+ */
+extern JSAtom *
+js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
+
+/*
+ * This variant handles all primitive values.
+ */
+JSBool
+js_AtomizePrimitiveValue(JSContext *cx, jsval v, JSAtom **atomp);
+
+/*
+ * Convert v to an atomized string and wrap it as an id.
+ */
+extern JSBool
+js_ValueToStringId(JSContext *cx, jsval v, jsid *idp);
+
+#ifdef DEBUG
+
+extern JS_FRIEND_API(void)
+js_DumpAtoms(JSContext *cx, FILE *fp);
+
+#endif
+
+/*
+ * Assign atom an index and insert it on al.
+ */
+extern JSAtomListElement *
+js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al);
+
+/*
+ * For all unmapped atoms recorded in al, add a mapping from the atom's index
+ * to its address. map->length must already be set to the number of atoms in
+ * the list and map->vector must point to pre-allocated memory.
+ */
+extern void
+js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al);
+
+JS_END_EXTERN_C
+
+#endif /* jsatom_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbit.h b/tools/node_modules/expresso/deps/jscoverage/js/jsbit.h
new file mode 100644
index 0000000..f54199b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbit.h
@@ -0,0 +1,253 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsbit_h___
+#define jsbit_h___
+
+#include "jstypes.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+** A jsbitmap_t is a long integer that can be used for bitmaps
+*/
+typedef JSUword jsbitmap_t; /* NSPR name, a la Unix system types */
+typedef jsbitmap_t jsbitmap; /* JS-style scalar typedef name */
+
+#define JS_BITMAP_SIZE(bits) (JS_HOWMANY(bits, JS_BITS_PER_WORD) * \
+ sizeof(jsbitmap))
+
+#define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] & \
+ ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
+#define JS_SET_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |= \
+ ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
+#define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= \
+ ~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
+
+/*
+** Compute the log of the least power of 2 greater than or equal to n
+*/
+extern JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 i);
+
+/*
+** Compute the log of the greatest power of 2 less than or equal to n
+*/
+extern JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 i);
+
+/*
+ * Replace bit-scanning code sequences with CPU-specific instructions to
+ * speedup calculations of ceiling/floor log2.
+ *
+ * With GCC 3.4 or later we can use __builtin_clz for that, see bug 327129.
+ *
+ * SWS: Added MSVC intrinsic bitscan support. See bugs 349364 and 356856.
+ */
+#if defined(_WIN32) && (_MSC_VER >= 1300) && defined(_M_IX86)
+
+unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask);
+unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask);
+# pragma intrinsic(_BitScanForward,_BitScanReverse)
+
+__forceinline static int
+__BitScanForward32(unsigned int val)
+{
+ unsigned long idx;
+
+ _BitScanForward(&idx, (unsigned long)val);
+ return (int)idx;
+}
+__forceinline static int
+__BitScanReverse32(unsigned int val)
+{
+ unsigned long idx;
+
+ _BitScanReverse(&idx, (unsigned long)val);
+ return (int)(31-idx);
+}
+# define js_bitscan_ctz32(val) __BitScanForward32(val)
+# define js_bitscan_clz32(val) __BitScanReverse32(val)
+# define JS_HAS_BUILTIN_BITSCAN32
+
+#elif (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+
+# define js_bitscan_ctz32(val) __builtin_ctz(val)
+# define js_bitscan_clz32(val) __builtin_clz(val)
+# define JS_HAS_BUILTIN_BITSCAN32
+# if (JS_BYTES_PER_WORD == 8)
+# define js_bitscan_ctz64(val) __builtin_ctzll(val)
+# define js_bitscan_clz64(val) __builtin_clzll(val)
+# define JS_HAS_BUILTIN_BITSCAN64
+# endif
+
+#endif
+
+/*
+** Macro version of JS_CeilingLog2: Compute the log of the least power of
+** 2 greater than or equal to _n. The result is returned in _log2.
+*/
+#ifdef JS_HAS_BUILTIN_BITSCAN32
+/*
+ * Use intrinsic function or count-leading-zeros to calculate ceil(log2(_n)).
+ * The macro checks for "n <= 1" and not "n != 0" as js_bitscan_clz32(0) is
+ * undefined.
+ */
+# define JS_CEILING_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JS_STATIC_ASSERT(sizeof(unsigned int) == sizeof(JSUint32)); \
+ unsigned int j_ = (unsigned int)(_n); \
+ (_log2) = (j_ <= 1 ? 0 : 32 - js_bitscan_clz32(j_ - 1)); \
+ JS_END_MACRO
+#else
+# define JS_CEILING_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JSUint32 j_ = (JSUint32)(_n); \
+ (_log2) = 0; \
+ if ((j_) & ((j_)-1)) \
+ (_log2) += 1; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1; \
+ JS_END_MACRO
+#endif
+
+/*
+** Macro version of JS_FloorLog2: Compute the log of the greatest power of
+** 2 less than or equal to _n. The result is returned in _log2.
+**
+** This is equivalent to finding the highest set bit in the word.
+*/
+#ifdef JS_HAS_BUILTIN_BITSCAN32
+/*
+ * Use js_bitscan_clz32 or count-leading-zeros to calculate floor(log2(_n)).
+ * Since js_bitscan_clz32(0) is undefined, the macro set the loweset bit to 1
+ * to ensure 0 result when _n == 0.
+ */
+# define JS_FLOOR_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JS_STATIC_ASSERT(sizeof(unsigned int) == sizeof(JSUint32)); \
+ (_log2) = 31 - js_bitscan_clz32(((unsigned int)(_n)) | 1); \
+ JS_END_MACRO
+#else
+# define JS_FLOOR_LOG2(_log2,_n) \
+ JS_BEGIN_MACRO \
+ JSUint32 j_ = (JSUint32)(_n); \
+ (_log2) = 0; \
+ if ((j_) >> 16) \
+ (_log2) += 16, (j_) >>= 16; \
+ if ((j_) >> 8) \
+ (_log2) += 8, (j_) >>= 8; \
+ if ((j_) >> 4) \
+ (_log2) += 4, (j_) >>= 4; \
+ if ((j_) >> 2) \
+ (_log2) += 2, (j_) >>= 2; \
+ if ((j_) >> 1) \
+ (_log2) += 1; \
+ JS_END_MACRO
+#endif
+
+/*
+ * Internal function.
+ * Compute the log of the least power of 2 greater than or equal to n.
+ * This is a version of JS_CeilingLog2 that operates on jsuword with
+ * CPU-dependant size.
+ */
+#define JS_CEILING_LOG2W(n) ((n) <= 1 ? 0 : 1 + JS_FLOOR_LOG2W((n) - 1))
+
+/*
+ * Internal function.
+ * Compute the log of the greatest power of 2 less than or equal to n.
+ * This is a version of JS_FloorLog2 that operates on jsuword with
+ * CPU-dependant size and requires that n != 0.
+ */
+#define JS_FLOOR_LOG2W(n) (JS_ASSERT((n) != 0), js_FloorLog2wImpl(n))
+
+#if JS_BYTES_PER_WORD == 4
+
+# ifdef JS_HAS_BUILTIN_BITSCAN32
+JS_STATIC_ASSERT(sizeof(unsigned) == sizeof(JSUword));
+# define js_FloorLog2wImpl(n) \
+ ((JSUword)(JS_BITS_PER_WORD - 1 - js_bitscan_clz32(n)))
+# else
+# define js_FloorLog2wImpl(n) ((JSUword)JS_FloorLog2(n))
+#endif
+
+#elif JS_BYTES_PER_WORD == 8
+
+# ifdef JS_HAS_BUILTIN_BITSCAN64
+JS_STATIC_ASSERT(sizeof(unsigned long long) == sizeof(JSUword));
+# define js_FloorLog2wImpl(n) \
+ ((JSUword)(JS_BITS_PER_WORD - 1 - js_bitscan_clz64(n)))
+# else
+extern JSUword js_FloorLog2wImpl(JSUword n);
+# endif
+
+#else
+
+# error "NOT SUPPORTED"
+
+#endif
+
+/*
+ * Macros for rotate left. There is no rotate operation in the C Language so
+ * the construct (a << 4) | (a >> 28) is used instead. Most compilers convert
+ * this to a rotate instruction but some versions of MSVC don't without a
+ * little help. To get MSVC to generate a rotate instruction, we have to use
+ * the _rotl intrinsic and use a pragma to make _rotl inline.
+ *
+ * MSVC in VS2005 will do an inline rotate instruction on the above construct.
+ */
+
+#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
+ defined(_M_X64))
+#include <stdlib.h>
+#pragma intrinsic(_rotl)
+#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
+#else
+#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
+#endif
+
+JS_END_EXTERN_C
+#endif /* jsbit_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp
new file mode 100644
index 0000000..9167fa1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.cpp
@@ -0,0 +1,182 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS boolean implementation.
+ */
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsstr.h"
+
+/* Check pseudo-booleans values. */
+JS_STATIC_ASSERT(JSVAL_VOID == JSVAL_TRUE + JSVAL_ALIGN);
+JS_STATIC_ASSERT(JSVAL_HOLE == JSVAL_VOID + JSVAL_ALIGN);
+JS_STATIC_ASSERT(JSVAL_ARETURN == JSVAL_HOLE + JSVAL_ALIGN);
+
+JSClass js_BooleanClass = {
+ "Boolean",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Boolean),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#if JS_HAS_TOSOURCE
+#include "jsprf.h"
+
+static JSBool
+bool_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ char buf[32];
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ JS_snprintf(buf, sizeof buf, "(new %s(%s))",
+ js_BooleanClass.name,
+ JS_BOOLEAN_STR(JSVAL_TO_BOOLEAN(v)));
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+bool_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ JSAtom *atom;
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_BooleanClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ atom = cx->runtime->atomState.booleanAtoms[JSVAL_TO_BOOLEAN(v) ? 1 : 0];
+ str = ATOM_TO_STRING(atom);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+bool_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_GetPrimitiveThis(cx, vp, &js_BooleanClass, vp);
+}
+
+static JSFunctionSpec boolean_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, bool_toSource, 0, JSFUN_THISP_BOOLEAN),
+#endif
+ JS_FN(js_toString_str, bool_toString, 0, JSFUN_THISP_BOOLEAN),
+ JS_FN(js_valueOf_str, bool_valueOf, 0, JSFUN_THISP_BOOLEAN),
+ JS_FN(js_toJSON_str, bool_valueOf, 0, JSFUN_THISP_BOOLEAN),
+ JS_FS_END
+};
+
+static JSBool
+Boolean(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval bval;
+
+ bval = (argc != 0)
+ ? BOOLEAN_TO_JSVAL(js_ValueToBoolean(argv[0]))
+ : JSVAL_FALSE;
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ *rval = bval;
+ return JS_TRUE;
+ }
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, bval);
+ return JS_TRUE;
+}
+
+JSObject *
+js_InitBooleanClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_BooleanClass, Boolean, 1,
+ NULL, boolean_methods, NULL, NULL);
+ if (!proto)
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_FALSE);
+ return proto;
+}
+
+JSString *
+js_BooleanToString(JSContext *cx, JSBool b)
+{
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
+}
+
+JSBool
+js_ValueToBoolean(jsval v)
+{
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ return JS_FALSE;
+ if (JSVAL_IS_OBJECT(v))
+ return JS_TRUE;
+ if (JSVAL_IS_STRING(v))
+ return JSSTRING_LENGTH(JSVAL_TO_STRING(v)) != 0;
+ if (JSVAL_IS_INT(v))
+ return JSVAL_TO_INT(v) != 0;
+ if (JSVAL_IS_DOUBLE(v)) {
+ jsdouble d;
+
+ d = *JSVAL_TO_DOUBLE(v);
+ return !JSDOUBLE_IS_NaN(d) && d != 0;
+ }
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ return JSVAL_TO_BOOLEAN(v);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbool.h b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.h
new file mode 100644
index 0000000..f76de2e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbool.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsbool_h___
+#define jsbool_h___
+/*
+ * JS boolean interface.
+ */
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Pseudo-booleans, not visible to script but used internally by the engine.
+ *
+ * JSVAL_HOLE is a useful value for identifying a hole in an array. It's also
+ * used in the interpreter to represent "no exception pending". In general it
+ * can be used to represent "no value".
+ *
+ * JSVAL_ARETURN is used to throw asynchronous return for generator.close().
+ *
+ * NB: BOOLEAN_TO_JSVAL(2) is JSVAL_VOID (see jsapi.h).
+ */
+#define JSVAL_HOLE BOOLEAN_TO_JSVAL(3)
+#define JSVAL_ARETURN BOOLEAN_TO_JSVAL(4)
+
+extern JSClass js_BooleanClass;
+
+extern JSObject *
+js_InitBooleanClass(JSContext *cx, JSObject *obj);
+
+extern JSString *
+js_BooleanToString(JSContext *cx, JSBool b);
+
+extern JSBool
+js_ValueToBoolean(jsval v);
+
+JS_END_EXTERN_C
+
+#endif /* jsbool_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp
new file mode 100644
index 0000000..8a21edb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.cpp
@@ -0,0 +1,497 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Andreas Gal <gal@mozilla.com>
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ * Mike Shaver <shaver@mozilla.org>
+ * David Anderson <danderson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include <math.h>
+
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsgc.h"
+#include "jsiter.h"
+#include "jslibmath.h"
+#include "jsmath.h"
+#include "jsnum.h"
+#include "prmjtime.h"
+#include "jsdate.h"
+#include "jsscope.h"
+#include "jsstr.h"
+#include "jsbuiltins.h"
+#include "jstracer.h"
+
+using namespace avmplus;
+using namespace nanojit;
+
+extern jsdouble js_NaN;
+
+/*
+ * NB: bool FASTCALL is not compatible with Nanojit's calling convention usage.
+ * Do not use bool FASTCALL, use JSBool only!
+ */
+
+jsdouble FASTCALL
+js_dmod(jsdouble a, jsdouble b)
+{
+ if (b == 0.0) {
+ jsdpun u;
+ u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
+ u.s.lo = 0xffffffff;
+ return u.d;
+ }
+ jsdouble r;
+#ifdef XP_WIN
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
+ if (JSDOUBLE_IS_FINITE(a) && JSDOUBLE_IS_INFINITE(b))
+ r = a;
+ else
+#endif
+ r = fmod(a, b);
+ return r;
+}
+
+int32 FASTCALL
+js_imod(int32 a, int32 b)
+{
+ if (a < 0 || b <= 0)
+ return -1;
+ int r = a % b;
+ return r;
+}
+
+/* The following boxing/unboxing primitives we can't emit inline because
+ they either interact with the GC and depend on Spidermonkey's 32-bit
+ integer representation. */
+
+jsval FASTCALL
+js_BoxDouble(JSContext* cx, jsdouble d)
+{
+ int32 i;
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
+ return INT_TO_JSVAL(i);
+ JS_ASSERT(JS_ON_TRACE(cx));
+ jsval v; /* not rooted but ok here because we know GC won't run */
+ if (!js_NewDoubleInRootedValue(cx, d, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+jsval FASTCALL
+js_BoxInt32(JSContext* cx, int32 i)
+{
+ if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
+ return INT_TO_JSVAL(i);
+ JS_ASSERT(JS_ON_TRACE(cx));
+ jsval v; /* not rooted but ok here because we know GC won't run */
+ jsdouble d = (jsdouble)i;
+ if (!js_NewDoubleInRootedValue(cx, d, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+jsdouble FASTCALL
+js_UnboxDouble(jsval v)
+{
+ if (JS_LIKELY(JSVAL_IS_INT(v)))
+ return (jsdouble)JSVAL_TO_INT(v);
+ return *JSVAL_TO_DOUBLE(v);
+}
+
+int32 FASTCALL
+js_UnboxInt32(jsval v)
+{
+ if (JS_LIKELY(JSVAL_IS_INT(v)))
+ return JSVAL_TO_INT(v);
+ return js_DoubleToECMAInt32(*JSVAL_TO_DOUBLE(v));
+}
+
+int32 FASTCALL
+js_DoubleToInt32(jsdouble d)
+{
+ return js_DoubleToECMAInt32(d);
+}
+
+uint32 FASTCALL
+js_DoubleToUint32(jsdouble d)
+{
+ return js_DoubleToECMAUint32(d);
+}
+
+jsdouble FASTCALL
+js_StringToNumber(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if ((!js_strtod(cx, bp, end, &ep, &d) ||
+ js_SkipWhiteSpace(ep, end) != end) &&
+ (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
+ js_SkipWhiteSpace(ep, end) != end)) {
+ return js_NaN;
+ }
+ return d;
+}
+
+int32 FASTCALL
+js_StringToInt32(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtod(cx, bp, end, &ep, &d) || js_SkipWhiteSpace(ep, end) != end)
+ return 0;
+ return js_DoubleToECMAInt32(d);
+}
+
+static inline JSBool
+js_Int32ToId(JSContext* cx, int32 index, jsid* id)
+{
+ if (index <= JSVAL_INT_MAX) {
+ *id = INT_TO_JSID(index);
+ return JS_TRUE;
+ }
+ JSString* str = js_NumberToString(cx, index);
+ if (!str)
+ return JS_FALSE;
+ return js_ValueToStringId(cx, STRING_TO_JSVAL(str), id);
+}
+
+jsval FASTCALL
+js_Any_getprop(JSContext* cx, JSObject* obj, JSString* idstr)
+{
+ jsval v;
+ jsid id;
+
+ if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+ return JSVAL_ERROR_COOKIE;
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+JSBool FASTCALL
+js_Any_setprop(JSContext* cx, JSObject* obj, JSString* idstr, jsval v)
+{
+ jsid id;
+ if (!js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+ return JS_FALSE;
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+jsval FASTCALL
+js_Any_getelem(JSContext* cx, JSObject* obj, int32 index)
+{
+ jsval v;
+ jsid id;
+ if (!js_Int32ToId(cx, index, &id))
+ return JSVAL_ERROR_COOKIE;
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+JSBool FASTCALL
+js_Any_setelem(JSContext* cx, JSObject* obj, int32 index, jsval v)
+{
+ jsid id;
+ if (!js_Int32ToId(cx, index, &id))
+ return JSVAL_ERROR_COOKIE;
+ return OBJ_SET_PROPERTY(cx, obj, id, &v);
+}
+
+JSObject* FASTCALL
+js_FastValueToIterator(JSContext* cx, jsuint flags, jsval v)
+{
+ if (!js_ValueToIterator(cx, flags, &v))
+ return NULL;
+ return JSVAL_TO_OBJECT(v);
+}
+
+jsval FASTCALL
+js_FastCallIteratorNext(JSContext* cx, JSObject* iterobj)
+{
+ jsval v;
+ if (!js_CallIteratorNext(cx, iterobj, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+SideExit* FASTCALL
+js_CallTree(InterpState* state, Fragment* f)
+{
+ union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
+
+ u.code = f->code();
+ JS_ASSERT(u.code);
+
+ GuardRecord* rec;
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+ SIMULATE_FASTCALL(rec, state, NULL, u.func);
+#else
+ rec = u.func(state, NULL);
+#endif
+ VMSideExit* lr = (VMSideExit*)rec->exit;
+
+ if (lr->exitType == NESTED_EXIT) {
+ /* This only occurs once a tree call guard mismatches and we unwind the tree call stack.
+ We store the first (innermost) tree call guard in state and we will try to grow
+ the outer tree the failing call was in starting at that guard. */
+ if (!state->lastTreeCallGuard) {
+ state->lastTreeCallGuard = lr;
+ FrameInfo* rp = (FrameInfo*)state->rp;
+ state->rpAtLastTreeCall = rp + lr->calldepth;
+ }
+ } else {
+ /* If the tree exits on a regular (non-nested) guard, keep updating lastTreeExitGuard
+ with that guard. If we mismatch on a tree call guard, this will contain the last
+ non-nested guard we encountered, which is the innermost loop or branch guard. */
+ state->lastTreeExitGuard = lr;
+ }
+
+ return lr;
+}
+
+JSObject* FASTCALL
+js_FastNewObject(JSContext* cx, JSObject* ctor)
+{
+ JS_ASSERT(HAS_FUNCTION_CLASS(ctor));
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
+ JSClass* clasp = (FUN_INTERPRETED(fun) || (fun->flags & JSFUN_TRACEABLE))
+ ? &js_ObjectClass
+ : FUN_CLASP(fun);
+ JS_ASSERT(clasp != &js_ArrayClass);
+
+ JS_LOCK_OBJ(cx, ctor);
+ JSScope *scope = OBJ_SCOPE(ctor);
+ JS_ASSERT(scope->object == ctor);
+ JSAtom* atom = cx->runtime->atomState.classPrototypeAtom;
+
+ JSScopeProperty *sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, scope));
+ jsval v = LOCKED_OBJ_GET_SLOT(ctor, sprop->slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ JSObject* proto;
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ if (!js_GetClassPrototype(cx, JSVAL_TO_OBJECT(ctor->fslots[JSSLOT_PARENT]),
+ INT_TO_JSID(JSProto_Object), &proto)) {
+ return NULL;
+ }
+ } else {
+ proto = JSVAL_TO_OBJECT(v);
+ }
+
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
+ if (!obj)
+ return NULL;
+
+ obj->classword = jsuword(clasp);
+ obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
+ obj->fslots[JSSLOT_PARENT] = ctor->fslots[JSSLOT_PARENT];
+ for (unsigned i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+ obj->map = js_HoldObjectMap(cx, proto->map);
+ obj->dslots = NULL;
+ return obj;
+}
+
+JSBool FASTCALL
+js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
+{
+ JSScopeProperty* sprop2 = NULL; // initialize early to make MSVC happy
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_ASSERT(SPROP_HAS_STUB_SETTER(sprop));
+
+ JS_LOCK_OBJ(cx, obj);
+ JSScope* scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ JS_ASSERT(!SCOPE_HAS_PROPERTY(scope, sprop));
+ } else {
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ }
+
+ uint32 slot = sprop->slot;
+ if (!scope->table && sprop->parent == scope->lastProp && slot == scope->map.freeslot) {
+ if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
+ JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->map.freeslot)));
+ ++scope->map.freeslot;
+ } else {
+ if (!js_AllocSlot(cx, obj, &slot)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+
+ if (slot != sprop->slot)
+ goto slot_changed;
+ }
+
+ SCOPE_EXTEND_SHAPE(cx, scope, sprop);
+ ++scope->entryCount;
+ scope->lastProp = sprop;
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+ }
+
+ sprop2 = js_AddScopeProperty(cx, scope, sprop->id,
+ sprop->getter, sprop->setter, SPROP_INVALID_SLOT,
+ sprop->attrs, sprop->flags, sprop->shortid);
+ if (sprop2 == sprop) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+ }
+ slot = sprop2->slot;
+
+ slot_changed:
+ js_FreeSlot(cx, obj, slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+}
+
+JSBool FASTCALL
+js_HasNamedProperty(JSContext* cx, JSObject* obj, JSString* idstr)
+{
+ jsid id;
+ if (!obj || !js_ValueToStringId(cx, STRING_TO_JSVAL(idstr), &id))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+
+ JSObject* obj2;
+ JSProperty* prop;
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return prop != NULL;
+}
+
+JSBool FASTCALL
+js_HasNamedPropertyInt32(JSContext* cx, JSObject* obj, int32 index)
+{
+ jsid id;
+ if (!obj || !js_Int32ToId(cx, index, &id))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+
+ JSObject* obj2;
+ JSProperty* prop;
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return prop != NULL;
+}
+
+jsval FASTCALL
+js_CallGetter(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
+{
+ JS_ASSERT(!SPROP_HAS_STUB_GETTER(sprop));
+ jsval v;
+ if (!SPROP_GET(cx, sprop, obj, obj, &v))
+ return JSVAL_ERROR_COOKIE;
+ return v;
+}
+
+JSString* FASTCALL
+js_TypeOfObject(JSContext* cx, JSObject* obj)
+{
+ JSType type = JS_TypeOfValue(cx, OBJECT_TO_JSVAL(obj));
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
+}
+
+JSString* FASTCALL
+js_TypeOfBoolean(JSContext* cx, int32 unboxed)
+{
+ jsval boxed = BOOLEAN_TO_JSVAL(unboxed);
+ JS_ASSERT(JSVAL_IS_VOID(boxed) || JSVAL_IS_BOOLEAN(boxed));
+ JSType type = JS_TypeOfValue(cx, boxed);
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[type]);
+}
+
+jsdouble FASTCALL
+js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed)
+{
+ if (unboxed == JSVAL_TO_BOOLEAN(JSVAL_VOID))
+ return js_NaN;
+ return unboxed;
+}
+
+JSString* FASTCALL
+js_BooleanOrUndefinedToString(JSContext *cx, int32 unboxed)
+{
+ JS_ASSERT(uint32(unboxed) <= 2);
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[unboxed]);
+}
+
+JSString* FASTCALL
+js_ObjectToString(JSContext* cx, JSObject* obj)
+{
+ if (!obj)
+ return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+ jsval v;
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+JSObject* FASTCALL
+js_Arguments(JSContext* cx)
+{
+ return NULL;
+}
+
+#define BUILTIN1 JS_DEFINE_CALLINFO_1
+#define BUILTIN2 JS_DEFINE_CALLINFO_2
+#define BUILTIN3 JS_DEFINE_CALLINFO_3
+#define BUILTIN4 JS_DEFINE_CALLINFO_4
+#define BUILTIN5 JS_DEFINE_CALLINFO_5
+#include "builtins.tbl"
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h
new file mode 100644
index 0000000..366d24f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsbuiltins.h
@@ -0,0 +1,374 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ *
+ * Contributor(s):
+ * Jason Orendorff <jorendorff@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsbuiltins_h___
+#define jsbuiltins_h___
+
+#ifdef JS_TRACER
+
+#include "nanojit/nanojit.h"
+#include "jstracer.h"
+
+enum JSTNErrType { INFALLIBLE, FAIL_NULL, FAIL_NEG, FAIL_VOID, FAIL_JSVAL };
+enum { JSTN_ERRTYPE_MASK = 7, JSTN_MORE = 8 };
+
+#define JSTN_ERRTYPE(jstn) ((jstn)->flags & JSTN_ERRTYPE_MASK)
+
+/*
+ * |prefix| and |argtypes| declare what arguments should be passed to the
+ * native function. |prefix| can contain the following characters:
+ *
+ * 'C': a JSContext* argument
+ * 'T': |this| as a JSObject* argument (bails if |this| is not an object)
+ * 'S': |this| as a JSString* argument (bails if |this| is not a string)
+ * 'R': a JSRuntime* argument
+ * 'P': the pc as a jsbytecode*
+ * 'D': |this| as a number (jsdouble)
+ * 'f': the function being called, as a JSObject*
+ * 'p': the .prototype of the function, as a JSObject*
+ *
+ * The corresponding things will get passed as arguments to the builtin in
+ * reverse order (so TC means JSContext* as the first arg, and the
+ * JSObject* for |this| as the second arg).
+ *
+ * |argtypes| can contain the following characters:
+ * 'd': a number (double) argument
+ * 'i': an integer argument
+ * 's': a JSString* argument
+ * 'o': a JSObject* argument
+ * 'r': a JSObject* argument that is of class js_RegExpClass
+ * 'f': a JSObject* argument that is of class js_FunctionClass
+ * 'v': a jsval argument (boxing whatever value is actually being passed in)
+ */
+struct JSTraceableNative {
+ JSFastNative native;
+ const nanojit::CallInfo *builtin;
+ const char *prefix;
+ const char *argtypes;
+ uintN flags; /* JSTN_MORE | JSTNErrType */
+};
+
+/*
+ * We use a magic boxed pointer value to represent error conditions that
+ * trigger a side exit. The address is so low that it should never be actually
+ * in use. If it is, a performance regression occurs, not an actual runtime
+ * error.
+ */
+#define JSVAL_ERROR_COOKIE OBJECT_TO_JSVAL((void*)0x10)
+
+/* Macros used by JS_DEFINE_CALLINFOn. */
+#ifdef DEBUG
+#define _JS_CI_NAME(op) ,#op
+#else
+#define _JS_CI_NAME(op)
+#endif
+
+#define _JS_I32_ARGSIZE nanojit::ARGSIZE_LO
+#define _JS_I32_RETSIZE nanojit::ARGSIZE_LO
+#define _JS_F64_ARGSIZE nanojit::ARGSIZE_F
+#define _JS_F64_RETSIZE nanojit::ARGSIZE_F
+#define _JS_PTR_ARGSIZE nanojit::ARGSIZE_LO
+#if defined AVMPLUS_64BIT
+# define _JS_PTR_RETSIZE nanojit::ARGSIZE_Q
+#else
+# define _JS_PTR_RETSIZE nanojit::ARGSIZE_LO
+#endif
+
+/*
+ * Supported types for builtin functions.
+ *
+ * Types with -- for the two string fields are not permitted as argument types
+ * in JS_DEFINE_TRCINFO.
+ *
+ * If a traceable native can fail, the values that indicate failure are part of
+ * the return type:
+ * JSVAL_FAIL: JSVAL_ERROR_COOKIE
+ * BOOL_FAIL: JSVAL_TO_BOOLEAN(JSVAL_VOID)
+ * INT32_FAIL: any negative value
+ * STRING_FAIL: NULL
+ * OBJECT_FAIL_NULL: NULL
+ * OBJECT_FAIL_VOID: JSVAL_TO_OBJECT(JSVAL_VOID)
+ * (NULL means the function successfully returned JS null.)
+ *
+ * Special builtins known to the tracer can have their own idiosyncratic
+ * error codes.
+ *
+ * When a traceable native returns a value indicating failure, we fall off
+ * trace. If an exception is pending, it is thrown; otherwise, we assume the
+ * builtin had no side effects and retry the current bytecode in the
+ * interpreter.
+ *
+ * So a builtin must not return a value indicating failure after causing side
+ * effects (such as reporting an error), without setting an exception pending.
+ * The operation would be retried, despite the first attempt's observable
+ * effects.
+ */
+#define _JS_CTYPE(ctype, size, pch, ach, flags) (ctype, size, pch, ach, flags)
+#define _JS_CTYPE_CONTEXT _JS_CTYPE(JSContext *, _JS_PTR,"C", "", INFALLIBLE)
+#define _JS_CTYPE_RUNTIME _JS_CTYPE(JSRuntime *, _JS_PTR,"R", "", INFALLIBLE)
+#define _JS_CTYPE_THIS _JS_CTYPE(JSObject *, _JS_PTR,"T", "", INFALLIBLE)
+#define _JS_CTYPE_THIS_DOUBLE _JS_CTYPE(jsdouble, _JS_F64,"D", "", INFALLIBLE)
+#define _JS_CTYPE_THIS_STRING _JS_CTYPE(JSString *, _JS_PTR,"S", "", INFALLIBLE)
+#define _JS_CTYPE_PC _JS_CTYPE(jsbytecode *, _JS_PTR,"P", "", INFALLIBLE)
+#define _JS_CTYPE_JSVAL _JS_CTYPE(jsval, _JS_PTR, "","v", INFALLIBLE)
+#define _JS_CTYPE_JSVAL_FAIL _JS_CTYPE(jsval, _JS_PTR, --, --, FAIL_JSVAL)
+#define _JS_CTYPE_BOOL _JS_CTYPE(JSBool, _JS_I32, "","i", INFALLIBLE)
+#define _JS_CTYPE_BOOL_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_VOID)
+#define _JS_CTYPE_INT32 _JS_CTYPE(int32, _JS_I32, "","i", INFALLIBLE)
+#define _JS_CTYPE_INT32_FAIL _JS_CTYPE(int32, _JS_I32, --, --, FAIL_NEG)
+#define _JS_CTYPE_UINT32 _JS_CTYPE(uint32, _JS_I32, --, --, INFALLIBLE)
+#define _JS_CTYPE_DOUBLE _JS_CTYPE(jsdouble, _JS_F64, "","d", INFALLIBLE)
+#define _JS_CTYPE_STRING _JS_CTYPE(JSString *, _JS_PTR, "","s", INFALLIBLE)
+#define _JS_CTYPE_STRING_FAIL _JS_CTYPE(JSString *, _JS_PTR, --, --, FAIL_NULL)
+#define _JS_CTYPE_OBJECT _JS_CTYPE(JSObject *, _JS_PTR, "","o", INFALLIBLE)
+#define _JS_CTYPE_OBJECT_FAIL_NULL _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_NULL)
+#define _JS_CTYPE_OBJECT_FAIL_VOID _JS_CTYPE(JSObject *, _JS_PTR, --, --, FAIL_VOID)
+#define _JS_CTYPE_REGEXP _JS_CTYPE(JSObject *, _JS_PTR, "","r", INFALLIBLE)
+#define _JS_CTYPE_SCOPEPROP _JS_CTYPE(JSScopeProperty *, _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_SIDEEXIT _JS_CTYPE(SideExit *, _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE)
+#define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
+
+#define _JS_EXPAND(tokens) tokens
+
+#define _JS_CTYPE_TYPE2(t,s,p,a,f) t
+#define _JS_CTYPE_TYPE(tyname) _JS_EXPAND(_JS_CTYPE_TYPE2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_RETSIZE2(t,s,p,a,f) s##_RETSIZE
+#define _JS_CTYPE_RETSIZE(tyname) _JS_EXPAND(_JS_CTYPE_RETSIZE2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_ARGSIZE2(t,s,p,a,f) s##_ARGSIZE
+#define _JS_CTYPE_ARGSIZE(tyname) _JS_EXPAND(_JS_CTYPE_ARGSIZE2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_PCH2(t,s,p,a,f) p
+#define _JS_CTYPE_PCH(tyname) _JS_EXPAND(_JS_CTYPE_PCH2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_ACH2(t,s,p,a,f) a
+#define _JS_CTYPE_ACH(tyname) _JS_EXPAND(_JS_CTYPE_ACH2 _JS_CTYPE_##tyname)
+#define _JS_CTYPE_FLAGS2(t,s,p,a,f) f
+#define _JS_CTYPE_FLAGS(tyname) _JS_EXPAND(_JS_CTYPE_FLAGS2 _JS_CTYPE_##tyname)
+
+#define _JS_static_TN(t) static t
+#define _JS_static_CI static
+#define _JS_extern_TN(t) extern t
+#define _JS_extern_CI
+#define _JS_FRIEND_TN(t) extern JS_FRIEND_API(t)
+#define _JS_FRIEND_CI
+#define _JS_TN_LINKAGE(linkage, t) _JS_##linkage##_TN(t)
+#define _JS_CI_LINKAGE(linkage) _JS_##linkage##_CI
+
+#define _JS_CALLINFO(name) name##_ci
+
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \
+ _JS_TN_LINKAGE(linkage, crtype) name cargtypes; \
+ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
+ { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_CDECL _JS_CI_NAME(name) };
+#else
+#define _JS_DEFINE_CALLINFO(linkage, name, crtype, cargtypes, argtypes, cse, fold) \
+ _JS_TN_LINKAGE(linkage, crtype) FASTCALL name cargtypes; \
+ _JS_CI_LINKAGE(linkage) const nanojit::CallInfo _JS_CALLINFO(name) = \
+ { (intptr_t) &name, argtypes, cse, fold, nanojit::ABI_FASTCALL _JS_CI_NAME(name) };
+#endif
+
+/*
+ * Declare a C function named <op> and a CallInfo struct named <op>_callinfo so the
+ * tracer can call it. |linkage| controls the visibility of both the function
+ * and the CallInfo global. It can be extern, static, or FRIEND, which
+ * specifies JS_FRIEND_API linkage for the function.
+ */
+#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), (_JS_CTYPE_TYPE(at0)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 2) | _JS_CTYPE_RETSIZE(rt), cse, fold)
+#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 4) | (_JS_CTYPE_ARGSIZE(at1) << 2) | \
+ _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 6) | (_JS_CTYPE_ARGSIZE(at1) << 4) | \
+ (_JS_CTYPE_ARGSIZE(at2) << 2) | _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \
+ _JS_CTYPE_TYPE(at3)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 8) | (_JS_CTYPE_ARGSIZE(at1) << 6) | \
+ (_JS_CTYPE_ARGSIZE(at2) << 4) | (_JS_CTYPE_ARGSIZE(at3) << 2) | \
+ _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \
+ _JS_DEFINE_CALLINFO(linkage, op, _JS_CTYPE_TYPE(rt), \
+ (_JS_CTYPE_TYPE(at0), _JS_CTYPE_TYPE(at1), _JS_CTYPE_TYPE(at2), \
+ _JS_CTYPE_TYPE(at3), _JS_CTYPE_TYPE(at4)), \
+ (_JS_CTYPE_ARGSIZE(at0) << 10) | (_JS_CTYPE_ARGSIZE(at1) << 8) | \
+ (_JS_CTYPE_ARGSIZE(at2) << 6) | (_JS_CTYPE_ARGSIZE(at3) << 4) | \
+ (_JS_CTYPE_ARGSIZE(at4) << 2) | _JS_CTYPE_RETSIZE(rt), \
+ cse, fold)
+
+#define JS_DECLARE_CALLINFO(name) extern const nanojit::CallInfo _JS_CALLINFO(name);
+
+#define _JS_TN_INIT_HELPER_n(n, args) _JS_TN_INIT_HELPER_##n args
+
+#define _JS_TN_INIT_HELPER_1(linkage, rt, op, at0, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_2(linkage, rt, op, at0, at1, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_3(linkage, rt, op, at0, at1, at2, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_4(linkage, rt, op, at0, at1, at2, at3, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at3), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define _JS_TN_INIT_HELPER_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) \
+ &_JS_CALLINFO(op), \
+ _JS_CTYPE_PCH(at4) _JS_CTYPE_PCH(at3) _JS_CTYPE_PCH(at2) _JS_CTYPE_PCH(at1) \
+ _JS_CTYPE_PCH(at0), \
+ _JS_CTYPE_ACH(at0) _JS_CTYPE_ACH(at1) _JS_CTYPE_ACH(at2) _JS_CTYPE_ACH(at3) \
+ _JS_CTYPE_ACH(at4), \
+ _JS_CTYPE_FLAGS(rt)
+
+#define JS_DEFINE_TRCINFO_1(name, tn0) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 } \
+ };
+
+#define JS_DEFINE_TRCINFO_2(name, tn0, tn1) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ _JS_DEFINE_CALLINFO_n tn1 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn1 } \
+ };
+
+#define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ _JS_DEFINE_CALLINFO_n tn1 \
+ _JS_DEFINE_CALLINFO_n tn2 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn2 } \
+ };
+
+#define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3) \
+ _JS_DEFINE_CALLINFO_n tn0 \
+ _JS_DEFINE_CALLINFO_n tn1 \
+ _JS_DEFINE_CALLINFO_n tn2 \
+ _JS_DEFINE_CALLINFO_n tn3 \
+ JSTraceableNative name##_trcinfo[] = { \
+ { name, _JS_TN_INIT_HELPER_n tn0 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn1 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn2 | JSTN_MORE }, \
+ { name, _JS_TN_INIT_HELPER_n tn3 } \
+ };
+
+#define _JS_DEFINE_CALLINFO_n(n, args) JS_DEFINE_CALLINFO_##n args
+
+jsdouble FASTCALL
+js_StringToNumber(JSContext* cx, JSString* str);
+
+jsdouble FASTCALL
+js_BooleanOrUndefinedToNumber(JSContext* cx, int32 unboxed);
+
+#else
+
+#define JS_DEFINE_CALLINFO_1(linkage, rt, op, at0, cse, fold)
+#define JS_DEFINE_CALLINFO_2(linkage, rt, op, at0, at1, cse, fold)
+#define JS_DEFINE_CALLINFO_3(linkage, rt, op, at0, at1, at2, cse, fold)
+#define JS_DEFINE_CALLINFO_4(linkage, rt, op, at0, at1, at2, at3, cse, fold)
+#define JS_DEFINE_CALLINFO_5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold)
+#define JS_DECLARE_CALLINFO(name)
+#define JS_DEFINE_TRCINFO_1(name, tn0)
+#define JS_DEFINE_TRCINFO_2(name, tn0, tn1)
+#define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)
+#define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)
+
+#endif /* !JS_TRACER */
+
+/* Defined in jsarray.cpp */
+JS_DECLARE_CALLINFO(js_Array_dense_setelem)
+JS_DECLARE_CALLINFO(js_FastNewArray)
+JS_DECLARE_CALLINFO(js_Array_1int)
+JS_DECLARE_CALLINFO(js_Array_1str)
+JS_DECLARE_CALLINFO(js_Array_2obj)
+JS_DECLARE_CALLINFO(js_Array_3num)
+
+/* Defined in jsdate.cpp */
+JS_DECLARE_CALLINFO(js_FastNewDate)
+
+/* Defined in jsnum.cpp */
+JS_DECLARE_CALLINFO(js_NumberToString)
+
+/* Defined in jsstr.cpp */
+JS_DECLARE_CALLINFO(js_ConcatStrings)
+JS_DECLARE_CALLINFO(js_String_getelem)
+JS_DECLARE_CALLINFO(js_String_p_charCodeAt)
+JS_DECLARE_CALLINFO(js_EqualStrings)
+JS_DECLARE_CALLINFO(js_CompareStrings)
+
+/* Defined in jsbuiltins.cpp */
+#define BUILTIN1(linkage, rt, op, at0, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN2(linkage, rt, op, at0, at1, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN3(linkage, rt, op, at0, at1, at2, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN4(linkage, rt, op, at0, at1, at2, at3, cse, fold) JS_DECLARE_CALLINFO(op)
+#define BUILTIN5(linkage, rt, op, at0, at1, at2, at3, at4, cse, fold) JS_DECLARE_CALLINFO(op)
+#include "builtins.tbl"
+#undef BUILTIN
+#undef BUILTIN1
+#undef BUILTIN2
+#undef BUILTIN3
+#undef BUILTIN4
+#undef BUILTIN5
+
+#endif /* jsbuiltins_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsclist.h b/tools/node_modules/expresso/deps/jscoverage/js/jsclist.h
new file mode 100644
index 0000000..604ec0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsclist.h
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsclist_h___
+#define jsclist_h___
+
+#include "jstypes.h"
+
+/*
+** Circular linked list
+*/
+typedef struct JSCListStr {
+ struct JSCListStr *next;
+ struct JSCListStr *prev;
+} JSCList;
+
+/*
+** Insert element "_e" into the list, before "_l".
+*/
+#define JS_INSERT_BEFORE(_e,_l) \
+ JS_BEGIN_MACRO \
+ (_e)->next = (_l); \
+ (_e)->prev = (_l)->prev; \
+ (_l)->prev->next = (_e); \
+ (_l)->prev = (_e); \
+ JS_END_MACRO
+
+/*
+** Insert element "_e" into the list, after "_l".
+*/
+#define JS_INSERT_AFTER(_e,_l) \
+ JS_BEGIN_MACRO \
+ (_e)->next = (_l)->next; \
+ (_e)->prev = (_l); \
+ (_l)->next->prev = (_e); \
+ (_l)->next = (_e); \
+ JS_END_MACRO
+
+/*
+** Return the element following element "_e"
+*/
+#define JS_NEXT_LINK(_e) \
+ ((_e)->next)
+/*
+** Return the element preceding element "_e"
+*/
+#define JS_PREV_LINK(_e) \
+ ((_e)->prev)
+
+/*
+** Append an element "_e" to the end of the list "_l"
+*/
+#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
+
+/*
+** Insert an element "_e" at the head of the list "_l"
+*/
+#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
+
+/* Return the head/tail of the list */
+#define JS_LIST_HEAD(_l) (_l)->next
+#define JS_LIST_TAIL(_l) (_l)->prev
+
+/*
+** Remove the element "_e" from it's circular list.
+*/
+#define JS_REMOVE_LINK(_e) \
+ JS_BEGIN_MACRO \
+ (_e)->prev->next = (_e)->next; \
+ (_e)->next->prev = (_e)->prev; \
+ JS_END_MACRO
+
+/*
+** Remove the element "_e" from it's circular list. Also initializes the
+** linkage.
+*/
+#define JS_REMOVE_AND_INIT_LINK(_e) \
+ JS_BEGIN_MACRO \
+ (_e)->prev->next = (_e)->next; \
+ (_e)->next->prev = (_e)->prev; \
+ (_e)->next = (_e); \
+ (_e)->prev = (_e); \
+ JS_END_MACRO
+
+/*
+** Return non-zero if the given circular list "_l" is empty, zero if the
+** circular list is not empty
+*/
+#define JS_CLIST_IS_EMPTY(_l) \
+ ((_l)->next == (_l))
+
+/*
+** Initialize a circular list
+*/
+#define JS_INIT_CLIST(_l) \
+ JS_BEGIN_MACRO \
+ (_l)->next = (_l); \
+ (_l)->prev = (_l); \
+ JS_END_MACRO
+
+#define JS_INIT_STATIC_CLIST(_l) \
+ {(_l), (_l)}
+
+#endif /* jsclist_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp
new file mode 100644
index 0000000..c06a334
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.cpp
@@ -0,0 +1,1394 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS execution context.
+ */
+#include "jsstddef.h"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jsprf.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jstracer.h"
+
+#ifdef JS_THREADSAFE
+#include "prtypes.h"
+
+/*
+ * The index for JSThread info, returned by PR_NewThreadPrivateIndex. The
+ * index value is visible and shared by all threads, but the data associated
+ * with it is private to each thread.
+ */
+static PRUintn threadTPIndex;
+static JSBool tpIndexInited = JS_FALSE;
+
+JS_BEGIN_EXTERN_C
+JSBool
+js_InitThreadPrivateIndex(void (*ptr)(void *))
+{
+ PRStatus status;
+
+ if (tpIndexInited)
+ return JS_TRUE;
+
+ status = PR_NewThreadPrivateIndex(&threadTPIndex, ptr);
+
+ if (status == PR_SUCCESS)
+ tpIndexInited = JS_TRUE;
+ return status == PR_SUCCESS;
+}
+JS_END_EXTERN_C
+
+/*
+ * Callback function to delete a JSThread info when the thread that owns it
+ * is destroyed.
+ */
+void
+js_ThreadDestructorCB(void *ptr)
+{
+ JSThread *thread = (JSThread *)ptr;
+
+ if (!thread)
+ return;
+
+ /*
+ * Check that this thread properly called either JS_DestroyContext or
+ * JS_ClearContextThread on each JSContext it created or used.
+ */
+ JS_ASSERT(JS_CLIST_IS_EMPTY(&thread->contextList));
+ GSN_CACHE_CLEAR(&thread->gsnCache);
+#if defined JS_TRACER
+ js_FinishJIT(&thread->traceMonitor);
+#endif
+ free(thread);
+}
+
+/*
+ * Get current thread-local JSThread info, creating one if it doesn't exist.
+ * Each thread has a unique JSThread pointer.
+ *
+ * Since we are dealing with thread-local data, no lock is needed.
+ *
+ * Return a pointer to the thread local info, NULL if the system runs out
+ * of memory, or it failed to set thread private data (neither case is very
+ * likely; both are probably due to out-of-memory). It is up to the caller
+ * to report an error, if possible.
+ */
+JSThread *
+js_GetCurrentThread(JSRuntime *rt)
+{
+ JSThread *thread;
+
+ thread = (JSThread *)PR_GetThreadPrivate(threadTPIndex);
+ if (!thread) {
+ thread = (JSThread *) malloc(sizeof(JSThread));
+ if (!thread)
+ return NULL;
+#ifdef DEBUG
+ memset(thread, JS_FREE_PATTERN, sizeof(JSThread));
+#endif
+ if (PR_FAILURE == PR_SetThreadPrivate(threadTPIndex, thread)) {
+ free(thread);
+ return NULL;
+ }
+
+ JS_INIT_CLIST(&thread->contextList);
+ thread->id = js_CurrentThreadId();
+ thread->gcMallocBytes = 0;
+#ifdef JS_TRACER
+ memset(&thread->traceMonitor, 0, sizeof(thread->traceMonitor));
+ js_InitJIT(&thread->traceMonitor);
+#endif
+ thread->scriptsToGC = NULL;
+
+ /*
+ * js_SetContextThread initializes the remaining fields as necessary.
+ */
+ }
+ return thread;
+}
+
+/*
+ * Sets current thread as owning thread of a context by assigning the
+ * thread-private info to the context. If the current thread doesn't have
+ * private JSThread info, create one.
+ */
+JSBool
+js_SetContextThread(JSContext *cx)
+{
+ JSThread *thread = js_GetCurrentThread(cx->runtime);
+
+ if (!thread) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ /*
+ * Clear caches on each transition from 0 to 1 context active on the
+ * current thread. See bug 425828.
+ */
+ if (JS_CLIST_IS_EMPTY(&thread->contextList)) {
+ memset(&thread->gsnCache, 0, sizeof(thread->gsnCache));
+ memset(&thread->propertyCache, 0, sizeof(thread->propertyCache));
+ }
+
+ /* Assert that the previous cx->thread called JS_ClearContextThread(). */
+ JS_ASSERT(!cx->thread || cx->thread == thread);
+ if (!cx->thread)
+ JS_APPEND_LINK(&cx->threadLinks, &thread->contextList);
+ cx->thread = thread;
+ return JS_TRUE;
+}
+
+/* Remove the owning thread info of a context. */
+void
+js_ClearContextThread(JSContext *cx)
+{
+ /*
+ * If cx is associated with a thread, this must be called only from that
+ * thread. If not, this is a harmless no-op.
+ */
+ JS_ASSERT(cx->thread == js_GetCurrentThread(cx->runtime) || !cx->thread);
+ JS_REMOVE_AND_INIT_LINK(&cx->threadLinks);
+ cx->thread = NULL;
+}
+
+#endif /* JS_THREADSAFE */
+
+void
+js_OnVersionChange(JSContext *cx)
+{
+#ifdef DEBUG
+ JSVersion version = JSVERSION_NUMBER(cx);
+
+ JS_ASSERT(version == JSVERSION_DEFAULT || version >= JSVERSION_ECMA_3);
+#endif
+}
+
+void
+js_SetVersion(JSContext *cx, JSVersion version)
+{
+ cx->version = version;
+ js_OnVersionChange(cx);
+}
+
+JSContext *
+js_NewContext(JSRuntime *rt, size_t stackChunkSize)
+{
+ JSContext *cx;
+ JSBool ok, first;
+ JSContextCallback cxCallback;
+
+ cx = (JSContext *) malloc(sizeof *cx);
+ if (!cx)
+ return NULL;
+ memset(cx, 0, sizeof *cx);
+
+ cx->runtime = rt;
+ JS_ClearOperationCallback(cx);
+ cx->debugHooks = &rt->globalDebugHooks;
+#if JS_STACK_GROWTH_DIRECTION > 0
+ cx->stackLimit = (jsuword)-1;
+#endif
+ cx->scriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
+#ifdef JS_THREADSAFE
+ cx->gcLocalFreeLists = (JSGCFreeListSet *) &js_GCEmptyFreeListSet;
+ JS_INIT_CLIST(&cx->threadLinks);
+ js_SetContextThread(cx);
+#endif
+
+ JS_LOCK_GC(rt);
+ for (;;) {
+ first = (rt->contextList.next == &rt->contextList);
+ if (rt->state == JSRTS_UP) {
+ JS_ASSERT(!first);
+ break;
+ }
+ if (rt->state == JSRTS_DOWN) {
+ JS_ASSERT(first);
+ rt->state = JSRTS_LAUNCHING;
+ break;
+ }
+ JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT);
+ }
+ JS_APPEND_LINK(&cx->links, &rt->contextList);
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * First we do the infallible, every-time per-context initializations.
+ * Should a later, fallible initialization (js_InitRegExpStatics, e.g.,
+ * or the stuff under 'if (first)' below) fail, at least the version
+ * and arena-pools will be valid and safe to use (say, from the last GC
+ * done by js_DestroyContext).
+ */
+ cx->version = JSVERSION_DEFAULT;
+ JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
+ &cx->scriptStackQuota);
+
+ JS_INIT_ARENA_POOL(&cx->tempPool, "temp",
+ 1024, /* FIXME: bug 421435 */
+ sizeof(jsdouble), &cx->scriptStackQuota);
+
+ /*
+ * To avoid multiple allocations in InitMatch() (in jsregexp.c), the arena
+ * size parameter should be at least as big as:
+ * INITIAL_BACKTRACK
+ * + (sizeof(REProgState) * INITIAL_STATESTACK)
+ * + (offsetof(REMatchState, parens) + avgParanSize * sizeof(RECapture))
+ */
+ JS_INIT_ARENA_POOL(&cx->regexpPool, "regexp",
+ 12 * 1024 - 40, /* FIXME: bug 421435 */
+ sizeof(void *), &cx->scriptStackQuota);
+
+ if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
+ return NULL;
+ }
+
+ cx->resolveFlags = 0;
+
+ /*
+ * If cx is the first context on this runtime, initialize well-known atoms,
+ * keywords, numbers, and strings. If one of these steps should fail, the
+ * runtime will be left in a partially initialized state, with zeroes and
+ * nulls stored in the default-initialized remainder of the struct. We'll
+ * clean the runtime up under js_DestroyContext, because cx will be "last"
+ * as well as "first".
+ */
+ if (first) {
+#ifdef JS_THREADSAFE
+ JS_BeginRequest(cx);
+#endif
+ ok = js_InitCommonAtoms(cx);
+
+ /*
+ * scriptFilenameTable may be left over from a previous episode of
+ * non-zero contexts alive in rt, so don't re-init the table if it's
+ * not necessary.
+ */
+ if (ok && !rt->scriptFilenameTable)
+ ok = js_InitRuntimeScriptState(rt);
+ if (ok)
+ ok = js_InitRuntimeNumberState(cx);
+ if (ok)
+ ok = js_InitRuntimeStringState(cx);
+#ifdef JS_THREADSAFE
+ JS_EndRequest(cx);
+#endif
+ if (!ok) {
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
+ return NULL;
+ }
+
+ JS_LOCK_GC(rt);
+ rt->state = JSRTS_UP;
+ JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
+ JS_UNLOCK_GC(rt);
+ }
+
+ cxCallback = rt->cxCallback;
+ if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) {
+ js_DestroyContext(cx, JSDCM_NEW_FAILED);
+ return NULL;
+ }
+
+ return cx;
+}
+
+void
+js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
+{
+ JSRuntime *rt;
+ JSContextCallback cxCallback;
+ JSBool last;
+ JSArgumentFormatMap *map;
+ JSLocalRootStack *lrs;
+ JSLocalRootChunk *lrc;
+
+ rt = cx->runtime;
+
+ if (mode != JSDCM_NEW_FAILED) {
+ cxCallback = rt->cxCallback;
+ if (cxCallback) {
+ /*
+ * JSCONTEXT_DESTROY callback is not allowed to fail and must
+ * return true.
+ */
+#ifdef DEBUG
+ JSBool callbackStatus =
+#endif
+ cxCallback(cx, JSCONTEXT_DESTROY);
+ JS_ASSERT(callbackStatus);
+ }
+ }
+
+ /* Remove cx from context list first. */
+ JS_LOCK_GC(rt);
+ JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
+ JS_REMOVE_LINK(&cx->links);
+ last = (rt->contextList.next == &rt->contextList);
+ if (last)
+ rt->state = JSRTS_LANDING;
+#ifdef JS_THREADSAFE
+ js_RevokeGCLocalFreeLists(cx);
+#endif
+ JS_UNLOCK_GC(rt);
+
+ if (last) {
+#ifdef JS_THREADSAFE
+ /*
+ * If cx is not in a request already, begin one now so that we wait
+ * for any racing GC started on a not-last context to finish, before
+ * we plow ahead and unpin atoms. Note that even though we begin a
+ * request here if necessary, we end all requests on cx below before
+ * forcing a final GC. This lets any not-last context destruction
+ * racing in another thread try to force or maybe run the GC, but by
+ * that point, rt->state will not be JSRTS_UP, and that GC attempt
+ * will return early.
+ */
+ if (cx->requestDepth == 0)
+ JS_BeginRequest(cx);
+#endif
+
+ /* Unlock and clear GC things held by runtime pointers. */
+ js_FinishRuntimeNumberState(cx);
+ js_FinishRuntimeStringState(cx);
+
+ /* Unpin all common atoms before final GC. */
+ js_FinishCommonAtoms(cx);
+
+ /* Clear debugging state to remove GC roots. */
+ JS_ClearAllTraps(cx);
+ JS_ClearAllWatchPoints(cx);
+ }
+
+ /*
+ * Remove more GC roots in regExpStatics, then collect garbage.
+ * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within
+ * XXX this function call to wait for any racing GC to complete, in the
+ * XXX case where JS_DestroyContext is called outside of a request on cx
+ */
+ js_FreeRegExpStatics(cx, &cx->regExpStatics);
+
+#ifdef JS_THREADSAFE
+ /*
+ * Destroying a context implicitly calls JS_EndRequest(). Also, we must
+ * end our request here in case we are "last" -- in that event, another
+ * js_DestroyContext that was not last might be waiting in the GC for our
+ * request to end. We'll let it run below, just before we do the truly
+ * final GC and then free atom state.
+ *
+ * At this point, cx must be inaccessible to other threads. It's off the
+ * rt->contextList, and it should not be reachable via any object private
+ * data structure.
+ */
+ while (cx->requestDepth != 0)
+ JS_EndRequest(cx);
+#endif
+
+ if (last) {
+ js_GC(cx, GC_LAST_CONTEXT);
+
+ /*
+ * Free the script filename table if it exists and is empty. Do this
+ * after the last GC to avoid finalizers tripping on free memory.
+ */
+ if (rt->scriptFilenameTable && rt->scriptFilenameTable->nentries == 0)
+ js_FinishRuntimeScriptState(rt);
+
+ /* Take the runtime down, now that it has no contexts or atoms. */
+ JS_LOCK_GC(rt);
+ rt->state = JSRTS_DOWN;
+ JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
+ JS_UNLOCK_GC(rt);
+ } else {
+ if (mode == JSDCM_FORCE_GC)
+ js_GC(cx, GC_NORMAL);
+ else if (mode == JSDCM_MAYBE_GC)
+ JS_MaybeGC(cx);
+ }
+
+ /* Free the stuff hanging off of cx. */
+ JS_FinishArenaPool(&cx->stackPool);
+ JS_FinishArenaPool(&cx->tempPool);
+ JS_FinishArenaPool(&cx->regexpPool);
+
+ if (cx->lastMessage)
+ free(cx->lastMessage);
+
+ /* Remove any argument formatters. */
+ map = cx->argumentFormatMap;
+ while (map) {
+ JSArgumentFormatMap *temp = map;
+ map = map->next;
+ JS_free(cx, temp);
+ }
+
+ /* Destroy the resolve recursion damper. */
+ if (cx->resolvingTable) {
+ JS_DHashTableDestroy(cx->resolvingTable);
+ cx->resolvingTable = NULL;
+ }
+
+ lrs = cx->localRootStack;
+ if (lrs) {
+ while ((lrc = lrs->topChunk) != &lrs->firstChunk) {
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ }
+ JS_free(cx, lrs);
+ }
+
+#ifdef JS_THREADSAFE
+ js_ClearContextThread(cx);
+#endif
+
+ /* Finally, free cx itself. */
+ free(cx);
+}
+
+JSBool
+js_ValidContextPointer(JSRuntime *rt, JSContext *cx)
+{
+ JSCList *cl;
+
+ for (cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next) {
+ if (cl == &cx->links)
+ return JS_TRUE;
+ }
+ JS_RUNTIME_METER(rt, deadContexts);
+ return JS_FALSE;
+}
+
+JSContext *
+js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp)
+{
+ JSContext *cx = *iterp;
+
+ if (unlocked)
+ JS_LOCK_GC(rt);
+ cx = (JSContext *) (cx ? cx->links.next : rt->contextList.next);
+ if (&cx->links == &rt->contextList)
+ cx = NULL;
+ *iterp = cx;
+ if (unlocked)
+ JS_UNLOCK_GC(rt);
+ return cx;
+}
+
+static JSDHashNumber
+resolving_HashKey(JSDHashTable *table, const void *ptr)
+{
+ const JSResolvingKey *key = (const JSResolvingKey *)ptr;
+
+ return ((JSDHashNumber)JS_PTR_TO_UINT32(key->obj) >> JSVAL_TAGBITS) ^ key->id;
+}
+
+JS_PUBLIC_API(JSBool)
+resolving_MatchEntry(JSDHashTable *table,
+ const JSDHashEntryHdr *hdr,
+ const void *ptr)
+{
+ const JSResolvingEntry *entry = (const JSResolvingEntry *)hdr;
+ const JSResolvingKey *key = (const JSResolvingKey *)ptr;
+
+ return entry->key.obj == key->obj && entry->key.id == key->id;
+}
+
+static const JSDHashTableOps resolving_dhash_ops = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ resolving_HashKey,
+ resolving_MatchEntry,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+JSBool
+js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry **entryp)
+{
+ JSDHashTable *table;
+ JSResolvingEntry *entry;
+
+ table = cx->resolvingTable;
+ if (!table) {
+ table = JS_NewDHashTable(&resolving_dhash_ops, NULL,
+ sizeof(JSResolvingEntry),
+ JS_DHASH_MIN_SIZE);
+ if (!table)
+ goto outofmem;
+ cx->resolvingTable = table;
+ }
+
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, key, JS_DHASH_ADD);
+ if (!entry)
+ goto outofmem;
+
+ if (entry->flags & flag) {
+ /* An entry for (key, flag) exists already -- dampen recursion. */
+ entry = NULL;
+ } else {
+ /* Fill in key if we were the first to add entry, then set flag. */
+ if (!entry->key.obj)
+ entry->key = *key;
+ entry->flags |= flag;
+ }
+ *entryp = entry;
+ return JS_TRUE;
+
+outofmem:
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+}
+
+void
+js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry *entry, uint32 generation)
+{
+ JSDHashTable *table;
+
+ /*
+ * Clear flag from entry->flags and return early if other flags remain.
+ * We must take care to re-lookup entry if the table has changed since
+ * it was found by js_StartResolving.
+ */
+ table = cx->resolvingTable;
+ if (!entry || table->generation != generation) {
+ entry = (JSResolvingEntry *)
+ JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP);
+ }
+ JS_ASSERT(JS_DHASH_ENTRY_IS_BUSY(&entry->hdr));
+ entry->flags &= ~flag;
+ if (entry->flags)
+ return;
+
+ /*
+ * Do a raw remove only if fewer entries were removed than would cause
+ * alpha to be less than .5 (alpha is at most .75). Otherwise, we just
+ * call JS_DHashTableOperate to re-lookup the key and remove its entry,
+ * compressing or shrinking the table as needed.
+ */
+ if (table->removedCount < JS_DHASH_TABLE_SIZE(table) >> 2)
+ JS_DHashTableRawRemove(table, &entry->hdr);
+ else
+ JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);
+}
+
+JSBool
+js_EnterLocalRootScope(JSContext *cx)
+{
+ JSLocalRootStack *lrs;
+ int mark;
+
+ lrs = cx->localRootStack;
+ if (!lrs) {
+ lrs = (JSLocalRootStack *) JS_malloc(cx, sizeof *lrs);
+ if (!lrs)
+ return JS_FALSE;
+ lrs->scopeMark = JSLRS_NULL_MARK;
+ lrs->rootCount = 0;
+ lrs->topChunk = &lrs->firstChunk;
+ lrs->firstChunk.down = NULL;
+ cx->localRootStack = lrs;
+ }
+
+ /* Push lrs->scopeMark to save it for restore when leaving. */
+ mark = js_PushLocalRoot(cx, lrs, INT_TO_JSVAL(lrs->scopeMark));
+ if (mark < 0)
+ return JS_FALSE;
+ lrs->scopeMark = (uint32) mark;
+ return JS_TRUE;
+}
+
+void
+js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval)
+{
+ JSLocalRootStack *lrs;
+ uint32 mark, m, n;
+ JSLocalRootChunk *lrc;
+
+ /* Defend against buggy native callers. */
+ lrs = cx->localRootStack;
+ JS_ASSERT(lrs && lrs->rootCount != 0);
+ if (!lrs || lrs->rootCount == 0)
+ return;
+
+ mark = lrs->scopeMark;
+ JS_ASSERT(mark != JSLRS_NULL_MARK);
+ if (mark == JSLRS_NULL_MARK)
+ return;
+
+ /* Free any chunks being popped by this leave operation. */
+ m = mark >> JSLRS_CHUNK_SHIFT;
+ n = (lrs->rootCount - 1) >> JSLRS_CHUNK_SHIFT;
+ while (n > m) {
+ lrc = lrs->topChunk;
+ JS_ASSERT(lrc != &lrs->firstChunk);
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ --n;
+ }
+
+ /*
+ * Pop the scope, restoring lrs->scopeMark. If rval is a GC-thing, push
+ * it on the caller's scope, or store it in lastInternalResult if we are
+ * leaving the outermost scope. We don't need to allocate a new lrc
+ * because we can overwrite the old mark's slot with rval.
+ */
+ lrc = lrs->topChunk;
+ m = mark & JSLRS_CHUNK_MASK;
+ lrs->scopeMark = (uint32) JSVAL_TO_INT(lrc->roots[m]);
+ if (JSVAL_IS_GCTHING(rval) && !JSVAL_IS_NULL(rval)) {
+ if (mark == 0) {
+ cx->weakRoots.lastInternalResult = rval;
+ } else {
+ /*
+ * Increment m to avoid the "else if (m == 0)" case below. If
+ * rval is not a GC-thing, that case would take care of freeing
+ * any chunk that contained only the old mark. Since rval *is*
+ * a GC-thing here, we want to reuse that old mark's slot.
+ */
+ lrc->roots[m++] = rval;
+ ++mark;
+ }
+ }
+ lrs->rootCount = (uint32) mark;
+
+ /*
+ * Free the stack eagerly, risking malloc churn. The alternative would
+ * require an lrs->entryCount member, maintained by Enter and Leave, and
+ * tested by the GC in addition to the cx->localRootStack non-null test.
+ *
+ * That approach would risk hoarding 264 bytes (net) per context. Right
+ * now it seems better to give fresh (dirty in CPU write-back cache, and
+ * the data is no longer needed) memory back to the malloc heap.
+ */
+ if (mark == 0) {
+ cx->localRootStack = NULL;
+ JS_free(cx, lrs);
+ } else if (m == 0) {
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ }
+}
+
+void
+js_ForgetLocalRoot(JSContext *cx, jsval v)
+{
+ JSLocalRootStack *lrs;
+ uint32 i, j, m, n, mark;
+ JSLocalRootChunk *lrc, *lrc2;
+ jsval top;
+
+ lrs = cx->localRootStack;
+ JS_ASSERT(lrs && lrs->rootCount);
+ if (!lrs || lrs->rootCount == 0)
+ return;
+
+ /* Prepare to pop the top-most value from the stack. */
+ n = lrs->rootCount - 1;
+ m = n & JSLRS_CHUNK_MASK;
+ lrc = lrs->topChunk;
+ top = lrc->roots[m];
+
+ /* Be paranoid about calls on an empty scope. */
+ mark = lrs->scopeMark;
+ JS_ASSERT(mark < n);
+ if (mark >= n)
+ return;
+
+ /* If v was not the last root pushed in the top scope, find it. */
+ if (top != v) {
+ /* Search downward in case v was recently pushed. */
+ i = n;
+ j = m;
+ lrc2 = lrc;
+ while (--i > mark) {
+ if (j == 0)
+ lrc2 = lrc2->down;
+ j = i & JSLRS_CHUNK_MASK;
+ if (lrc2->roots[j] == v)
+ break;
+ }
+
+ /* If we didn't find v in this scope, assert and bail out. */
+ JS_ASSERT(i != mark);
+ if (i == mark)
+ return;
+
+ /* Swap top and v so common tail code can pop v. */
+ lrc2->roots[j] = top;
+ }
+
+ /* Pop the last value from the stack. */
+ lrc->roots[m] = JSVAL_NULL;
+ lrs->rootCount = n;
+ if (m == 0) {
+ JS_ASSERT(n != 0);
+ JS_ASSERT(lrc != &lrs->firstChunk);
+ lrs->topChunk = lrc->down;
+ JS_free(cx, lrc);
+ }
+}
+
+int
+js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v)
+{
+ uint32 n, m;
+ JSLocalRootChunk *lrc;
+
+ n = lrs->rootCount;
+ m = n & JSLRS_CHUNK_MASK;
+ if (n == 0 || m != 0) {
+ /*
+ * At start of first chunk, or not at start of a non-first top chunk.
+ * Check for lrs->rootCount overflow.
+ */
+ if ((uint32)(n + 1) == 0) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_LOCAL_ROOTS);
+ return -1;
+ }
+ lrc = lrs->topChunk;
+ JS_ASSERT(n != 0 || lrc == &lrs->firstChunk);
+ } else {
+ /*
+ * After lrs->firstChunk, trying to index at a power-of-two chunk
+ * boundary: need a new chunk.
+ */
+ lrc = (JSLocalRootChunk *) JS_malloc(cx, sizeof *lrc);
+ if (!lrc)
+ return -1;
+ lrc->down = lrs->topChunk;
+ lrs->topChunk = lrc;
+ }
+ lrs->rootCount = n + 1;
+ lrc->roots[m] = v;
+ return (int) n;
+}
+
+void
+js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs)
+{
+ uint32 n, m, mark;
+ JSLocalRootChunk *lrc;
+ jsval v;
+
+ n = lrs->rootCount;
+ if (n == 0)
+ return;
+
+ mark = lrs->scopeMark;
+ lrc = lrs->topChunk;
+ do {
+ while (--n > mark) {
+ m = n & JSLRS_CHUNK_MASK;
+ v = lrc->roots[m];
+ JS_ASSERT(JSVAL_IS_GCTHING(v) && v != JSVAL_NULL);
+ JS_SET_TRACING_INDEX(trc, "local_root", n);
+ js_CallValueTracerIfGCThing(trc, v);
+ if (m == 0)
+ lrc = lrc->down;
+ }
+ m = n & JSLRS_CHUNK_MASK;
+ mark = JSVAL_TO_INT(lrc->roots[m]);
+ if (m == 0)
+ lrc = lrc->down;
+ } while (n != 0);
+ JS_ASSERT(!lrc);
+}
+
+static void
+ReportError(JSContext *cx, const char *message, JSErrorReport *reportp)
+{
+ /*
+ * Check the error report, and set a JavaScript-catchable exception
+ * if the error is defined to have an associated exception. If an
+ * exception is thrown, then the JSREPORT_EXCEPTION flag will be set
+ * on the error report, and exception-aware hosts should ignore it.
+ */
+ JS_ASSERT(reportp);
+ if (reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION)
+ reportp->flags |= JSREPORT_EXCEPTION;
+
+ /*
+ * Call the error reporter only if an exception wasn't raised.
+ *
+ * If an exception was raised, then we call the debugErrorHook
+ * (if present) to give it a chance to see the error before it
+ * propagates out of scope. This is needed for compatability
+ * with the old scheme.
+ */
+ if (!cx->fp || !js_ErrorToException(cx, message, reportp)) {
+ js_ReportErrorAgain(cx, message, reportp);
+ } else if (cx->debugHooks->debugErrorHook && cx->errorReporter) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+ /* test local in case debugErrorHook changed on another thread */
+ if (hook)
+ hook(cx, message, reportp, cx->debugHooks->debugErrorHookData);
+ }
+}
+
+/*
+ * We don't post an exception in this case, since doing so runs into
+ * complications of pre-allocating an exception object which required
+ * running the Exception class initializer early etc.
+ * Instead we just invoke the errorReporter with an "Out Of Memory"
+ * type message, and then hope the process ends swiftly.
+ */
+void
+js_ReportOutOfMemory(JSContext *cx)
+{
+ JSStackFrame *fp;
+ JSErrorReport report;
+ JSErrorReporter onError = cx->errorReporter;
+
+ /* Get the message for this error, but we won't expand any arguments. */
+ const JSErrorFormatString *efs =
+ js_GetLocalizedErrorMessage(cx, NULL, NULL, JSMSG_OUT_OF_MEMORY);
+ const char *msg = efs ? efs->format : "Out of memory";
+
+ /* Fill out the report, but don't do anything that requires allocation. */
+ memset(&report, 0, sizeof (struct JSErrorReport));
+ report.flags = JSREPORT_ERROR;
+ report.errorNumber = JSMSG_OUT_OF_MEMORY;
+
+ /*
+ * Walk stack until we find a frame that is associated with some script
+ * rather than a native frame.
+ */
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->regs) {
+ report.filename = fp->script->filename;
+ report.lineno = js_FramePCToLineNumber(cx, fp);
+ break;
+ }
+ }
+
+ /*
+ * If debugErrorHook is present then we give it a chance to veto sending
+ * the error on to the regular ErrorReporter. We also clear a pending
+ * exception if any now so the hooks can replace the out-of-memory error
+ * by a script-catchable exception.
+ */
+ cx->throwing = JS_FALSE;
+ if (onError) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+ if (hook &&
+ !hook(cx, msg, &report, cx->debugHooks->debugErrorHookData)) {
+ onError = NULL;
+ }
+ }
+
+ if (onError)
+ onError(cx, msg, &report);
+}
+
+void
+js_ReportOutOfScriptQuota(JSContext *cx)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_SCRIPT_STACK_QUOTA);
+}
+
+void
+js_ReportOverRecursed(JSContext *cx)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
+}
+
+void
+js_ReportAllocationOverflow(JSContext *cx)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_ALLOC_OVERFLOW);
+}
+
+JSBool
+js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
+{
+ char *message;
+ jschar *ucmessage;
+ size_t messagelen;
+ JSStackFrame *fp;
+ JSErrorReport report;
+ JSBool warning;
+
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
+ return JS_TRUE;
+
+ message = JS_vsmprintf(format, ap);
+ if (!message)
+ return JS_FALSE;
+ messagelen = strlen(message);
+
+ memset(&report, 0, sizeof (struct JSErrorReport));
+ report.flags = flags;
+ report.errorNumber = JSMSG_USER_DEFINED_ERROR;
+ report.ucmessage = ucmessage = js_InflateString(cx, message, &messagelen);
+
+ /* Find the top-most active script frame, for best line number blame. */
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->regs) {
+ report.filename = fp->script->filename;
+ report.lineno = js_FramePCToLineNumber(cx, fp);
+ break;
+ }
+ }
+
+ warning = JSREPORT_IS_WARNING(report.flags);
+ if (warning && JS_HAS_WERROR_OPTION(cx)) {
+ report.flags &= ~JSREPORT_WARNING;
+ warning = JS_FALSE;
+ }
+
+ ReportError(cx, message, &report);
+ free(message);
+ JS_free(cx, ucmessage);
+ return warning;
+}
+
+/*
+ * The arguments from ap need to be packaged up into an array and stored
+ * into the report struct.
+ *
+ * The format string addressed by the error number may contain operands
+ * identified by the format {N}, where N is a decimal digit. Each of these
+ * is to be replaced by the Nth argument from the va_list. The complete
+ * message is placed into reportp->ucmessage converted to a JSString.
+ *
+ * Returns true if the expansion succeeds (can fail if out of memory).
+ */
+JSBool
+js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ char **messagep, JSErrorReport *reportp,
+ JSBool *warningp, JSBool charArgs, va_list ap)
+{
+ const JSErrorFormatString *efs;
+ int i;
+ int argCount;
+
+ *warningp = JSREPORT_IS_WARNING(reportp->flags);
+ if (*warningp && JS_HAS_WERROR_OPTION(cx)) {
+ reportp->flags &= ~JSREPORT_WARNING;
+ *warningp = JS_FALSE;
+ }
+
+ *messagep = NULL;
+
+ /* Most calls supply js_GetErrorMessage; if this is so, assume NULL. */
+ if (!callback || callback == js_GetErrorMessage)
+ efs = js_GetLocalizedErrorMessage(cx, userRef, NULL, errorNumber);
+ else
+ efs = callback(userRef, NULL, errorNumber);
+ if (efs) {
+ size_t totalArgsLength = 0;
+ size_t argLengths[10]; /* only {0} thru {9} supported */
+ argCount = efs->argCount;
+ JS_ASSERT(argCount <= 10);
+ if (argCount > 0) {
+ /*
+ * Gather the arguments into an array, and accumulate
+ * their sizes. We allocate 1 more than necessary and
+ * null it out to act as the caboose when we free the
+ * pointers later.
+ */
+ reportp->messageArgs = (const jschar **)
+ JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
+ if (!reportp->messageArgs)
+ return JS_FALSE;
+ reportp->messageArgs[argCount] = NULL;
+ for (i = 0; i < argCount; i++) {
+ if (charArgs) {
+ char *charArg = va_arg(ap, char *);
+ size_t charArgLength = strlen(charArg);
+ reportp->messageArgs[i]
+ = js_InflateString(cx, charArg, &charArgLength);
+ if (!reportp->messageArgs[i])
+ goto error;
+ } else {
+ reportp->messageArgs[i] = va_arg(ap, jschar *);
+ }
+ argLengths[i] = js_strlen(reportp->messageArgs[i]);
+ totalArgsLength += argLengths[i];
+ }
+ /* NULL-terminate for easy copying. */
+ reportp->messageArgs[i] = NULL;
+ }
+ /*
+ * Parse the error format, substituting the argument X
+ * for {X} in the format.
+ */
+ if (argCount > 0) {
+ if (efs->format) {
+ jschar *buffer, *fmt, *out;
+ int expandedArgs = 0;
+ size_t expandedLength;
+ size_t len = strlen(efs->format);
+
+ buffer = fmt = js_InflateString (cx, efs->format, &len);
+ if (!buffer)
+ goto error;
+ expandedLength = len
+ - (3 * argCount) /* exclude the {n} */
+ + totalArgsLength;
+
+ /*
+ * Note - the above calculation assumes that each argument
+ * is used once and only once in the expansion !!!
+ */
+ reportp->ucmessage = out = (jschar *)
+ JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
+ if (!out) {
+ JS_free (cx, buffer);
+ goto error;
+ }
+ while (*fmt) {
+ if (*fmt == '{') {
+ if (isdigit(fmt[1])) {
+ int d = JS7_UNDEC(fmt[1]);
+ JS_ASSERT(d < argCount);
+ js_strncpy(out, reportp->messageArgs[d],
+ argLengths[d]);
+ out += argLengths[d];
+ fmt += 3;
+ expandedArgs++;
+ continue;
+ }
+ }
+ *out++ = *fmt++;
+ }
+ JS_ASSERT(expandedArgs == argCount);
+ *out = 0;
+ JS_free (cx, buffer);
+ *messagep =
+ js_DeflateString(cx, reportp->ucmessage,
+ (size_t)(out - reportp->ucmessage));
+ if (!*messagep)
+ goto error;
+ }
+ } else {
+ /*
+ * Zero arguments: the format string (if it exists) is the
+ * entire message.
+ */
+ if (efs->format) {
+ size_t len;
+ *messagep = JS_strdup(cx, efs->format);
+ if (!*messagep)
+ goto error;
+ len = strlen(*messagep);
+ reportp->ucmessage = js_InflateString(cx, *messagep, &len);
+ if (!reportp->ucmessage)
+ goto error;
+ }
+ }
+ }
+ if (*messagep == NULL) {
+ /* where's the right place for this ??? */
+ const char *defaultErrorMessage
+ = "No error message available for error number %d";
+ size_t nbytes = strlen(defaultErrorMessage) + 16;
+ *messagep = (char *)JS_malloc(cx, nbytes);
+ if (!*messagep)
+ goto error;
+ JS_snprintf(*messagep, nbytes, defaultErrorMessage, errorNumber);
+ }
+ return JS_TRUE;
+
+error:
+ if (reportp->messageArgs) {
+ /* free the arguments only if we allocated them */
+ if (charArgs) {
+ i = 0;
+ while (reportp->messageArgs[i])
+ JS_free(cx, (void *)reportp->messageArgs[i++]);
+ }
+ JS_free(cx, (void *)reportp->messageArgs);
+ reportp->messageArgs = NULL;
+ }
+ if (reportp->ucmessage) {
+ JS_free(cx, (void *)reportp->ucmessage);
+ reportp->ucmessage = NULL;
+ }
+ if (*messagep) {
+ JS_free(cx, (void *)*messagep);
+ *messagep = NULL;
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ JSBool charArgs, va_list ap)
+{
+ JSStackFrame *fp;
+ JSErrorReport report;
+ char *message;
+ JSBool warning;
+
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
+ return JS_TRUE;
+
+ memset(&report, 0, sizeof (struct JSErrorReport));
+ report.flags = flags;
+ report.errorNumber = errorNumber;
+
+ /*
+ * If we can't find out where the error was based on the current frame,
+ * see if the next frame has a script/pc combo we can use.
+ */
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->regs) {
+ report.filename = fp->script->filename;
+ report.lineno = js_FramePCToLineNumber(cx, fp);
+ break;
+ }
+ }
+
+ if (!js_ExpandErrorArguments(cx, callback, userRef, errorNumber,
+ &message, &report, &warning, charArgs, ap)) {
+ return JS_FALSE;
+ }
+
+ ReportError(cx, message, &report);
+
+ if (message)
+ JS_free(cx, message);
+ if (report.messageArgs) {
+ /*
+ * js_ExpandErrorArguments owns its messageArgs only if it had to
+ * inflate the arguments (from regular |char *|s).
+ */
+ if (charArgs) {
+ int i = 0;
+ while (report.messageArgs[i])
+ JS_free(cx, (void *)report.messageArgs[i++]);
+ }
+ JS_free(cx, (void *)report.messageArgs);
+ }
+ if (report.ucmessage)
+ JS_free(cx, (void *)report.ucmessage);
+
+ return warning;
+}
+
+JS_FRIEND_API(void)
+js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
+{
+ JSErrorReporter onError;
+
+ if (!message)
+ return;
+
+ if (cx->lastMessage)
+ free(cx->lastMessage);
+ cx->lastMessage = JS_strdup(cx, message);
+ if (!cx->lastMessage)
+ return;
+ onError = cx->errorReporter;
+
+ /*
+ * If debugErrorHook is present then we give it a chance to veto
+ * sending the error on to the regular ErrorReporter.
+ */
+ if (onError) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+ if (hook &&
+ !hook(cx, cx->lastMessage, reportp,
+ cx->debugHooks->debugErrorHookData)) {
+ onError = NULL;
+ }
+ }
+ if (onError)
+ onError(cx, cx->lastMessage, reportp);
+}
+
+void
+js_ReportIsNotDefined(JSContext *cx, const char *name)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_DEFINED, name);
+}
+
+JSBool
+js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback)
+{
+ char *bytes;
+ JSBool ok;
+
+ bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
+ if (!bytes)
+ return JS_FALSE;
+
+ if (strcmp(bytes, js_undefined_str) == 0 ||
+ strcmp(bytes, js_null_str) == 0) {
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_NO_PROPERTIES, bytes,
+ NULL, NULL);
+ } else if (JSVAL_IS_VOID(v)) {
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_NULL_OR_UNDEFINED, bytes,
+ js_undefined_str, NULL);
+ } else {
+ JS_ASSERT(JSVAL_IS_NULL(v));
+ ok = JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_NULL_OR_UNDEFINED, bytes,
+ js_null_str, NULL);
+ }
+
+ JS_free(cx, bytes);
+ return ok;
+}
+
+void
+js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg)
+{
+ char argbuf[11];
+ char *bytes;
+ JSAtom *atom;
+
+ JS_snprintf(argbuf, sizeof argbuf, "%u", arg);
+ bytes = NULL;
+ if (VALUE_IS_FUNCTION(cx, *vp)) {
+ atom = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp))->atom;
+ bytes = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, *vp,
+ ATOM_TO_STRING(atom));
+ if (!bytes)
+ return;
+ }
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_MISSING_FUN_ARG, argbuf,
+ bytes ? bytes : "");
+ JS_free(cx, bytes);
+}
+
+JSBool
+js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
+ intN spindex, jsval v, JSString *fallback,
+ const char *arg1, const char *arg2)
+{
+ char *bytes;
+ JSBool ok;
+
+ JS_ASSERT(js_ErrorFormatString[errorNumber].argCount >= 1);
+ JS_ASSERT(js_ErrorFormatString[errorNumber].argCount <= 3);
+ bytes = js_DecompileValueGenerator(cx, spindex, v, fallback);
+ if (!bytes)
+ return JS_FALSE;
+
+ ok = JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage,
+ NULL, errorNumber, bytes, arg1, arg2);
+ JS_free(cx, bytes);
+ return ok;
+}
+
+#if defined DEBUG && defined XP_UNIX
+/* For gdb usage. */
+void js_traceon(JSContext *cx) { cx->tracefp = stderr; }
+void js_traceoff(JSContext *cx) { cx->tracefp = NULL; }
+#endif
+
+JSErrorFormatString js_ErrorFormatString[JSErr_Limit] = {
+#define MSG_DEF(name, number, count, exception, format) \
+ { format, count, exception } ,
+#include "js.msg"
+#undef MSG_DEF
+};
+
+JS_FRIEND_API(const JSErrorFormatString *)
+js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber)
+{
+ if ((errorNumber > 0) && (errorNumber < JSErr_Limit))
+ return &js_ErrorFormatString[errorNumber];
+ return NULL;
+}
+
+JSBool
+js_ResetOperationCount(JSContext *cx)
+{
+ JSScript *script;
+
+ JS_ASSERT(cx->operationCount <= 0);
+ JS_ASSERT(cx->operationLimit > 0);
+
+ cx->operationCount = (int32) cx->operationLimit;
+ if (cx->operationCallbackIsSet)
+ return cx->operationCallback(cx);
+
+ if (cx->operationCallback) {
+ /*
+ * Invoke the deprecated branch callback. It may be called only when
+ * the top-most frame is scripted or JSOPTION_NATIVE_BRANCH_CALLBACK
+ * is set.
+ */
+ script = cx->fp ? cx->fp->script : NULL;
+ if (script || JS_HAS_OPTION(cx, JSOPTION_NATIVE_BRANCH_CALLBACK))
+ return ((JSBranchCallback) cx->operationCallback)(cx, script);
+ }
+ return JS_TRUE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h
new file mode 100644
index 0000000..c201f1f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscntxt.h
@@ -0,0 +1,1247 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jscntxt_h___
+#define jscntxt_h___
+/*
+ * JS execution context.
+ */
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jslong.h"
+#include "jsatom.h"
+#include "jsversion.h"
+#include "jsdhash.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsobj.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsregexp.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * js_GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
+ * given pc in a script. We use the script->code pointer to tag the cache,
+ * instead of the script address itself, so that source notes are always found
+ * by offset from the bytecode with which they were generated.
+ */
+typedef struct JSGSNCache {
+ jsbytecode *code;
+ JSDHashTable table;
+#ifdef JS_GSNMETER
+ uint32 hits;
+ uint32 misses;
+ uint32 fills;
+ uint32 clears;
+# define GSN_CACHE_METER(cache,cnt) (++(cache)->cnt)
+#else
+# define GSN_CACHE_METER(cache,cnt) /* nothing */
+#endif
+} JSGSNCache;
+
+#define GSN_CACHE_CLEAR(cache) \
+ JS_BEGIN_MACRO \
+ (cache)->code = NULL; \
+ if ((cache)->table.ops) { \
+ JS_DHashTableFinish(&(cache)->table); \
+ (cache)->table.ops = NULL; \
+ } \
+ GSN_CACHE_METER(cache, clears); \
+ JS_END_MACRO
+
+/* These helper macros take a cx as parameter and operate on its GSN cache. */
+#define JS_CLEAR_GSN_CACHE(cx) GSN_CACHE_CLEAR(&JS_GSN_CACHE(cx))
+#define JS_METER_GSN_CACHE(cx,cnt) GSN_CACHE_METER(&JS_GSN_CACHE(cx), cnt)
+
+#ifdef __cplusplus
+namespace nanojit {
+ class Fragment;
+ class Fragmento;
+}
+class TraceRecorder;
+extern "C++" { template<typename T> class Queue; }
+typedef Queue<uint16> SlotList;
+class TypeMap;
+
+# define CLS(T) T*
+#else
+# define CLS(T) void*
+#endif
+
+/*
+ * Trace monitor. Every JSThread (if JS_THREADSAFE) or JSRuntime (if not
+ * JS_THREADSAFE) has an associated trace monitor that keeps track of loop
+ * frequencies for all JavaScript code loaded into that runtime.
+ */
+typedef struct JSTraceMonitor {
+ /*
+ * Flag set when running (or recording) JIT-compiled code. This prevents
+ * both interpreter activation and last-ditch garbage collection when up
+ * against our runtime's memory limits. This flag also suppresses calls to
+ * JS_ReportOutOfMemory when failing due to runtime limits.
+ */
+ JSBool onTrace;
+ CLS(nanojit::Fragmento) fragmento;
+ CLS(TraceRecorder) recorder;
+ uint32 globalShape;
+ CLS(SlotList) globalSlots;
+ CLS(TypeMap) globalTypeMap;
+ jsval *recoveryDoublePool;
+ jsval *recoveryDoublePoolPtr;
+
+ /* Fragmento for the regular expression compiler. This is logically
+ * a distinct compiler but needs to be managed in exactly the same
+ * way as the real tracing Fragmento. */
+ CLS(nanojit::Fragmento) reFragmento;
+
+ /* Keep a list of recorders we need to abort on cache flush. */
+ CLS(TraceRecorder) abortStack;
+} JSTraceMonitor;
+
+#ifdef JS_TRACER
+# define JS_ON_TRACE(cx) (JS_TRACE_MONITOR(cx).onTrace)
+#else
+# define JS_ON_TRACE(cx) JS_FALSE
+#endif
+
+#ifdef JS_THREADSAFE
+
+/*
+ * Structure uniquely representing a thread. It holds thread-private data
+ * that can be accessed without a global lock.
+ */
+struct JSThread {
+ /* Linked list of all contexts active on this thread. */
+ JSCList contextList;
+
+ /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
+ jsword id;
+
+ /*
+ * Thread-local version of JSRuntime.gcMallocBytes to avoid taking
+ * locks on each JS_malloc.
+ */
+ uint32 gcMallocBytes;
+
+ /*
+ * Store the GSN cache in struct JSThread, not struct JSContext, both to
+ * save space and to simplify cleanup in js_GC. Any embedding (Firefox
+ * or another Gecko application) that uses many contexts per thread is
+ * unlikely to interleave js_GetSrcNote-intensive loops in the decompiler
+ * among two or more contexts running script in one thread.
+ */
+ JSGSNCache gsnCache;
+
+ /* Property cache for faster call/get/set invocation. */
+ JSPropertyCache propertyCache;
+
+ /* Trace-tree JIT recorder/interpreter state. */
+ JSTraceMonitor traceMonitor;
+
+ /* Lock-free list of scripts created by eval to garbage-collect. */
+ JSScript *scriptsToGC;
+};
+
+#define JS_GSN_CACHE(cx) ((cx)->thread->gsnCache)
+#define JS_PROPERTY_CACHE(cx) ((cx)->thread->propertyCache)
+#define JS_TRACE_MONITOR(cx) ((cx)->thread->traceMonitor)
+#define JS_SCRIPTS_TO_GC(cx) ((cx)->thread->scriptsToGC)
+
+extern void
+js_ThreadDestructorCB(void *ptr);
+
+extern JSBool
+js_SetContextThread(JSContext *cx);
+
+extern void
+js_ClearContextThread(JSContext *cx);
+
+extern JSThread *
+js_GetCurrentThread(JSRuntime *rt);
+
+#endif /* JS_THREADSAFE */
+
+typedef enum JSDestroyContextMode {
+ JSDCM_NO_GC,
+ JSDCM_MAYBE_GC,
+ JSDCM_FORCE_GC,
+ JSDCM_NEW_FAILED
+} JSDestroyContextMode;
+
+typedef enum JSRuntimeState {
+ JSRTS_DOWN,
+ JSRTS_LAUNCHING,
+ JSRTS_UP,
+ JSRTS_LANDING
+} JSRuntimeState;
+
+typedef struct JSPropertyTreeEntry {
+ JSDHashEntryHdr hdr;
+ JSScopeProperty *child;
+} JSPropertyTreeEntry;
+
+typedef struct JSSetSlotRequest JSSetSlotRequest;
+
+struct JSSetSlotRequest {
+ JSObject *obj; /* object containing slot to set */
+ JSObject *pobj; /* new proto or parent reference */
+ uint16 slot; /* which to set, proto or parent */
+ uint16 errnum; /* JSMSG_NO_ERROR or error result */
+ JSSetSlotRequest *next; /* next request in GC worklist */
+};
+
+struct JSRuntime {
+ /* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
+ JSRuntimeState state;
+
+ /* Context create/destroy callback. */
+ JSContextCallback cxCallback;
+
+ /* Garbage collector state, used by jsgc.c. */
+ JSGCChunkInfo *gcChunkList;
+ JSGCArenaList gcArenaList[GC_NUM_FREELISTS];
+ JSGCDoubleArenaList gcDoubleArenaList;
+ JSGCFreeListSet *gcFreeListsPool;
+ JSDHashTable gcRootsHash;
+ JSDHashTable *gcLocksHash;
+ jsrefcount gcKeepAtoms;
+ uint32 gcBytes;
+ uint32 gcLastBytes;
+ uint32 gcMaxBytes;
+ uint32 gcMaxMallocBytes;
+ uint32 gcEmptyArenaPoolLifespan;
+ uint32 gcLevel;
+ uint32 gcNumber;
+ JSTracer *gcMarkingTracer;
+
+ /*
+ * NB: do not pack another flag here by claiming gcPadding unless the new
+ * flag is written only by the GC thread. Atomic updates to packed bytes
+ * are not guaranteed, so stores issued by one thread may be lost due to
+ * unsynchronized read-modify-write cycles on other threads.
+ */
+ JSPackedBool gcPoke;
+ JSPackedBool gcRunning;
+ uint16 gcPadding;
+#ifdef JS_GC_ZEAL
+ jsrefcount gcZeal;
+#endif
+
+ JSGCCallback gcCallback;
+ uint32 gcMallocBytes;
+ JSGCArenaInfo *gcUntracedArenaStackTop;
+#ifdef DEBUG
+ size_t gcTraceLaterCount;
+#endif
+
+ /*
+ * Table for tracking iterators to ensure that we close iterator's state
+ * before finalizing the iterable object.
+ */
+ JSPtrTable gcIteratorTable;
+
+ /*
+ * The trace operation and its data argument to trace embedding-specific
+ * GC roots.
+ */
+ JSTraceDataOp gcExtraRootsTraceOp;
+ void *gcExtraRootsData;
+
+ /*
+ * Used to serialize cycle checks when setting __proto__ or __parent__ by
+ * requesting the GC handle the required cycle detection. If the GC hasn't
+ * been poked, it won't scan for garbage. This member is protected by
+ * rt->gcLock.
+ */
+ JSSetSlotRequest *setSlotRequests;
+
+ /* Random number generator state, used by jsmath.c. */
+ JSBool rngInitialized;
+ int64 rngMultiplier;
+ int64 rngAddend;
+ int64 rngMask;
+ int64 rngSeed;
+ jsdouble rngDscale;
+
+ /* Well-known numbers held for use by this runtime's contexts. */
+ jsdouble *jsNaN;
+ jsdouble *jsNegativeInfinity;
+ jsdouble *jsPositiveInfinity;
+
+#ifdef JS_THREADSAFE
+ JSLock *deflatedStringCacheLock;
+#endif
+ JSHashTable *deflatedStringCache;
+#ifdef DEBUG
+ uint32 deflatedStringCacheBytes;
+#endif
+
+ /*
+ * Empty and unit-length strings held for use by this runtime's contexts.
+ * The unitStrings array and its elements are created on demand.
+ */
+ JSString *emptyString;
+ JSString **unitStrings;
+
+ /* List of active contexts sharing this runtime; protected by gcLock. */
+ JSCList contextList;
+
+ /* Per runtime debug hooks -- see jsprvtd.h and jsdbgapi.h. */
+ JSDebugHooks globalDebugHooks;
+
+ /* More debugging state, see jsdbgapi.c. */
+ JSCList trapList;
+ JSCList watchPointList;
+
+ /* Client opaque pointers */
+ void *data;
+
+#ifdef JS_THREADSAFE
+ /* These combine to interlock the GC and new requests. */
+ PRLock *gcLock;
+ PRCondVar *gcDone;
+ PRCondVar *requestDone;
+ uint32 requestCount;
+ JSThread *gcThread;
+
+ /* Lock and owning thread pointer for JS_LOCK_RUNTIME. */
+ PRLock *rtLock;
+#ifdef DEBUG
+ jsword rtLockOwner;
+#endif
+
+ /* Used to synchronize down/up state change; protected by gcLock. */
+ PRCondVar *stateChange;
+
+ /*
+ * State for sharing single-threaded titles, once a second thread tries to
+ * lock a title. The titleSharingDone condvar is protected by rt->gcLock
+ * to minimize number of locks taken in JS_EndRequest.
+ *
+ * The titleSharingTodo linked list is likewise "global" per runtime, not
+ * one-list-per-context, to conserve space over all contexts, optimizing
+ * for the likely case that titles become shared rarely, and among a very
+ * small set of threads (contexts).
+ */
+ PRCondVar *titleSharingDone;
+ JSTitle *titleSharingTodo;
+
+/*
+ * Magic terminator for the rt->titleSharingTodo linked list, threaded through
+ * title->u.link. This hack allows us to test whether a title is on the list
+ * by asking whether title->u.link is non-null. We use a large, likely bogus
+ * pointer here to distinguish this value from any valid u.count (small int)
+ * value.
+ */
+#define NO_TITLE_SHARING_TODO ((JSTitle *) 0xfeedbeef)
+
+ /*
+ * Lock serializing trapList and watchPointList accesses, and count of all
+ * mutations to trapList and watchPointList made by debugger threads. To
+ * keep the code simple, we define debuggerMutations for the thread-unsafe
+ * case too.
+ */
+ PRLock *debuggerLock;
+#endif /* JS_THREADSAFE */
+ uint32 debuggerMutations;
+
+ /*
+ * Security callbacks set on the runtime are used by each context unless
+ * an override is set on the context.
+ */
+ JSSecurityCallbacks *securityCallbacks;
+
+ /*
+ * Shared scope property tree, and arena-pool for allocating its nodes.
+ * The propertyRemovals counter is incremented for every js_ClearScope,
+ * and for each js_RemoveScopeProperty that frees a slot in an object.
+ * See js_NativeGet and js_NativeSet in jsobj.c.
+ */
+ JSDHashTable propertyTreeHash;
+ JSScopeProperty *propertyFreeList;
+ JSArenaPool propertyArenaPool;
+ int32 propertyRemovals;
+
+ /* Script filename table. */
+ struct JSHashTable *scriptFilenameTable;
+ JSCList scriptFilenamePrefixes;
+#ifdef JS_THREADSAFE
+ PRLock *scriptFilenameTableLock;
+#endif
+
+ /* Number localization, used by jsnum.c */
+ const char *thousandsSeparator;
+ const char *decimalSeparator;
+ const char *numGrouping;
+
+ /*
+ * Weak references to lazily-created, well-known XML singletons.
+ *
+ * NB: Singleton objects must be carefully disconnected from the rest of
+ * the object graph usually associated with a JSContext's global object,
+ * including the set of standard class objects. See jsxml.c for details.
+ */
+ JSObject *anynameObject;
+ JSObject *functionNamespaceObject;
+
+ /*
+ * A helper list for the GC, so it can mark native iterator states. See
+ * js_TraceNativeEnumerators for details.
+ */
+ JSNativeEnumerator *nativeEnumerators;
+
+#ifndef JS_THREADSAFE
+ /*
+ * For thread-unsafe embeddings, the GSN cache lives in the runtime and
+ * not each context, since we expect it to be filled once when decompiling
+ * a longer script, then hit repeatedly as js_GetSrcNote is called during
+ * the decompiler activation that filled it.
+ */
+ JSGSNCache gsnCache;
+
+ /* Property cache for faster call/get/set invocation. */
+ JSPropertyCache propertyCache;
+
+ /* Trace-tree JIT recorder/interpreter state. */
+ JSTraceMonitor traceMonitor;
+
+ /* Lock-free list of scripts created by eval to garbage-collect. */
+ JSScript *scriptsToGC;
+
+#define JS_GSN_CACHE(cx) ((cx)->runtime->gsnCache)
+#define JS_PROPERTY_CACHE(cx) ((cx)->runtime->propertyCache)
+#define JS_TRACE_MONITOR(cx) ((cx)->runtime->traceMonitor)
+#define JS_SCRIPTS_TO_GC(cx) ((cx)->runtime->scriptsToGC)
+#endif
+
+ /*
+ * Object shape (property cache structural type) identifier generator.
+ *
+ * Type 0 stands for the empty scope, and must not be regenerated due to
+ * uint32 wrap-around. Since we use atomic pre-increment, the initial
+ * value for the first typed non-empty scope will be 1.
+ *
+ * The GC compresses live types, minimizing rt->shapeGen in the process.
+ * If this counter overflows into SHAPE_OVERFLOW_BIT (in jsinterp.h), the
+ * GC will disable property caches for all threads, to avoid aliasing two
+ * different types. Updated by js_GenerateShape (in jsinterp.c).
+ */
+ uint32 shapeGen;
+
+ /* Literal table maintained by jsatom.c functions. */
+ JSAtomState atomState;
+
+ /*
+ * Cache of reusable JSNativeEnumerators mapped by shape identifiers (as
+ * stored in scope->shape). This cache is nulled by the GC and protected
+ * by gcLock.
+ */
+#define NATIVE_ENUM_CACHE_LOG2 8
+#define NATIVE_ENUM_CACHE_MASK JS_BITMASK(NATIVE_ENUM_CACHE_LOG2)
+#define NATIVE_ENUM_CACHE_SIZE JS_BIT(NATIVE_ENUM_CACHE_LOG2)
+
+#define NATIVE_ENUM_CACHE_HASH(shape) \
+ ((((shape) >> NATIVE_ENUM_CACHE_LOG2) ^ (shape)) & NATIVE_ENUM_CACHE_MASK)
+
+ jsuword nativeEnumCache[NATIVE_ENUM_CACHE_SIZE];
+
+ /*
+ * Runtime-wide flag set to true when any Array prototype has an indexed
+ * property defined on it, creating a hazard for code reading or writing
+ * over a hole from a dense Array instance that is not prepared to look up
+ * the proto chain (the writing case must involve a check for a read-only
+ * element, which cannot be shadowed).
+ */
+ JSBool anyArrayProtoHasElement;
+
+ /*
+ * Various metering fields are defined at the end of JSRuntime. In this
+ * way there is no need to recompile all the code that refers to other
+ * fields of JSRuntime after enabling the corresponding metering macro.
+ */
+#ifdef JS_DUMP_ENUM_CACHE_STATS
+ int32 nativeEnumProbes;
+ int32 nativeEnumMisses;
+# define ENUM_CACHE_METER(name) JS_ATOMIC_INCREMENT(&cx->runtime->name)
+#else
+# define ENUM_CACHE_METER(name) ((void) 0)
+#endif
+
+#ifdef JS_DUMP_LOOP_STATS
+ /* Loop statistics, to trigger trace recording and compiling. */
+ JSBasicStats loopStats;
+#endif
+
+#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
+ /* Function invocation metering. */
+ jsrefcount inlineCalls;
+ jsrefcount nativeCalls;
+ jsrefcount nonInlineCalls;
+ jsrefcount constructs;
+
+ /* Title lock and scope property metering. */
+ jsrefcount claimAttempts;
+ jsrefcount claimedTitles;
+ jsrefcount deadContexts;
+ jsrefcount deadlocksAvoided;
+ jsrefcount liveScopes;
+ jsrefcount sharedTitles;
+ jsrefcount totalScopes;
+ jsrefcount liveScopeProps;
+ jsrefcount liveScopePropsPreSweep;
+ jsrefcount totalScopeProps;
+ jsrefcount livePropTreeNodes;
+ jsrefcount duplicatePropTreeNodes;
+ jsrefcount totalPropTreeNodes;
+ jsrefcount propTreeKidsChunks;
+ jsrefcount middleDeleteFixups;
+
+ /* String instrumentation. */
+ jsrefcount liveStrings;
+ jsrefcount totalStrings;
+ jsrefcount liveDependentStrings;
+ jsrefcount totalDependentStrings;
+ jsrefcount badUndependStrings;
+ double lengthSum;
+ double lengthSquaredSum;
+ double strdepLengthSum;
+ double strdepLengthSquaredSum;
+#endif /* DEBUG || JS_DUMP_PROPTREE_STATS */
+
+#ifdef JS_SCOPE_DEPTH_METER
+ /*
+ * Stats on runtime prototype chain lookups and scope chain depths, i.e.,
+ * counts of objects traversed on a chain until the wanted id is found.
+ */
+ JSBasicStats protoLookupDepthStats;
+ JSBasicStats scopeSearchDepthStats;
+
+ /*
+ * Stats on compile-time host environment and lexical scope chain lengths
+ * (maximum depths).
+ */
+ JSBasicStats hostenvScopeDepthStats;
+ JSBasicStats lexicalScopeDepthStats;
+#endif
+
+#ifdef JS_GCMETER
+ JSGCStats gcStats;
+#endif
+};
+
+#ifdef DEBUG
+# define JS_RUNTIME_METER(rt, which) JS_ATOMIC_INCREMENT(&(rt)->which)
+# define JS_RUNTIME_UNMETER(rt, which) JS_ATOMIC_DECREMENT(&(rt)->which)
+#else
+# define JS_RUNTIME_METER(rt, which) /* nothing */
+# define JS_RUNTIME_UNMETER(rt, which) /* nothing */
+#endif
+
+#define JS_KEEP_ATOMS(rt) JS_ATOMIC_INCREMENT(&(rt)->gcKeepAtoms);
+#define JS_UNKEEP_ATOMS(rt) JS_ATOMIC_DECREMENT(&(rt)->gcKeepAtoms);
+
+#ifdef JS_ARGUMENT_FORMATTER_DEFINED
+/*
+ * Linked list mapping format strings for JS_{Convert,Push}Arguments{,VA} to
+ * formatter functions. Elements are sorted in non-increasing format string
+ * length order.
+ */
+struct JSArgumentFormatMap {
+ const char *format;
+ size_t length;
+ JSArgumentFormatter formatter;
+ JSArgumentFormatMap *next;
+};
+#endif
+
+struct JSStackHeader {
+ uintN nslots;
+ JSStackHeader *down;
+};
+
+#define JS_STACK_SEGMENT(sh) ((jsval *)(sh) + 2)
+
+/*
+ * Key and entry types for the JSContext.resolvingTable hash table, typedef'd
+ * here because all consumers need to see these declarations (and not just the
+ * typedef names, as would be the case for an opaque pointer-to-typedef'd-type
+ * declaration), along with cx->resolvingTable.
+ */
+typedef struct JSResolvingKey {
+ JSObject *obj;
+ jsid id;
+} JSResolvingKey;
+
+typedef struct JSResolvingEntry {
+ JSDHashEntryHdr hdr;
+ JSResolvingKey key;
+ uint32 flags;
+} JSResolvingEntry;
+
+#define JSRESFLAG_LOOKUP 0x1 /* resolving id from lookup */
+#define JSRESFLAG_WATCH 0x2 /* resolving id from watch */
+
+typedef struct JSLocalRootChunk JSLocalRootChunk;
+
+#define JSLRS_CHUNK_SHIFT 8
+#define JSLRS_CHUNK_SIZE JS_BIT(JSLRS_CHUNK_SHIFT)
+#define JSLRS_CHUNK_MASK JS_BITMASK(JSLRS_CHUNK_SHIFT)
+
+struct JSLocalRootChunk {
+ jsval roots[JSLRS_CHUNK_SIZE];
+ JSLocalRootChunk *down;
+};
+
+typedef struct JSLocalRootStack {
+ uint32 scopeMark;
+ uint32 rootCount;
+ JSLocalRootChunk *topChunk;
+ JSLocalRootChunk firstChunk;
+} JSLocalRootStack;
+
+#define JSLRS_NULL_MARK ((uint32) -1)
+
+/*
+ * Macros to push/pop JSTempValueRooter instances to context-linked stack of
+ * temporary GC roots. If you need to protect a result value that flows out of
+ * a C function across several layers of other functions, use the
+ * js_LeaveLocalRootScopeWithResult internal API (see further below) instead.
+ *
+ * The macros also provide a simple way to get a single rooted pointer via
+ * JS_PUSH_TEMP_ROOT_<KIND>(cx, NULL, &tvr). Then &tvr.u.<kind> gives the
+ * necessary pointer.
+ *
+ * JSTempValueRooter.count defines the type of the rooted value referenced by
+ * JSTempValueRooter.u union of type JSTempValueUnion. When count is positive
+ * or zero, u.array points to a vector of jsvals. Otherwise it must be one of
+ * the following constants:
+ */
+#define JSTVU_SINGLE (-1) /* u.value or u.<gcthing> is single jsval
+ or GC-thing */
+#define JSTVU_TRACE (-2) /* u.trace is a hook to trace a custom
+ * structure */
+#define JSTVU_SPROP (-3) /* u.sprop roots property tree node */
+#define JSTVU_WEAK_ROOTS (-4) /* u.weakRoots points to saved weak roots */
+#define JSTVU_PARSE_CONTEXT (-5) /* u.parseContext roots JSParseContext* */
+#define JSTVU_SCRIPT (-6) /* u.script roots JSScript* */
+
+/*
+ * Here single JSTVU_SINGLE covers both jsval and pointers to any GC-thing via
+ * reinterpreting the thing as JSVAL_OBJECT. It works because the GC-thing is
+ * aligned on a 0 mod 8 boundary, and object has the 0 jsval tag. So any
+ * GC-thing may be tagged as if it were an object and untagged, if it's then
+ * used only as an opaque pointer until discriminated by other means than tag
+ * bits. This is how, for example, js_GetGCThingTraceKind uses its |thing|
+ * parameter -- it consults GC-thing flags stored separately from the thing to
+ * decide the kind of thing.
+ *
+ * The following checks that this type-punning is possible.
+ */
+JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(jsval));
+JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(void *));
+
+#define JS_PUSH_TEMP_ROOT_COMMON(cx,x,tvr,cnt,kind) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT((cx)->tempValueRooters != (tvr)); \
+ (tvr)->count = (cnt); \
+ (tvr)->u.kind = (x); \
+ (tvr)->down = (cx)->tempValueRooters; \
+ (cx)->tempValueRooters = (tvr); \
+ JS_END_MACRO
+
+#define JS_POP_TEMP_ROOT(cx,tvr) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT((cx)->tempValueRooters == (tvr)); \
+ (cx)->tempValueRooters = (tvr)->down; \
+ JS_END_MACRO
+
+#define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT((int)(cnt) >= 0); \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, arr, tvr, (ptrdiff_t) (cnt), array); \
+ JS_END_MACRO
+
+#define JS_PUSH_SINGLE_TEMP_ROOT(cx,val,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, val, tvr, JSTVU_SINGLE, value)
+
+#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, obj, tvr, JSTVU_SINGLE, object)
+
+#define JS_PUSH_TEMP_ROOT_STRING(cx,str,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, str, tvr, JSTVU_SINGLE, string)
+
+#define JS_PUSH_TEMP_ROOT_XML(cx,xml_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, xml_, tvr, JSTVU_SINGLE, xml)
+
+#define JS_PUSH_TEMP_ROOT_TRACE(cx,trace_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, trace_, tvr, JSTVU_TRACE, trace)
+
+#define JS_PUSH_TEMP_ROOT_SPROP(cx,sprop_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, sprop_, tvr, JSTVU_SPROP, sprop)
+
+#define JS_PUSH_TEMP_ROOT_WEAK_COPY(cx,weakRoots_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, weakRoots_, tvr, JSTVU_WEAK_ROOTS, weakRoots)
+
+#define JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx,pc,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, pc, tvr, JSTVU_PARSE_CONTEXT, parseContext)
+
+#define JS_PUSH_TEMP_ROOT_SCRIPT(cx,script_,tvr) \
+ JS_PUSH_TEMP_ROOT_COMMON(cx, script_, tvr, JSTVU_SCRIPT, script)
+
+
+#define JSRESOLVE_INFER 0xffff /* infer bits from current bytecode */
+
+struct JSContext {
+ /* JSRuntime contextList linkage. */
+ JSCList links;
+
+ /*
+ * Operation count. It is declared early in the structure as a frequently
+ * accessed field.
+ */
+ int32 operationCount;
+
+#if JS_HAS_XML_SUPPORT
+ /*
+ * Bit-set formed from binary exponentials of the XML_* tiny-ids defined
+ * for boolean settings in jsxml.c, plus an XSF_CACHE_VALID bit. Together
+ * these act as a cache of the boolean XML.ignore* and XML.prettyPrinting
+ * property values associated with this context's global object.
+ */
+ uint8 xmlSettingFlags;
+ uint8 padding;
+#else
+ uint16 padding;
+#endif
+
+ /*
+ * Classic Algol "display" static link optimization.
+ */
+#define JS_DISPLAY_SIZE 16
+
+ JSStackFrame *display[JS_DISPLAY_SIZE];
+
+ /* Runtime version control identifier. */
+ uint16 version;
+
+ /* Per-context options. */
+ uint32 options; /* see jsapi.h for JSOPTION_* */
+
+ /* Locale specific callbacks for string conversion. */
+ JSLocaleCallbacks *localeCallbacks;
+
+ /*
+ * cx->resolvingTable is non-null and non-empty if we are initializing
+ * standard classes lazily, or if we are otherwise recursing indirectly
+ * from js_LookupProperty through a JSClass.resolve hook. It is used to
+ * limit runaway recursion (see jsapi.c and jsobj.c).
+ */
+ JSDHashTable *resolvingTable;
+
+#if JS_HAS_LVALUE_RETURN
+ /*
+ * Secondary return value from native method called on the left-hand side
+ * of an assignment operator. The native should store the object in which
+ * to set a property in *rval, and return the property's id expressed as a
+ * jsval by calling JS_SetCallReturnValue2(cx, idval).
+ */
+ jsval rval2;
+ JSPackedBool rval2set;
+#endif
+
+ /*
+ * True if generating an error, to prevent runaway recursion.
+ * NB: generatingError packs with rval2set, #if JS_HAS_LVALUE_RETURN;
+ * with insideGCMarkCallback and with throwing below.
+ */
+ JSPackedBool generatingError;
+
+ /* Flag to indicate that we run inside gcCallback(cx, JSGC_MARK_END). */
+ JSPackedBool insideGCMarkCallback;
+
+ /* Exception state -- the exception member is a GC root by definition. */
+ JSPackedBool throwing; /* is there a pending exception? */
+ jsval exception; /* most-recently-thrown exception */
+
+ /* Limit pointer for checking native stack consumption during recursion. */
+ jsuword stackLimit;
+
+ /* Quota on the size of arenas used to compile and execute scripts. */
+ size_t scriptStackQuota;
+
+ /* Data shared by threads in an address space. */
+ JSRuntime *runtime;
+
+ /* Stack arena pool and frame pointer register. */
+ JSArenaPool stackPool;
+ JSStackFrame *fp;
+
+ /* Temporary arena pool used while compiling and decompiling. */
+ JSArenaPool tempPool;
+
+ /* Top-level object and pointer to top stack frame's scope chain. */
+ JSObject *globalObject;
+
+ /* Storage to root recently allocated GC things and script result. */
+ JSWeakRoots weakRoots;
+
+ /* Regular expression class statics (XXX not shared globally). */
+ JSRegExpStatics regExpStatics;
+
+ /* State for object and array toSource conversion. */
+ JSSharpObjectMap sharpObjectMap;
+
+ /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
+ JSArgumentFormatMap *argumentFormatMap;
+
+ /* Last message string and trace file for debugging. */
+ char *lastMessage;
+#ifdef DEBUG
+ void *tracefp;
+#endif
+
+ /* Per-context optional error reporter. */
+ JSErrorReporter errorReporter;
+
+ /*
+ * Flag indicating that the operation callback is set. When the flag is 0
+ * but operationCallback is not null, operationCallback stores the branch
+ * callback.
+ */
+ uint32 operationCallbackIsSet : 1;
+ uint32 operationLimit : 31;
+ JSOperationCallback operationCallback;
+
+ /* Interpreter activation count. */
+ uintN interpLevel;
+
+ /* Client opaque pointers. */
+ void *data;
+ void *data2;
+
+ /* GC and thread-safe state. */
+ JSStackFrame *dormantFrameChain; /* dormant stack frame to scan */
+#ifdef JS_THREADSAFE
+ JSThread *thread;
+ jsrefcount requestDepth;
+ /* Same as requestDepth but ignoring JS_SuspendRequest/JS_ResumeRequest */
+ jsrefcount outstandingRequests;
+ JSTitle *titleToShare; /* weak reference, see jslock.c */
+ JSTitle *lockedSealedTitle; /* weak ref, for low-cost sealed
+ title locking */
+ JSCList threadLinks; /* JSThread contextList linkage */
+
+#define CX_FROM_THREAD_LINKS(tl) \
+ ((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks)))
+#endif
+
+ /* PDL of stack headers describing stack slots not rooted by argv, etc. */
+ JSStackHeader *stackHeaders;
+
+ /* Optional stack of heap-allocated scoped local GC roots. */
+ JSLocalRootStack *localRootStack;
+
+ /* Stack of thread-stack-allocated temporary GC roots. */
+ JSTempValueRooter *tempValueRooters;
+
+#ifdef JS_THREADSAFE
+ JSGCFreeListSet *gcLocalFreeLists;
+#endif
+
+ /* List of pre-allocated doubles. */
+ JSGCDoubleCell *doubleFreeList;
+
+ /* Debug hooks associated with the current context. */
+ JSDebugHooks *debugHooks;
+
+ /* Security callbacks that override any defined on the runtime. */
+ JSSecurityCallbacks *securityCallbacks;
+
+ /* Pinned regexp pool used for regular expressions. */
+ JSArenaPool regexpPool;
+
+ /* Stored here to avoid passing it around as a parameter. */
+ uintN resolveFlags;
+};
+
+#ifdef JS_THREADSAFE
+# define JS_THREAD_ID(cx) ((cx)->thread ? (cx)->thread->id : 0)
+#endif
+
+#ifdef __cplusplus
+/* FIXME(bug 332648): Move this into a public header. */
+class JSAutoTempValueRooter
+{
+ public:
+ JSAutoTempValueRooter(JSContext *cx, size_t len, jsval *vec)
+ : mContext(cx) {
+ JS_PUSH_TEMP_ROOT(mContext, len, vec, &mTvr);
+ }
+ JSAutoTempValueRooter(JSContext *cx, jsval v)
+ : mContext(cx) {
+ JS_PUSH_SINGLE_TEMP_ROOT(mContext, v, &mTvr);
+ }
+
+ ~JSAutoTempValueRooter() {
+ JS_POP_TEMP_ROOT(mContext, &mTvr);
+ }
+
+ protected:
+ JSContext *mContext;
+
+ private:
+#ifndef AIX
+ static void *operator new(size_t);
+ static void operator delete(void *, size_t);
+#endif
+
+ JSTempValueRooter mTvr;
+};
+
+class JSAutoResolveFlags
+{
+ public:
+ JSAutoResolveFlags(JSContext *cx, uintN flags)
+ : mContext(cx), mSaved(cx->resolveFlags) {
+ cx->resolveFlags = flags;
+ }
+
+ ~JSAutoResolveFlags() { mContext->resolveFlags = mSaved; }
+
+ private:
+ JSContext *mContext;
+ uintN mSaved;
+};
+#endif
+
+/*
+ * Slightly more readable macros for testing per-context option settings (also
+ * to hide bitset implementation detail).
+ *
+ * JSOPTION_XML must be handled specially in order to propagate from compile-
+ * to run-time (from cx->options to script->version/cx->version). To do that,
+ * we copy JSOPTION_XML from cx->options into cx->version as JSVERSION_HAS_XML
+ * whenever options are set, and preserve this XML flag across version number
+ * changes done via the JS_SetVersion API.
+ *
+ * But when executing a script or scripted function, the interpreter changes
+ * cx->version, including the XML flag, to script->version. Thus JSOPTION_XML
+ * is a compile-time option that causes a run-time version change during each
+ * activation of the compiled script. That version change has the effect of
+ * changing JS_HAS_XML_OPTION, so that any compiling done via eval enables XML
+ * support. If an XML-enabled script or function calls a non-XML function,
+ * the flag bit will be cleared during the callee's activation.
+ *
+ * Note that JS_SetVersion API calls never pass JSVERSION_HAS_XML or'd into
+ * that API's version parameter.
+ *
+ * Note also that script->version must contain this XML option flag in order
+ * for XDR'ed scripts to serialize and deserialize with that option preserved
+ * for detection at run-time. We can't copy other compile-time options into
+ * script->version because that would break backward compatibility (certain
+ * other options, e.g. JSOPTION_VAROBJFIX, are analogous to JSOPTION_XML).
+ */
+#define JS_HAS_OPTION(cx,option) (((cx)->options & (option)) != 0)
+#define JS_HAS_STRICT_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_STRICT)
+#define JS_HAS_WERROR_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_WERROR)
+#define JS_HAS_COMPILE_N_GO_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_COMPILE_N_GO)
+#define JS_HAS_ATLINE_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_ATLINE)
+
+#define JSVERSION_MASK 0x0FFF /* see JSVersion in jspubtd.h */
+#define JSVERSION_HAS_XML 0x1000 /* flag induced by XML option */
+
+#define JSVERSION_NUMBER(cx) ((JSVersion)((cx)->version & \
+ JSVERSION_MASK))
+#define JS_HAS_XML_OPTION(cx) ((cx)->version & JSVERSION_HAS_XML || \
+ JSVERSION_NUMBER(cx) >= JSVERSION_1_6)
+
+/*
+ * Initialize a library-wide thread private data index, and remember that it
+ * has already been done, so that it happens only once ever. Returns true on
+ * success.
+ */
+extern JSBool
+js_InitThreadPrivateIndex(void (*ptr)(void *));
+
+/*
+ * Common subroutine of JS_SetVersion and js_SetVersion, to update per-context
+ * data that depends on version.
+ */
+extern void
+js_OnVersionChange(JSContext *cx);
+
+/*
+ * Unlike the JS_SetVersion API, this function stores JSVERSION_HAS_XML and
+ * any future non-version-number flags induced by compiler options.
+ */
+extern void
+js_SetVersion(JSContext *cx, JSVersion version);
+
+/*
+ * Create and destroy functions for JSContext, which is manually allocated
+ * and exclusively owned.
+ */
+extern JSContext *
+js_NewContext(JSRuntime *rt, size_t stackChunkSize);
+
+extern void
+js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
+
+/*
+ * Return true if cx points to a context in rt->contextList, else return false.
+ * NB: the caller (see jslock.c:ClaimTitle) must hold rt->gcLock.
+ */
+extern JSBool
+js_ValidContextPointer(JSRuntime *rt, JSContext *cx);
+
+/*
+ * If unlocked, acquire and release rt->gcLock around *iterp update; otherwise
+ * the caller must be holding rt->gcLock.
+ */
+extern JSContext *
+js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
+
+/*
+ * JSClass.resolve and watchpoint recursion damping machinery.
+ */
+extern JSBool
+js_StartResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry **entryp);
+
+extern void
+js_StopResolving(JSContext *cx, JSResolvingKey *key, uint32 flag,
+ JSResolvingEntry *entry, uint32 generation);
+
+/*
+ * Local root set management.
+ *
+ * NB: the jsval parameters below may be properly tagged jsvals, or GC-thing
+ * pointers cast to (jsval). This relies on JSObject's tag being zero, but
+ * on the up side it lets us push int-jsval-encoded scopeMark values on the
+ * local root stack.
+ */
+extern JSBool
+js_EnterLocalRootScope(JSContext *cx);
+
+#define js_LeaveLocalRootScope(cx) \
+ js_LeaveLocalRootScopeWithResult(cx, JSVAL_NULL)
+
+extern void
+js_LeaveLocalRootScopeWithResult(JSContext *cx, jsval rval);
+
+extern void
+js_ForgetLocalRoot(JSContext *cx, jsval v);
+
+extern int
+js_PushLocalRoot(JSContext *cx, JSLocalRootStack *lrs, jsval v);
+
+extern void
+js_TraceLocalRoots(JSTracer *trc, JSLocalRootStack *lrs);
+
+/*
+ * Report an exception, which is currently realized as a printf-style format
+ * string and its arguments.
+ */
+typedef enum JSErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+ name = number,
+#include "js.msg"
+#undef MSG_DEF
+ JSErr_Limit
+} JSErrNum;
+
+extern JS_FRIEND_API(const JSErrorFormatString *)
+js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
+
+#ifdef va_start
+extern JSBool
+js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap);
+
+extern JSBool
+js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ JSBool charArgs, va_list ap);
+
+extern JSBool
+js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
+ void *userRef, const uintN errorNumber,
+ char **message, JSErrorReport *reportp,
+ JSBool *warningp, JSBool charArgs, va_list ap);
+#endif
+
+extern void
+js_ReportOutOfMemory(JSContext *cx);
+
+/*
+ * Report that cx->scriptStackQuota is exhausted.
+ */
+extern void
+js_ReportOutOfScriptQuota(JSContext *cx);
+
+extern void
+js_ReportOverRecursed(JSContext *cx);
+
+extern void
+js_ReportAllocationOverflow(JSContext *cx);
+
+#define JS_CHECK_RECURSION(cx, onerror) \
+ JS_BEGIN_MACRO \
+ int stackDummy_; \
+ \
+ if (!JS_CHECK_STACK_SIZE(cx, stackDummy_)) { \
+ js_ReportOverRecursed(cx); \
+ onerror; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Report an exception using a previously composed JSErrorReport.
+ * XXXbe remove from "friend" API
+ */
+extern JS_FRIEND_API(void)
+js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *report);
+
+extern void
+js_ReportIsNotDefined(JSContext *cx, const char *name);
+
+/*
+ * Report an attempt to access the property of a null or undefined value (v).
+ */
+extern JSBool
+js_ReportIsNullOrUndefined(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback);
+
+extern void
+js_ReportMissingArg(JSContext *cx, jsval *vp, uintN arg);
+
+/*
+ * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
+ * the first argument for the error message. If the error message has less
+ * then 3 arguments, use null for arg1 or arg2.
+ */
+extern JSBool
+js_ReportValueErrorFlags(JSContext *cx, uintN flags, const uintN errorNumber,
+ intN spindex, jsval v, JSString *fallback,
+ const char *arg1, const char *arg2);
+
+#define js_ReportValueError(cx,errorNumber,spindex,v,fallback) \
+ ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
+ spindex, v, fallback, NULL, NULL))
+
+#define js_ReportValueError2(cx,errorNumber,spindex,v,fallback,arg1) \
+ ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
+ spindex, v, fallback, arg1, NULL))
+
+#define js_ReportValueError3(cx,errorNumber,spindex,v,fallback,arg1,arg2) \
+ ((void)js_ReportValueErrorFlags(cx, JSREPORT_ERROR, errorNumber, \
+ spindex, v, fallback, arg1, arg2))
+
+extern JSErrorFormatString js_ErrorFormatString[JSErr_Limit];
+
+/*
+ * See JS_SetThreadStackLimit in jsapi.c, where we check that the stack grows
+ * in the expected direction. On Unix-y systems, JS_STACK_GROWTH_DIRECTION is
+ * computed on the build host by jscpucfg.c and written into jsautocfg.h. The
+ * macro is hardcoded in jscpucfg.h on Windows and Mac systems (for historical
+ * reasons pre-dating autoconf usage).
+ */
+#if JS_STACK_GROWTH_DIRECTION > 0
+# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) < (cx)->stackLimit)
+#else
+# define JS_CHECK_STACK_SIZE(cx, lval) ((jsuword)&(lval) > (cx)->stackLimit)
+#endif
+
+/*
+ * Update the operation counter according to the given weight and call the
+ * operation callback when we reach the operation limit. To make this
+ * frequently executed macro faster we decrease the counter from
+ * JSContext.operationLimit and compare against zero to check the limit.
+ *
+ * This macro can run the full GC. Return true if it is OK to continue and
+ * false otherwise.
+ */
+#define JS_CHECK_OPERATION_LIMIT(cx, weight) \
+ (JS_CHECK_OPERATION_WEIGHT(weight), \
+ (((cx)->operationCount -= (weight)) > 0 || js_ResetOperationCount(cx)))
+
+/*
+ * A version of JS_CHECK_OPERATION_LIMIT that just updates the operation count
+ * without calling the operation callback or any other API. This macro resets
+ * the count to 0 when it becomes negative to prevent a wrap-around when the
+ * macro is called repeatably.
+ */
+#define JS_COUNT_OPERATION(cx, weight) \
+ ((void)(JS_CHECK_OPERATION_WEIGHT(weight), \
+ (cx)->operationCount = ((cx)->operationCount > 0) \
+ ? (cx)->operationCount - (weight) \
+ : 0))
+
+/*
+ * The implementation of the above macros assumes that subtracting weights
+ * twice from a positive number does not wrap-around INT32_MIN.
+ */
+#define JS_CHECK_OPERATION_WEIGHT(weight) \
+ (JS_ASSERT((uint32) (weight) > 0), \
+ JS_ASSERT((uint32) (weight) < JS_BIT(30)))
+
+/* Relative operations weights. */
+#define JSOW_JUMP 1
+#define JSOW_ALLOCATION 100
+#define JSOW_LOOKUP_PROPERTY 5
+#define JSOW_GET_PROPERTY 10
+#define JSOW_SET_PROPERTY 20
+#define JSOW_NEW_PROPERTY 200
+#define JSOW_DELETE_PROPERTY 30
+#define JSOW_ENTER_SHARP JS_OPERATION_WEIGHT_BASE
+#define JSOW_SCRIPT_JUMP JS_OPERATION_WEIGHT_BASE
+
+/*
+ * Reset the operation count and call the operation callback assuming that the
+ * operation limit is reached.
+ */
+extern JSBool
+js_ResetOperationCount(JSContext *cx);
+
+JS_END_EXTERN_C
+
+#endif /* jscntxt_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscompat.h b/tools/node_modules/expresso/deps/jscoverage/js/jscompat.h
new file mode 100644
index 0000000..80d8605
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscompat.h
@@ -0,0 +1,57 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* -*- Mode: C; tab-width: 8 -*-
+ * Copyright (C) 1996-1999 Netscape Communications Corporation, All Rights Reserved.
+ */
+#ifndef jscompat_h___
+#define jscompat_h___
+/*
+ * Compatibility glue for various NSPR versions. We must always define int8,
+ * int16, jsword, and so on to minimize differences with js/ref, no matter what
+ * the NSPR typedef names may be.
+ */
+#include "jstypes.h"
+#include "jslong.h"
+
+typedef JSIntn intN;
+typedef JSUintn uintN;
+typedef JSUword jsuword;
+typedef JSWord jsword;
+typedef float float32;
+#define allocPriv allocPool
+#endif /* jscompat_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk b/tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk
new file mode 100644
index 0000000..1aeb75f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsconfig.mk
@@ -0,0 +1,181 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+ifndef OBJDIR
+ ifdef OBJDIR_NAME
+ OBJDIR = $(OBJDIR_NAME)
+ endif
+endif
+
+NSPR_VERSION = v4.0
+NSPR_LIBSUFFIX = 4
+
+NSPR_LOCAL = $(MOZ_DEPTH)/dist/$(OBJDIR)/nspr
+NSPR_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
+NSPR_OBJDIR = $(OBJDIR)
+ifeq ($(OS_ARCH), SunOS)
+ NSPR_OBJDIR := $(subst _sparc,,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_ARCH), Linux)
+ LINUX_REL := $(shell uname -r)
+ ifneq (,$(findstring 2.0,$(LINUX_REL)))
+ NSPR_OBJDIR := $(subst _All,2.0_x86_glibc_PTH,$(NSPR_OBJDIR))
+ else
+ NSPR_OBJDIR := $(subst _All,2.2_x86_glibc_PTH,$(NSPR_OBJDIR))
+ endif
+endif
+ifeq ($(OS_ARCH), AIX)
+ NSPR_OBJDIR := $(subst 4.1,4.2,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_CONFIG), IRIX6.2)
+ NSPR_OBJDIR := $(subst 6.2,6.2_n32_PTH,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_CONFIG), IRIX6.5)
+ NSPR_OBJDIR := $(subst 6.5,6.5_n32_PTH,$(NSPR_OBJDIR))
+endif
+ifeq ($(OS_ARCH), WINNT)
+ ifeq ($(OBJDIR), WIN32_D.OBJ)
+ NSPR_OBJDIR = WINNT4.0_DBG.OBJ
+ endif
+ ifeq ($(OBJDIR), WIN32_O.OBJ)
+ NSPR_OBJDIR = WINNT4.0_OPT.OBJ
+ endif
+endif
+NSPR_SHARED = /share/builds/components/nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
+ifeq ($(OS_ARCH), WINNT)
+ NSPR_SHARED = nspr20/$(NSPR_VERSION)/$(NSPR_OBJDIR)
+endif
+NSPR_VERSIONFILE = $(NSPR_LOCAL)/Version
+NSPR_CURVERSION := $(shell cat $(NSPR_VERSIONFILE) 2>/dev/null)
+
+get_nspr:
+ @echo "Grabbing NSPR component..."
+ifeq ($(NSPR_VERSION), $(NSPR_CURVERSION))
+ @echo "No need, NSPR is up to date in this tree (ver=$(NSPR_VERSION))."
+else
+ mkdir -p $(NSPR_LOCAL)
+ mkdir -p $(NSPR_DIST)
+ ifneq ($(OS_ARCH), WINNT)
+ cp $(NSPR_SHARED)/*.jar $(NSPR_LOCAL)
+ else
+ sh $(MOZ_DEPTH)/../reltools/compftp.sh $(NSPR_SHARED) $(NSPR_LOCAL) *.jar
+ endif
+ unzip -o $(NSPR_LOCAL)/mdbinary.jar -d $(NSPR_DIST)
+ mkdir -p $(NSPR_DIST)/include
+ unzip -o $(NSPR_LOCAL)/mdheader.jar -d $(NSPR_DIST)/include
+ rm -rf $(NSPR_DIST)/META-INF
+ rm -rf $(NSPR_DIST)/include/META-INF
+ echo $(NSPR_VERSION) > $(NSPR_VERSIONFILE)
+endif
+
+SHIP_DIST = $(MOZ_DEPTH)/dist/$(OBJDIR)
+SHIP_DIR = $(SHIP_DIST)/SHIP
+
+SHIP_LIBS = libjs.$(SO_SUFFIX) libjs.a
+ifdef JS_LIVECONNECT
+ SHIP_LIBS += libjsj.$(SO_SUFFIX) libjsj.a
+endif
+ifeq ($(OS_ARCH), WINNT)
+ SHIP_LIBS = js32.dll js32.lib
+ ifdef JS_LIVECONNECT
+ SHIP_LIBS += jsj.dll jsj.lib
+ endif
+endif
+SHIP_LIBS += $(LCJAR)
+SHIP_LIBS := $(addprefix $(SHIP_DIST)/lib/, $(SHIP_LIBS))
+
+SHIP_INCS = js*.h prmjtime.h resource.h *.msg *.tbl
+ifdef JS_LIVECONNECT
+ SHIP_INCS += netscape*.h nsC*.h nsI*.h
+endif
+SHIP_INCS := $(addprefix $(SHIP_DIST)/include/, $(SHIP_INCS))
+
+SHIP_BINS = js
+ifdef JS_LIVECONNECT
+ SHIP_BINS += lcshell
+endif
+ifeq ($(OS_ARCH), WINNT)
+ SHIP_BINS := $(addsuffix .exe, $(SHIP_BINS))
+endif
+SHIP_BINS := $(addprefix $(SHIP_DIST)/bin/, $(SHIP_BINS))
+
+ifdef BUILD_OPT
+ JSREFJAR = jsref_opt.jar
+else
+ifdef BUILD_IDG
+ JSREFJAR = jsref_idg.jar
+else
+ JSREFJAR = jsref_dbg.jar
+endif
+endif
+
+ship:
+ mkdir -p $(SHIP_DIR)/$(LIBDIR)
+ mkdir -p $(SHIP_DIR)/include
+ mkdir -p $(SHIP_DIR)/bin
+ cp $(SHIP_LIBS) $(SHIP_DIR)/$(LIBDIR)
+ cp $(SHIP_INCS) $(SHIP_DIR)/include
+ cp $(SHIP_BINS) $(SHIP_DIR)/bin
+ cd $(SHIP_DIR); \
+ zip -r $(JSREFJAR) bin lib include
+ifdef BUILD_SHIP
+ cp $(SHIP_DIR)/$(JSREFJAR) $(BUILD_SHIP)
+endif
+
+CWD = $(shell pwd)
+shipSource: $(SHIP_DIR)/jsref_src.lst .FORCE
+ mkdir -p $(SHIP_DIR)
+ cd $(MOZ_DEPTH)/.. ; \
+ zip $(CWD)/$(SHIP_DIR)/jsref_src.jar -@ < $(CWD)/$(SHIP_DIR)/jsref_src.lst
+ifdef BUILD_SHIP
+ cp $(SHIP_DIR)/jsref_src.jar $(BUILD_SHIP)
+endif
+
+JSREFSRCDIRS := $(shell cat $(DEPTH)/SpiderMonkey.rsp)
+$(SHIP_DIR)/jsref_src.lst: .FORCE
+ mkdir -p $(SHIP_DIR)
+ rm -f $@
+ touch $@
+ for d in $(JSREFSRCDIRS); do \
+ cd $(MOZ_DEPTH)/..; \
+ ls -1 -d $$d | grep -v CVS | grep -v \.OBJ >> $(CWD)/$@; \
+ cd $(CWD); \
+ done
+
+.FORCE:
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp
new file mode 100644
index 0000000..c41a47e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.cpp
@@ -0,0 +1,388 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Generate CPU-specific bit-size and similar #defines.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef CROSS_COMPILE
+#include <prtypes.h>
+#define INT64 PRInt64
+#else
+
+/************************************************************************/
+
+/* Generate cpucfg.h */
+
+#if defined(XP_WIN) || defined(XP_OS2)
+#ifdef WIN32
+#if defined(__GNUC__)
+#define INT64 long long
+#else
+#define INT64 _int64
+#endif /* __GNUC__ */
+#else
+#define INT64 long
+#endif
+#else
+#if defined(HPUX) || defined(__QNX__)
+#define INT64 long
+#else
+#define INT64 long long
+#endif
+#endif
+
+#endif /* CROSS_COMPILE */
+
+#ifdef __GNUC__
+#define NS_NEVER_INLINE __attribute__((noinline))
+#else
+#define NS_NEVER_INLINE
+#endif
+
+#ifdef __SUNPRO_C
+static int StackGrowthDirection(int *dummy1addr);
+#pragma no_inline(StackGrowthDirection)
+#endif
+
+typedef void *prword;
+
+struct align_short {
+ char c;
+ short a;
+};
+struct align_int {
+ char c;
+ int a;
+};
+struct align_long {
+ char c;
+ long a;
+};
+struct align_int64 {
+ char c;
+ INT64 a;
+};
+struct align_fakelonglong {
+ char c;
+ struct {
+ long hi, lo;
+ } a;
+};
+struct align_float {
+ char c;
+ float a;
+};
+struct align_double {
+ char c;
+ double a;
+};
+struct align_pointer {
+ char c;
+ void *a;
+};
+struct align_prword {
+ char c;
+ prword a;
+};
+
+#define ALIGN_OF(type) \
+ (((char*)&(((struct align_##type *)0)->a)) - ((char*)0))
+
+unsigned int bpb;
+
+static int Log2(unsigned int n)
+{
+ int log2 = 0;
+
+ if (n & (n-1))
+ log2++;
+ if (n >> 16)
+ log2 += 16, n >>= 16;
+ if (n >> 8)
+ log2 += 8, n >>= 8;
+ if (n >> 4)
+ log2 += 4, n >>= 4;
+ if (n >> 2)
+ log2 += 2, n >>= 2;
+ if (n >> 1)
+ log2++;
+ return log2;
+}
+
+/*
+ * Conceivably this could actually be used, but there is lots of code out
+ * there with ands and shifts in it that assumes a byte is exactly 8 bits,
+ * so forget about porting THIS code to all those non 8 bit byte machines.
+ */
+static void BitsPerByte(void)
+{
+ bpb = 8;
+}
+
+static int NS_NEVER_INLINE StackGrowthDirection(int *dummy1addr)
+{
+ int dummy2;
+
+ return (&dummy2 < dummy1addr) ? -1 : 1;
+}
+
+int main(int argc, char **argv)
+{
+ int sizeof_char, sizeof_short, sizeof_int, sizeof_int64, sizeof_long,
+ sizeof_float, sizeof_double, sizeof_word, sizeof_dword;
+ int bits_per_int64_log2, align_of_short, align_of_int, align_of_long,
+ align_of_int64, align_of_float, align_of_double, align_of_pointer,
+ align_of_word;
+ int dummy1;
+
+ BitsPerByte();
+
+ printf("#ifndef js_cpucfg___\n");
+ printf("#define js_cpucfg___\n\n");
+
+ printf("/* AUTOMATICALLY GENERATED - DO NOT EDIT */\n\n");
+
+#ifdef CROSS_COMPILE
+#if defined(IS_LITTLE_ENDIAN)
+ printf("#define IS_LITTLE_ENDIAN 1\n");
+ printf("#undef IS_BIG_ENDIAN\n\n");
+#elif defined(IS_BIG_ENDIAN)
+ printf("#undef IS_LITTLE_ENDIAN\n");
+ printf("#define IS_BIG_ENDIAN 1\n\n");
+#else
+#error "Endianess not defined."
+#endif
+
+ sizeof_char = PR_BYTES_PER_BYTE;
+ sizeof_short = PR_BYTES_PER_SHORT;
+ sizeof_int = PR_BYTES_PER_INT;
+ sizeof_int64 = PR_BYTES_PER_INT64;
+ sizeof_long = PR_BYTES_PER_LONG;
+ sizeof_float = PR_BYTES_PER_FLOAT;
+ sizeof_double = PR_BYTES_PER_DOUBLE;
+ sizeof_word = PR_BYTES_PER_WORD;
+ sizeof_dword = PR_BYTES_PER_DWORD;
+
+ bits_per_int64_log2 = PR_BITS_PER_INT64_LOG2;
+
+ align_of_short = PR_ALIGN_OF_SHORT;
+ align_of_int = PR_ALIGN_OF_INT;
+ align_of_long = PR_ALIGN_OF_LONG;
+ align_of_int64 = PR_ALIGN_OF_INT64;
+ align_of_float = PR_ALIGN_OF_FLOAT;
+ align_of_double = PR_ALIGN_OF_DOUBLE;
+ align_of_pointer = PR_ALIGN_OF_POINTER;
+ align_of_word = PR_ALIGN_OF_WORD;
+
+#else /* !CROSS_COMPILE */
+
+ /*
+ * We don't handle PDP-endian or similar orders: if a short is big-endian,
+ * so must int and long be big-endian for us to generate the IS_BIG_ENDIAN
+ * #define and the IS_LITTLE_ENDIAN #undef.
+ */
+ {
+ int big_endian = 0, little_endian = 0, ntests = 0;
+
+ if (sizeof(short) == 2) {
+ /* force |volatile| here to get rid of any compiler optimisations
+ * (var in register etc.) which may be appiled to |auto| vars -
+ * even those in |union|s...
+ * (|static| is used to get the same functionality for compilers
+ * which do not honor |volatile|...).
+ */
+ volatile static union {
+ short i;
+ char c[2];
+ } u;
+
+ u.i = 0x0102;
+ big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02);
+ little_endian += (u.c[0] == 0x02 && u.c[1] == 0x01);
+ ntests++;
+ }
+
+ if (sizeof(int) == 4) {
+ /* force |volatile| here ... */
+ volatile static union {
+ int i;
+ char c[4];
+ } u;
+
+ u.i = 0x01020304;
+ big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
+ u.c[2] == 0x03 && u.c[3] == 0x04);
+ little_endian += (u.c[0] == 0x04 && u.c[1] == 0x03 &&
+ u.c[2] == 0x02 && u.c[3] == 0x01);
+ ntests++;
+ }
+
+ if (sizeof(long) == 8) {
+ /* force |volatile| here ... */
+ volatile static union {
+ long i;
+ char c[8];
+ } u;
+
+ /*
+ * Write this as portably as possible: avoid 0x0102030405060708L
+ * and <<= 32.
+ */
+ u.i = 0x01020304;
+ u.i <<= 16, u.i <<= 16;
+ u.i |= 0x05060708;
+ big_endian += (u.c[0] == 0x01 && u.c[1] == 0x02 &&
+ u.c[2] == 0x03 && u.c[3] == 0x04 &&
+ u.c[4] == 0x05 && u.c[5] == 0x06 &&
+ u.c[6] == 0x07 && u.c[7] == 0x08);
+ little_endian += (u.c[0] == 0x08 && u.c[1] == 0x07 &&
+ u.c[2] == 0x06 && u.c[3] == 0x05 &&
+ u.c[4] == 0x04 && u.c[5] == 0x03 &&
+ u.c[6] == 0x02 && u.c[7] == 0x01);
+ ntests++;
+ }
+
+ if (big_endian && big_endian == ntests) {
+ printf("#undef IS_LITTLE_ENDIAN\n");
+ printf("#define IS_BIG_ENDIAN 1\n\n");
+ } else if (little_endian && little_endian == ntests) {
+ printf("#define IS_LITTLE_ENDIAN 1\n");
+ printf("#undef IS_BIG_ENDIAN\n\n");
+ } else {
+ fprintf(stderr, "%s: unknown byte order"
+ "(big_endian=%d, little_endian=%d, ntests=%d)!\n",
+ argv[0], big_endian, little_endian, ntests);
+ return EXIT_FAILURE;
+ }
+ }
+
+ sizeof_char = sizeof(char);
+ sizeof_short = sizeof(short);
+ sizeof_int = sizeof(int);
+ sizeof_int64 = 8;
+ sizeof_long = sizeof(long);
+ sizeof_float = sizeof(float);
+ sizeof_double = sizeof(double);
+ sizeof_word = sizeof(prword);
+ sizeof_dword = 8;
+
+ bits_per_int64_log2 = 6;
+
+ align_of_short = ALIGN_OF(short);
+ align_of_int = ALIGN_OF(int);
+ align_of_long = ALIGN_OF(long);
+ if (sizeof(INT64) < 8) {
+ /* this machine doesn't actually support int64's */
+ align_of_int64 = ALIGN_OF(fakelonglong);
+ } else {
+ align_of_int64 = ALIGN_OF(int64);
+ }
+ align_of_float = ALIGN_OF(float);
+ align_of_double = ALIGN_OF(double);
+ align_of_pointer = ALIGN_OF(pointer);
+ align_of_word = ALIGN_OF(prword);
+
+#endif /* CROSS_COMPILE */
+
+ printf("#define JS_BYTES_PER_BYTE %dL\n", sizeof_char);
+ printf("#define JS_BYTES_PER_SHORT %dL\n", sizeof_short);
+ printf("#define JS_BYTES_PER_INT %dL\n", sizeof_int);
+ printf("#define JS_BYTES_PER_INT64 %dL\n", sizeof_int64);
+ printf("#define JS_BYTES_PER_LONG %dL\n", sizeof_long);
+ printf("#define JS_BYTES_PER_FLOAT %dL\n", sizeof_float);
+ printf("#define JS_BYTES_PER_DOUBLE %dL\n", sizeof_double);
+ printf("#define JS_BYTES_PER_WORD %dL\n", sizeof_word);
+ printf("#define JS_BYTES_PER_DWORD %dL\n", sizeof_dword);
+ printf("\n");
+
+ printf("#define JS_BITS_PER_BYTE %dL\n", bpb);
+ printf("#define JS_BITS_PER_SHORT %dL\n", bpb * sizeof_short);
+ printf("#define JS_BITS_PER_INT %dL\n", bpb * sizeof_int);
+ printf("#define JS_BITS_PER_INT64 %dL\n", bpb * sizeof_int64);
+ printf("#define JS_BITS_PER_LONG %dL\n", bpb * sizeof_long);
+ printf("#define JS_BITS_PER_FLOAT %dL\n", bpb * sizeof_float);
+ printf("#define JS_BITS_PER_DOUBLE %dL\n", bpb * sizeof_double);
+ printf("#define JS_BITS_PER_WORD %dL\n", bpb * sizeof_word);
+ printf("\n");
+
+ printf("#define JS_BITS_PER_BYTE_LOG2 %dL\n", Log2(bpb));
+ printf("#define JS_BITS_PER_SHORT_LOG2 %dL\n", Log2(bpb * sizeof_short));
+ printf("#define JS_BITS_PER_INT_LOG2 %dL\n", Log2(bpb * sizeof_int));
+ printf("#define JS_BITS_PER_INT64_LOG2 %dL\n", bits_per_int64_log2);
+ printf("#define JS_BITS_PER_LONG_LOG2 %dL\n", Log2(bpb * sizeof_long));
+ printf("#define JS_BITS_PER_FLOAT_LOG2 %dL\n", Log2(bpb * sizeof_float));
+ printf("#define JS_BITS_PER_DOUBLE_LOG2 %dL\n", Log2(bpb * sizeof_double));
+ printf("#define JS_BITS_PER_WORD_LOG2 %dL\n", Log2(bpb * sizeof_word));
+ printf("\n");
+
+ printf("#define JS_ALIGN_OF_SHORT %dL\n", align_of_short);
+ printf("#define JS_ALIGN_OF_INT %dL\n", align_of_int);
+ printf("#define JS_ALIGN_OF_LONG %dL\n", align_of_long);
+ printf("#define JS_ALIGN_OF_INT64 %dL\n", align_of_int64);
+ printf("#define JS_ALIGN_OF_FLOAT %dL\n", align_of_float);
+ printf("#define JS_ALIGN_OF_DOUBLE %dL\n", align_of_double);
+ printf("#define JS_ALIGN_OF_POINTER %dL\n", align_of_pointer);
+ printf("#define JS_ALIGN_OF_WORD %dL\n", align_of_word);
+ printf("\n");
+
+ printf("#define JS_BYTES_PER_WORD_LOG2 %dL\n", Log2(sizeof_word));
+ printf("#define JS_BYTES_PER_DWORD_LOG2 %dL\n", Log2(sizeof_dword));
+ printf("#define JS_WORDS_PER_DWORD_LOG2 %dL\n", Log2(sizeof_dword/sizeof_word));
+ printf("\n");
+
+ printf("#define JS_STACK_GROWTH_DIRECTION (%d)\n", StackGrowthDirection(&dummy1));
+ printf("\n");
+
+ printf("#define JS_HAVE_LONG_LONG\n");
+ printf("\n");
+
+#if defined __GNUC__ && defined __x86_64__
+ printf("#define HAVE_VA_LIST_AS_ARRAY 1\n");
+ printf("\n");
+#endif
+
+ printf("#endif /* js_cpucfg___ */\n");
+
+ return EXIT_SUCCESS;
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h
new file mode 100644
index 0000000..c745e81
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jscpucfg.h
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_cpucfg___
+#define js_cpucfg___
+
+#define JS_HAVE_LONG_LONG
+
+#if defined(XP_WIN) || defined(XP_OS2) || defined(WINCE)
+
+#if defined(_WIN64)
+
+#if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 8L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 64L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 6L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 4L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 8L
+#define JS_ALIGN_OF_POINTER 8L
+#define JS_ALIGN_OF_WORD 8L
+
+#define JS_BYTES_PER_WORD_LOG2 3L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 0L
+#else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
+#error "CPU type is unknown"
+#endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
+
+#elif defined(_WIN32) || defined(XP_OS2) || defined(WINCE)
+
+#ifdef __WATCOMC__
+#define HAVE_VA_LIST_AS_ARRAY 1
+#endif
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 4L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 32L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 5L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 4L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 4L
+#define JS_ALIGN_OF_POINTER 4L
+#define JS_ALIGN_OF_WORD 4L
+
+#define JS_BYTES_PER_WORD_LOG2 2L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 1L
+#endif /* _WIN32 || XP_OS2 || WINCE*/
+
+#if defined(_WINDOWS) && !defined(_WIN32) /* WIN16 */
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 2L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 4L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 16L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 32L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 4L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 5L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 2L
+#define JS_ALIGN_OF_LONG 2L
+#define JS_ALIGN_OF_INT64 2L
+#define JS_ALIGN_OF_FLOAT 2L
+#define JS_ALIGN_OF_DOUBLE 2L
+#define JS_ALIGN_OF_POINTER 2L
+#define JS_ALIGN_OF_WORD 2L
+
+#define JS_BYTES_PER_WORD_LOG2 2L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define PR_WORDS_PER_DWORD_LOG2 1L
+
+#endif /* defined(_WINDOWS) && !defined(_WIN32) */
+
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+
+#error "This file is supposed to be auto-generated on UNIX platforms, but the"
+#error "static version for Mac and Windows platforms is being used."
+#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
+
+#else
+
+#error "Must define one of XP_BEOS, XP_OS2, XP_WIN, or XP_UNIX"
+
+#endif
+
+#ifndef JS_STACK_GROWTH_DIRECTION
+#define JS_STACK_GROWTH_DIRECTION (-1)
+#endif
+
+#endif /* js_cpucfg___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp
new file mode 100644
index 0000000..2fe7963
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.cpp
@@ -0,0 +1,2475 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS date methods.
+ */
+
+/*
+ * "For example, OS/360 devotes 26 bytes of the permanently
+ * resident date-turnover routine to the proper handling of
+ * December 31 on leap years (when it is Day 366). That
+ * might have been left to the operator."
+ *
+ * Frederick Brooks, 'The Second-System Effect'.
+ */
+
+#include "jsstddef.h"
+#include <ctype.h>
+#include <locale.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsprf.h"
+#include "prmjtime.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsversion.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsdate.h"
+#include "jsinterp.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsstr.h"
+
+/*
+ * The JS 'Date' object is patterned after the Java 'Date' object.
+ * Here is an script:
+ *
+ * today = new Date();
+ *
+ * print(today.toLocaleString());
+ *
+ * weekDay = today.getDay();
+ *
+ *
+ * These Java (and ECMA-262) methods are supported:
+ *
+ * UTC
+ * getDate (getUTCDate)
+ * getDay (getUTCDay)
+ * getHours (getUTCHours)
+ * getMinutes (getUTCMinutes)
+ * getMonth (getUTCMonth)
+ * getSeconds (getUTCSeconds)
+ * getMilliseconds (getUTCMilliseconds)
+ * getTime
+ * getTimezoneOffset
+ * getYear
+ * getFullYear (getUTCFullYear)
+ * parse
+ * setDate (setUTCDate)
+ * setHours (setUTCHours)
+ * setMinutes (setUTCMinutes)
+ * setMonth (setUTCMonth)
+ * setSeconds (setUTCSeconds)
+ * setMilliseconds (setUTCMilliseconds)
+ * setTime
+ * setYear (setFullYear, setUTCFullYear)
+ * toGMTString (toUTCString)
+ * toLocaleString
+ * toString
+ *
+ *
+ * These Java methods are not supported
+ *
+ * setDay
+ * before
+ * after
+ * equals
+ * hashCode
+ */
+
+/*
+ * 11/97 - jsdate.c has been rewritten to conform to the ECMA-262 language
+ * definition and reduce dependence on NSPR. NSPR is used to get the current
+ * time in milliseconds, the time zone offset, and the daylight savings time
+ * offset for a given time. NSPR is also used for Date.toLocaleString(), for
+ * locale-specific formatting, and to get a string representing the timezone.
+ * (Which turns out to be platform-dependent.)
+ *
+ * To do:
+ * (I did some performance tests by timing how long it took to run what
+ * I had of the js ECMA conformance tests.)
+ *
+ * - look at saving results across multiple calls to supporting
+ * functions; the toString functions compute some of the same values
+ * multiple times. Although - I took a quick stab at this, and I lost
+ * rather than gained. (Fractionally.) Hard to tell what compilers/processors
+ * are doing these days.
+ *
+ * - look at tweaking function return types to return double instead
+ * of int; this seems to make things run slightly faster sometimes.
+ * (though it could be architecture-dependent.) It'd be good to see
+ * how this does on win32. (Tried it on irix.) Types could use a
+ * general going-over.
+ */
+
+/*
+ * Supporting functions - ECMA 15.9.1.*
+ */
+
+#define HalfTimeDomain 8.64e15
+#define HoursPerDay 24.0
+#define MinutesPerDay (HoursPerDay * MinutesPerHour)
+#define MinutesPerHour 60.0
+#define SecondsPerDay (MinutesPerDay * SecondsPerMinute)
+#define SecondsPerHour (MinutesPerHour * SecondsPerMinute)
+#define SecondsPerMinute 60.0
+
+#if defined(XP_WIN) || defined(XP_OS2)
+/* Work around msvc double optimization bug by making these runtime values; if
+ * they're available at compile time, msvc optimizes division by them by
+ * computing the reciprocal and multiplying instead of dividing - this loses
+ * when the reciprocal isn't representable in a double.
+ */
+static jsdouble msPerSecond = 1000.0;
+static jsdouble msPerDay = SecondsPerDay * 1000.0;
+static jsdouble msPerHour = SecondsPerHour * 1000.0;
+static jsdouble msPerMinute = SecondsPerMinute * 1000.0;
+#else
+#define msPerDay (SecondsPerDay * msPerSecond)
+#define msPerHour (SecondsPerHour * msPerSecond)
+#define msPerMinute (SecondsPerMinute * msPerSecond)
+#define msPerSecond 1000.0
+#endif
+
+#define Day(t) floor((t) / msPerDay)
+
+static jsdouble
+TimeWithinDay(jsdouble t)
+{
+ jsdouble result;
+ result = fmod(t, msPerDay);
+ if (result < 0)
+ result += msPerDay;
+ return result;
+}
+
+#define DaysInYear(y) ((y) % 4 == 0 && ((y) % 100 || ((y) % 400 == 0)) \
+ ? 366 : 365)
+
+/* math here has to be f.p, because we need
+ * floor((1968 - 1969) / 4) == -1
+ */
+#define DayFromYear(y) (365 * ((y)-1970) + floor(((y)-1969)/4.0) \
+ - floor(((y)-1901)/100.0) + floor(((y)-1601)/400.0))
+#define TimeFromYear(y) (DayFromYear(y) * msPerDay)
+
+static jsint
+YearFromTime(jsdouble t)
+{
+ jsint y = (jsint) floor(t /(msPerDay*365.2425)) + 1970;
+ jsdouble t2 = (jsdouble) TimeFromYear(y);
+
+ if (t2 > t) {
+ y--;
+ } else {
+ if (t2 + msPerDay * DaysInYear(y) <= t)
+ y++;
+ }
+ return y;
+}
+
+#define InLeapYear(t) (JSBool) (DaysInYear(YearFromTime(t)) == 366)
+
+#define DayWithinYear(t, year) ((intN) (Day(t) - DayFromYear(year)))
+
+/*
+ * The following array contains the day of year for the first day of
+ * each month, where index 0 is January, and day 0 is January 1.
+ */
+static jsdouble firstDayOfMonth[2][12] = {
+ {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0},
+ {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0}
+};
+
+#define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m];
+
+static intN
+MonthFromTime(jsdouble t)
+{
+ intN d, step;
+ jsint year = YearFromTime(t);
+ d = DayWithinYear(t, year);
+
+ if (d < (step = 31))
+ return 0;
+ step += (InLeapYear(t) ? 29 : 28);
+ if (d < step)
+ return 1;
+ if (d < (step += 31))
+ return 2;
+ if (d < (step += 30))
+ return 3;
+ if (d < (step += 31))
+ return 4;
+ if (d < (step += 30))
+ return 5;
+ if (d < (step += 31))
+ return 6;
+ if (d < (step += 31))
+ return 7;
+ if (d < (step += 30))
+ return 8;
+ if (d < (step += 31))
+ return 9;
+ if (d < (step += 30))
+ return 10;
+ return 11;
+}
+
+static intN
+DateFromTime(jsdouble t)
+{
+ intN d, step, next;
+ jsint year = YearFromTime(t);
+ d = DayWithinYear(t, year);
+
+ if (d <= (next = 30))
+ return d + 1;
+ step = next;
+ next += (InLeapYear(t) ? 29 : 28);
+ if (d <= next)
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ if (d <= (next += 31))
+ return d - step;
+ step = next;
+ if (d <= (next += 30))
+ return d - step;
+ step = next;
+ return d - step;
+}
+
+static intN
+WeekDay(jsdouble t)
+{
+ jsint result;
+ result = (jsint) Day(t) + 4;
+ result = result % 7;
+ if (result < 0)
+ result += 7;
+ return (intN) result;
+}
+
+#define MakeTime(hour, min, sec, ms) \
+((((hour) * MinutesPerHour + (min)) * SecondsPerMinute + (sec)) * msPerSecond + (ms))
+
+static jsdouble
+MakeDay(jsdouble year, jsdouble month, jsdouble date)
+{
+ JSBool leap;
+ jsdouble yearday;
+ jsdouble monthday;
+
+ year += floor(month / 12);
+
+ month = fmod(month, 12.0);
+ if (month < 0)
+ month += 12;
+
+ leap = (DaysInYear((jsint) year) == 366);
+
+ yearday = floor(TimeFromYear(year) / msPerDay);
+ monthday = DayFromMonth(month, leap);
+
+ return yearday + monthday + date - 1;
+}
+
+#define MakeDate(day, time) ((day) * msPerDay + (time))
+
+/*
+ * Years and leap years on which Jan 1 is a Sunday, Monday, etc.
+ *
+ * yearStartingWith[0][i] is an example non-leap year where
+ * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc.
+ *
+ * yearStartingWith[1][i] is an example leap year where
+ * Jan 1 appears on Sunday (i == 0), Monday (i == 1), etc.
+ */
+static jsint yearStartingWith[2][7] = {
+ {1978, 1973, 1974, 1975, 1981, 1971, 1977},
+ {1984, 1996, 1980, 1992, 1976, 1988, 1972}
+};
+
+/*
+ * Find a year for which any given date will fall on the same weekday.
+ *
+ * This function should be used with caution when used other than
+ * for determining DST; it hasn't been proven not to produce an
+ * incorrect year for times near year boundaries.
+ */
+static jsint
+EquivalentYearForDST(jsint year)
+{
+ jsint day;
+ JSBool isLeapYear;
+
+ day = (jsint) DayFromYear(year) + 4;
+ day = day % 7;
+ if (day < 0)
+ day += 7;
+
+ isLeapYear = (DaysInYear(year) == 366);
+
+ return yearStartingWith[isLeapYear][day];
+}
+
+/* LocalTZA gets set by js_InitDateClass() */
+static jsdouble LocalTZA;
+
+static jsdouble
+DaylightSavingTA(jsdouble t)
+{
+ volatile int64 PR_t;
+ int64 ms2us;
+ int64 offset;
+ jsdouble result;
+
+ /* abort if NaN */
+ if (JSDOUBLE_IS_NaN(t))
+ return t;
+
+ /*
+ * If earlier than 1970 or after 2038, potentially beyond the ken of
+ * many OSes, map it to an equivalent year before asking.
+ */
+ if (t < 0.0 || t > 2145916800000.0) {
+ jsint year;
+ jsdouble day;
+
+ year = EquivalentYearForDST(YearFromTime(t));
+ day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
+ t = MakeDate(day, TimeWithinDay(t));
+ }
+
+ /* put our t in an LL, and map it to usec for prtime */
+ JSLL_D2L(PR_t, t);
+ JSLL_I2L(ms2us, PRMJ_USEC_PER_MSEC);
+ JSLL_MUL(PR_t, PR_t, ms2us);
+
+ offset = PRMJ_DSTOffset(PR_t);
+
+ JSLL_DIV(offset, offset, ms2us);
+ JSLL_L2D(result, offset);
+ return result;
+}
+
+
+#define AdjustTime(t) fmod(LocalTZA + DaylightSavingTA(t), msPerDay)
+
+#define LocalTime(t) ((t) + AdjustTime(t))
+
+static jsdouble
+UTC(jsdouble t)
+{
+ return t - AdjustTime(t - LocalTZA);
+}
+
+static intN
+HourFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay);
+ if (result < 0)
+ result += (intN)HoursPerDay;
+ return result;
+}
+
+static intN
+MinFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour);
+ if (result < 0)
+ result += (intN)MinutesPerHour;
+ return result;
+}
+
+static intN
+SecFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(floor(t / msPerSecond), SecondsPerMinute);
+ if (result < 0)
+ result += (intN)SecondsPerMinute;
+ return result;
+}
+
+static intN
+msFromTime(jsdouble t)
+{
+ intN result = (intN) fmod(t, msPerSecond);
+ if (result < 0)
+ result += (intN)msPerSecond;
+ return result;
+}
+
+#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
+ && !((d < 0 ? -d : d) > HalfTimeDomain)) \
+ ? js_DoubleToInteger(d + (+0.)) : *cx->runtime->jsNaN)
+
+/**
+ * end of ECMA 'support' functions
+ */
+
+/*
+ * Other Support routines and definitions
+ */
+
+/*
+ * We use the first reseved slot to store UTC time, and the second for caching
+ * the local time. The initial value of the cache entry is NaN.
+ */
+const uint32 JSSLOT_UTC_TIME = JSSLOT_PRIVATE;
+const uint32 JSSLOT_LOCAL_TIME = JSSLOT_PRIVATE + 1;
+
+const uint32 DATE_RESERVED_SLOTS = 2;
+
+JSClass js_DateClass = {
+ js_Date_str,
+ JSCLASS_HAS_RESERVED_SLOTS(DATE_RESERVED_SLOTS) |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Date),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+/* for use by date_parse */
+
+static const char* wtb[] = {
+ "am", "pm",
+ "monday", "tuesday", "wednesday", "thursday", "friday",
+ "saturday", "sunday",
+ "january", "february", "march", "april", "may", "june",
+ "july", "august", "september", "october", "november", "december",
+ "gmt", "ut", "utc",
+ "est", "edt",
+ "cst", "cdt",
+ "mst", "mdt",
+ "pst", "pdt"
+ /* time zone table needs to be expanded */
+};
+
+static int ttb[] = {
+ -1, -2, 0, 0, 0, 0, 0, 0, 0, /* AM/PM */
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 10000 + 0, 10000 + 0, 10000 + 0, /* GMT/UT/UTC */
+ 10000 + 5 * 60, 10000 + 4 * 60, /* EST/EDT */
+ 10000 + 6 * 60, 10000 + 5 * 60, /* CST/CDT */
+ 10000 + 7 * 60, 10000 + 6 * 60, /* MST/MDT */
+ 10000 + 8 * 60, 10000 + 7 * 60 /* PST/PDT */
+};
+
+/* helper for date_parse */
+static JSBool
+date_regionMatches(const char* s1, int s1off, const jschar* s2, int s2off,
+ int count, int ignoreCase)
+{
+ JSBool result = JS_FALSE;
+ /* return true if matches, otherwise, false */
+
+ while (count > 0 && s1[s1off] && s2[s2off]) {
+ if (ignoreCase) {
+ if (JS_TOLOWER((jschar)s1[s1off]) != JS_TOLOWER(s2[s2off])) {
+ break;
+ }
+ } else {
+ if ((jschar)s1[s1off] != s2[s2off]) {
+ break;
+ }
+ }
+ s1off++;
+ s2off++;
+ count--;
+ }
+
+ if (count == 0) {
+ result = JS_TRUE;
+ }
+
+ return result;
+}
+
+/* find UTC time from given date... no 1900 correction! */
+static jsdouble
+date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
+ jsdouble min, jsdouble sec, jsdouble msec)
+{
+ jsdouble day;
+ jsdouble msec_time;
+ jsdouble result;
+
+ day = MakeDay(year, mon, mday);
+ msec_time = MakeTime(hour, min, sec, msec);
+ result = MakeDate(day, msec_time);
+ return result;
+}
+
+/* compute the time in msec (unclipped) from the given args */
+#define MAXARGS 7
+
+static JSBool
+date_msecFromArgs(JSContext *cx, uintN argc, jsval *argv, jsdouble *rval)
+{
+ uintN loop;
+ jsdouble array[MAXARGS];
+ jsdouble d;
+ jsdouble msec_time;
+
+ for (loop = 0; loop < MAXARGS; loop++) {
+ if (loop < argc) {
+ d = js_ValueToNumber(cx, &argv[loop]);
+ if (JSVAL_IS_NULL(argv[loop]))
+ return JS_FALSE;
+ /* return NaN if any arg is not finite */
+ if (!JSDOUBLE_IS_FINITE(d)) {
+ *rval = *cx->runtime->jsNaN;
+ return JS_TRUE;
+ }
+ array[loop] = js_DoubleToInteger(d);
+ } else {
+ if (loop == 2) {
+ array[loop] = 1; /* Default the date argument to 1. */
+ } else {
+ array[loop] = 0;
+ }
+ }
+ }
+
+ /* adjust 2-digit years into the 20th century */
+ if (array[0] >= 0 && array[0] <= 99)
+ array[0] += 1900;
+
+ msec_time = date_msecFromDate(array[0], array[1], array[2],
+ array[3], array[4], array[5], array[6]);
+ *rval = msec_time;
+ return JS_TRUE;
+}
+
+/*
+ * See ECMA 15.9.4.[3-10];
+ */
+static JSBool
+date_UTC(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble msec_time;
+
+ if (!date_msecFromArgs(cx, argc, vp + 2, &msec_time))
+ return JS_FALSE;
+
+ msec_time = TIMECLIP(msec_time);
+
+ return js_NewNumberInRootedValue(cx, msec_time, vp);
+}
+
+static JSBool
+date_parseString(JSString *str, jsdouble *result)
+{
+ jsdouble msec;
+
+ const jschar *s;
+ size_t limit;
+ size_t i = 0;
+ int year = -1;
+ int mon = -1;
+ int mday = -1;
+ int hour = -1;
+ int min = -1;
+ int sec = -1;
+ int c = -1;
+ int n = -1;
+ int tzoffset = -1;
+ int prevc = 0;
+ JSBool seenplusminus = JS_FALSE;
+ int temp;
+ JSBool seenmonthname = JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, limit);
+ if (limit == 0)
+ goto syntax;
+ while (i < limit) {
+ c = s[i];
+ i++;
+ if (c <= ' ' || c == ',' || c == '-') {
+ if (c == '-' && '0' <= s[i] && s[i] <= '9') {
+ prevc = c;
+ }
+ continue;
+ }
+ if (c == '(') { /* comments) */
+ int depth = 1;
+ while (i < limit) {
+ c = s[i];
+ i++;
+ if (c == '(') depth++;
+ else if (c == ')')
+ if (--depth <= 0)
+ break;
+ }
+ continue;
+ }
+ if ('0' <= c && c <= '9') {
+ n = c - '0';
+ while (i < limit && '0' <= (c = s[i]) && c <= '9') {
+ n = n * 10 + c - '0';
+ i++;
+ }
+
+ /* allow TZA before the year, so
+ * 'Wed Nov 05 21:49:11 GMT-0800 1997'
+ * works */
+
+ /* uses of seenplusminus allow : in TZA, so Java
+ * no-timezone style of GMT+4:30 works
+ */
+
+ if ((prevc == '+' || prevc == '-')/* && year>=0 */) {
+ /* make ':' case below change tzoffset */
+ seenplusminus = JS_TRUE;
+
+ /* offset */
+ if (n < 24)
+ n = n * 60; /* EG. "GMT-3" */
+ else
+ n = n % 100 + n / 100 * 60; /* eg "GMT-0430" */
+ if (prevc == '+') /* plus means east of GMT */
+ n = -n;
+ if (tzoffset != 0 && tzoffset != -1)
+ goto syntax;
+ tzoffset = n;
+ } else if (prevc == '/' && mon >= 0 && mday >= 0 && year < 0) {
+ if (c <= ' ' || c == ',' || c == '/' || i >= limit)
+ year = n;
+ else
+ goto syntax;
+ } else if (c == ':') {
+ if (hour < 0)
+ hour = /*byte*/ n;
+ else if (min < 0)
+ min = /*byte*/ n;
+ else
+ goto syntax;
+ } else if (c == '/') {
+ /* until it is determined that mon is the actual
+ month, keep it as 1-based rather than 0-based */
+ if (mon < 0)
+ mon = /*byte*/ n;
+ else if (mday < 0)
+ mday = /*byte*/ n;
+ else
+ goto syntax;
+ } else if (i < limit && c != ',' && c > ' ' && c != '-' && c != '(') {
+ goto syntax;
+ } else if (seenplusminus && n < 60) { /* handle GMT-3:30 */
+ if (tzoffset < 0)
+ tzoffset -= n;
+ else
+ tzoffset += n;
+ } else if (hour >= 0 && min < 0) {
+ min = /*byte*/ n;
+ } else if (prevc == ':' && min >= 0 && sec < 0) {
+ sec = /*byte*/ n;
+ } else if (mon < 0) {
+ mon = /*byte*/n;
+ } else if (mon >= 0 && mday < 0) {
+ mday = /*byte*/ n;
+ } else if (mon >= 0 && mday >= 0 && year < 0) {
+ year = n;
+ } else {
+ goto syntax;
+ }
+ prevc = 0;
+ } else if (c == '/' || c == ':' || c == '+' || c == '-') {
+ prevc = c;
+ } else {
+ size_t st = i - 1;
+ int k;
+ while (i < limit) {
+ c = s[i];
+ if (!(('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')))
+ break;
+ i++;
+ }
+ if (i <= st + 1)
+ goto syntax;
+ for (k = JS_ARRAY_LENGTH(wtb); --k >= 0;)
+ if (date_regionMatches(wtb[k], 0, s, st, i-st, 1)) {
+ int action = ttb[k];
+ if (action != 0) {
+ if (action < 0) {
+ /*
+ * AM/PM. Count 12:30 AM as 00:30, 12:30 PM as
+ * 12:30, instead of blindly adding 12 if PM.
+ */
+ JS_ASSERT(action == -1 || action == -2);
+ if (hour > 12 || hour < 0) {
+ goto syntax;
+ } else {
+ if (action == -1 && hour == 12) { /* am */
+ hour = 0;
+ } else if (action == -2 && hour != 12) { /* pm */
+ hour += 12;
+ }
+ }
+ } else if (action <= 13) { /* month! */
+ /* Adjust mon to be 1-based until the final values
+ for mon, mday and year are adjusted below */
+ if (seenmonthname) {
+ goto syntax;
+ }
+ seenmonthname = JS_TRUE;
+ temp = /*byte*/ (action - 2) + 1;
+
+ if (mon < 0) {
+ mon = temp;
+ } else if (mday < 0) {
+ mday = mon;
+ mon = temp;
+ } else if (year < 0) {
+ year = mon;
+ mon = temp;
+ } else {
+ goto syntax;
+ }
+ } else {
+ tzoffset = action - 10000;
+ }
+ }
+ break;
+ }
+ if (k < 0)
+ goto syntax;
+ prevc = 0;
+ }
+ }
+ if (year < 0 || mon < 0 || mday < 0)
+ goto syntax;
+ /*
+ Case 1. The input string contains an English month name.
+ The form of the string can be month f l, or f month l, or
+ f l month which each evaluate to the same date.
+ If f and l are both greater than or equal to 70, or
+ both less than 70, the date is invalid.
+ The year is taken to be the greater of the values f, l.
+ If the year is greater than or equal to 70 and less than 100,
+ it is considered to be the number of years after 1900.
+ Case 2. The input string is of the form "f/m/l" where f, m and l are
+ integers, e.g. 7/16/45.
+ Adjust the mon, mday and year values to achieve 100% MSIE
+ compatibility.
+ a. If 0 <= f < 70, f/m/l is interpreted as month/day/year.
+ i. If year < 100, it is the number of years after 1900
+ ii. If year >= 100, it is the number of years after 0.
+ b. If 70 <= f < 100
+ i. If m < 70, f/m/l is interpreted as
+ year/month/day where year is the number of years after
+ 1900.
+ ii. If m >= 70, the date is invalid.
+ c. If f >= 100
+ i. If m < 70, f/m/l is interpreted as
+ year/month/day where year is the number of years after 0.
+ ii. If m >= 70, the date is invalid.
+ */
+ if (seenmonthname) {
+ if ((mday >= 70 && year >= 70) || (mday < 70 && year < 70)) {
+ goto syntax;
+ }
+ if (mday > year) {
+ temp = year;
+ year = mday;
+ mday = temp;
+ }
+ if (year >= 70 && year < 100) {
+ year += 1900;
+ }
+ } else if (mon < 70) { /* (a) month/day/year */
+ if (year < 100) {
+ year += 1900;
+ }
+ } else if (mon < 100) { /* (b) year/month/day */
+ if (mday < 70) {
+ temp = year;
+ year = mon + 1900;
+ mon = mday;
+ mday = temp;
+ } else {
+ goto syntax;
+ }
+ } else { /* (c) year/month/day */
+ if (mday < 70) {
+ temp = year;
+ year = mon;
+ mon = mday;
+ mday = temp;
+ } else {
+ goto syntax;
+ }
+ }
+ mon -= 1; /* convert month to 0-based */
+ if (sec < 0)
+ sec = 0;
+ if (min < 0)
+ min = 0;
+ if (hour < 0)
+ hour = 0;
+ if (tzoffset == -1) { /* no time zone specified, have to use local */
+ jsdouble msec_time;
+ msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
+
+ *result = UTC(msec_time);
+ return JS_TRUE;
+ }
+
+ msec = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
+ msec += tzoffset * msPerMinute;
+ *result = msec;
+ return JS_TRUE;
+
+syntax:
+ /* syntax error */
+ *result = 0;
+ return JS_FALSE;
+}
+
+static JSBool
+date_parse(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble result;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+ if (!date_parseString(str, &result)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+
+ result = TIMECLIP(result);
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_now(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_NewDoubleInRootedValue(cx, PRMJ_Now() / PRMJ_USEC_PER_MSEC, vp);
+}
+
+#ifdef JS_TRACER
+static jsdouble FASTCALL
+date_now_tn(JSContext*)
+{
+ return PRMJ_Now() / PRMJ_USEC_PER_MSEC;
+}
+#endif
+
+/*
+ * Get UTC time from the date object. Returns false if the object is not
+ * Date type.
+ */
+static JSBool
+GetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
+{
+ if (!JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
+ return JS_FALSE;
+ *dp = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
+ return JS_TRUE;
+}
+
+/*
+ * Set UTC time slot with a pointer pointing to a jsdouble. This function is
+ * used only for setting UTC time to some predefined values, such as NaN.
+ *
+ * It also invalidates cached local time.
+ */
+static JSBool
+SetUTCTimePtr(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
+{
+ if (vp && !JS_InstanceOf(cx, obj, &js_DateClass, vp + 2))
+ return JS_FALSE;
+ JS_ASSERT_IF(!vp, STOBJ_GET_CLASS(obj) == &js_DateClass);
+
+ /* Invalidate local time cache. */
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(dp);
+ return JS_TRUE;
+}
+
+/*
+ * Set UTC time to a given time.
+ */
+static JSBool
+SetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble t)
+{
+ jsdouble *dp = js_NewWeaklyRootedDouble(cx, t);
+ if (!dp)
+ return JS_FALSE;
+ return SetUTCTimePtr(cx, obj, vp, dp);
+}
+
+/*
+ * Get the local time, cache it if necessary. If UTC time is not finite
+ * (e.g., NaN), the local time slot is set to the UTC time without conversion.
+ */
+static JSBool
+GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
+{
+ jsval v;
+ jsdouble result;
+ jsdouble *cached;
+
+ if (!obj || !JS_InstanceOf(cx, obj, &js_DateClass, vp ? vp + 2 : NULL))
+ return JS_FALSE;
+ v = obj->fslots[JSSLOT_LOCAL_TIME];
+
+ result = *JSVAL_TO_DOUBLE(v);
+
+ if (JSDOUBLE_IS_NaN(result)) {
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ /* if result is NaN, it couldn't be finite. */
+ if (JSDOUBLE_IS_FINITE(result))
+ result = LocalTime(result);
+
+ cached = js_NewWeaklyRootedDouble(cx, result);
+ if (!cached)
+ return JS_FALSE;
+
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cached);
+ }
+
+ *dp = result;
+ return JS_TRUE;
+}
+
+/*
+ * See ECMA 15.9.5.4 thru 15.9.5.23
+ */
+static JSBool
+date_getTime(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ return GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result) &&
+ js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+GetYear(JSContext *cx, JSBool fullyear, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result)) {
+ result = YearFromTime(result);
+
+ /* Follow ECMA-262 to the letter, contrary to IE JScript. */
+ if (!fullyear)
+ result -= 1900;
+ }
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return GetYear(cx, JS_FALSE, vp);
+}
+
+static JSBool
+date_getFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return GetYear(cx, JS_TRUE, vp);
+}
+
+static JSBool
+date_getUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = YearFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MonthFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MonthFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = DateFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = DateFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getDay(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = WeekDay(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCDay(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = WeekDay(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = HourFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = HourFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetAndCacheLocalTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MinFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = MinFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+/* Date.getSeconds is mapped to getUTCSeconds */
+
+static JSBool
+date_getUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = SecFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+/* Date.getMilliseconds is mapped to getUTCMilliseconds */
+
+static JSBool
+date_getUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &result))
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(result))
+ result = msFromTime(result);
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_getTimezoneOffset(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsdouble utctime, localtime, result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &utctime))
+ return JS_FALSE;
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
+ return JS_FALSE;
+
+ /*
+ * Return the time zone offset in minutes for the current locale that is
+ * appropriate for this time. This value would be a constant except for
+ * daylight savings time.
+ */
+ result = (utctime - localtime) / msPerMinute;
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+SetDateToNaN(JSContext *cx, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))
+ return JS_FALSE;
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+}
+
+static JSBool
+date_setTime(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble result;
+
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ result = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+
+ result = TIMECLIP(result);
+
+ if (!SetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv;
+ uintN i;
+ jsdouble args[4], *argp, *stop;
+ jsdouble hour, min, sec, msec;
+ jsdouble lorutime; /* Local or UTC version of *date */
+
+ jsdouble msec_time;
+ jsdouble result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ /* just return NaN if the date is already NaN */
+ if (!JSDOUBLE_IS_FINITE(result))
+ return js_NewNumberInRootedValue(cx, result, vp);
+
+ /*
+ * Satisfy the ECMA rule that if a function is called with
+ * fewer arguments than the specified formal arguments, the
+ * remaining arguments are set to undefined. Seems like all
+ * the Date.setWhatever functions in ECMA are only varargs
+ * beyond the first argument; this should be set to undefined
+ * if it's not given. This means that "d = new Date();
+ * d.setMilliseconds()" returns NaN. Blech.
+ */
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ if (argc > maxargs)
+ argc = maxargs; /* clamp argc */
+ JS_ASSERT(argc <= 4);
+
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ args[i] = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(args[i]))
+ return SetDateToNaN(cx, vp);
+ args[i] = js_DoubleToInteger(args[i]);
+ }
+
+ if (local)
+ lorutime = LocalTime(result);
+ else
+ lorutime = result;
+
+ argp = args;
+ stop = argp + argc;
+ if (maxargs >= 4 && argp < stop)
+ hour = *argp++;
+ else
+ hour = HourFromTime(lorutime);
+
+ if (maxargs >= 3 && argp < stop)
+ min = *argp++;
+ else
+ min = MinFromTime(lorutime);
+
+ if (maxargs >= 2 && argp < stop)
+ sec = *argp++;
+ else
+ sec = SecFromTime(lorutime);
+
+ if (maxargs >= 1 && argp < stop)
+ msec = *argp;
+ else
+ msec = msFromTime(lorutime);
+
+ msec_time = MakeTime(hour, min, sec, msec);
+ result = MakeDate(Day(lorutime), msec_time);
+
+/* fprintf(stderr, "%f\n", result); */
+
+ if (local)
+ result = UTC(result);
+
+/* fprintf(stderr, "%f\n", result); */
+
+ result = TIMECLIP(result);
+ if (!SetUTCTime(cx, obj, NULL, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_setMilliseconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 1, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCMilliseconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 1, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setSeconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 2, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCSeconds(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 2, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 3, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCMinutes(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 3, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 4, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCHours(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeTime(cx, 4, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv;
+ uintN i;
+ jsdouble lorutime; /* local or UTC version of *date */
+ jsdouble args[3], *argp, *stop;
+ jsdouble year, month, day;
+ jsdouble result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ /* see complaint about ECMA in date_MakeTime */
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ if (argc > maxargs)
+ argc = maxargs; /* clamp argc */
+ JS_ASSERT(1 <= argc && argc <= 3);
+
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ args[i] = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(args[i]))
+ return SetDateToNaN(cx, vp);
+ args[i] = js_DoubleToInteger(args[i]);
+ }
+
+ /* return NaN if date is NaN and we're not setting the year,
+ * If we are, use 0 as the time. */
+ if (!(JSDOUBLE_IS_FINITE(result))) {
+ if (maxargs < 3)
+ return js_NewNumberInRootedValue(cx, result, vp);
+ lorutime = +0.;
+ } else {
+ lorutime = local ? LocalTime(result) : result;
+ }
+
+ argp = args;
+ stop = argp + argc;
+ if (maxargs >= 3 && argp < stop)
+ year = *argp++;
+ else
+ year = YearFromTime(lorutime);
+
+ if (maxargs >= 2 && argp < stop)
+ month = *argp++;
+ else
+ month = MonthFromTime(lorutime);
+
+ if (maxargs >= 1 && argp < stop)
+ day = *argp++;
+ else
+ day = DateFromTime(lorutime);
+
+ day = MakeDay(year, month, day); /* day within year */
+ result = MakeDate(day, TimeWithinDay(lorutime));
+
+ if (local)
+ result = UTC(result);
+
+ result = TIMECLIP(result);
+ if (!SetUTCTime(cx, obj, NULL, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+static JSBool
+date_setDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 1, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCDate(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 1, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 2, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCMonth(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 2, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 3, JS_TRUE, argc, vp);
+}
+
+static JSBool
+date_setUTCFullYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_makeDate(cx, 3, JS_FALSE, argc, vp);
+}
+
+static JSBool
+date_setYear(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsdouble t;
+ jsdouble year;
+ jsdouble day;
+ jsdouble result;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &result))
+ return JS_FALSE;
+
+ if (argc == 0)
+ return SetDateToNaN(cx, vp);
+ year = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(year))
+ return SetDateToNaN(cx, vp);
+
+ year = js_DoubleToInteger(year);
+
+ if (!JSDOUBLE_IS_FINITE(result)) {
+ t = +0.0;
+ } else {
+ t = LocalTime(result);
+ }
+
+ if (year >= 0 && year <= 99)
+ year += 1900;
+
+ day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
+ result = MakeDate(day, TimeWithinDay(t));
+ result = UTC(result);
+
+ result = TIMECLIP(result);
+ if (!SetUTCTime(cx, obj, NULL, result))
+ return JS_FALSE;
+
+ return js_NewNumberInRootedValue(cx, result, vp);
+}
+
+/* constants for toString, toUTCString */
+static char js_NaN_date_str[] = "Invalid Date";
+static const char* days[] =
+{
+ "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
+};
+static const char* months[] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+
+// Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
+// requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
+static void
+print_gmt_string(char* buf, size_t size, jsdouble utctime)
+{
+ JS_snprintf(buf, size, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
+ days[WeekDay(utctime)],
+ DateFromTime(utctime),
+ months[MonthFromTime(utctime)],
+ YearFromTime(utctime),
+ HourFromTime(utctime),
+ MinFromTime(utctime),
+ SecFromTime(utctime));
+}
+
+static void
+print_iso_string(char* buf, size_t size, jsdouble utctime)
+{
+ JS_snprintf(buf, size, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
+ YearFromTime(utctime),
+ MonthFromTime(utctime) + 1,
+ DateFromTime(utctime),
+ HourFromTime(utctime),
+ MinFromTime(utctime),
+ SecFromTime(utctime),
+ msFromTime(utctime));
+}
+
+static JSBool
+date_utc_format(JSContext *cx, jsval *vp,
+ void (*printFunc)(char*, size_t, jsdouble))
+{
+ char buf[100];
+ JSString *str;
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+
+ if (!JSDOUBLE_IS_FINITE(utctime)) {
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
+ } else {
+ (*printFunc)(buf, sizeof buf, utctime);
+ }
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+date_toGMTString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_utc_format(cx, vp, print_gmt_string);
+}
+
+static JSBool
+date_toISOString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_utc_format(cx, vp, print_iso_string);
+}
+
+/* for Date.toLocaleString; interface to PRMJTime date struct.
+ */
+static void
+new_explode(jsdouble timeval, PRMJTime *split)
+{
+ jsint year = YearFromTime(timeval);
+
+ split->tm_usec = (int32) msFromTime(timeval) * 1000;
+ split->tm_sec = (int8) SecFromTime(timeval);
+ split->tm_min = (int8) MinFromTime(timeval);
+ split->tm_hour = (int8) HourFromTime(timeval);
+ split->tm_mday = (int8) DateFromTime(timeval);
+ split->tm_mon = (int8) MonthFromTime(timeval);
+ split->tm_wday = (int8) WeekDay(timeval);
+ split->tm_year = year;
+ split->tm_yday = (int16) DayWithinYear(timeval, year);
+
+ /* not sure how this affects things, but it doesn't seem
+ to matter. */
+ split->tm_isdst = (DaylightSavingTA(timeval) != 0);
+}
+
+typedef enum formatspec {
+ FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME
+} formatspec;
+
+/* helper function */
+static JSBool
+date_format(JSContext *cx, jsdouble date, formatspec format, jsval *rval)
+{
+ char buf[100];
+ JSString *str;
+ char tzbuf[100];
+ JSBool usetz;
+ size_t i, tzlen;
+ PRMJTime split;
+
+ if (!JSDOUBLE_IS_FINITE(date)) {
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
+ } else {
+ jsdouble local = LocalTime(date);
+
+ /* offset from GMT in minutes. The offset includes daylight savings,
+ if it applies. */
+ jsint minutes = (jsint) floor(AdjustTime(date) / msPerMinute);
+
+ /* map 510 minutes to 0830 hours */
+ intN offset = (minutes / 60) * 100 + minutes % 60;
+
+ /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is
+ * printed as 'GMT-0800' rather than as 'PST' to avoid
+ * operating-system dependence on strftime (which
+ * PRMJ_FormatTimeUSEnglish calls, for %Z only.) win32 prints
+ * PST as 'Pacific Standard Time.' This way we always know
+ * what we're getting, and can parse it if we produce it.
+ * The OS TZA string is included as a comment.
+ */
+
+ /* get a timezone string from the OS to include as a
+ comment. */
+ new_explode(date, &split);
+ if (PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split) != 0) {
+
+ /* Decide whether to use the resulting timezone string.
+ *
+ * Reject it if it contains any non-ASCII, non-alphanumeric
+ * characters. It's then likely in some other character
+ * encoding, and we probably won't display it correctly.
+ */
+ usetz = JS_TRUE;
+ tzlen = strlen(tzbuf);
+ if (tzlen > 100) {
+ usetz = JS_FALSE;
+ } else {
+ for (i = 0; i < tzlen; i++) {
+ jschar c = tzbuf[i];
+ if (c > 127 ||
+ !(isalpha(c) || isdigit(c) ||
+ c == ' ' || c == '(' || c == ')')) {
+ usetz = JS_FALSE;
+ }
+ }
+ }
+
+ /* Also reject it if it's not parenthesized or if it's '()'. */
+ if (tzbuf[0] != '(' || tzbuf[1] == ')')
+ usetz = JS_FALSE;
+ } else
+ usetz = JS_FALSE;
+
+ switch (format) {
+ case FORMATSPEC_FULL:
+ /*
+ * Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
+ * requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
+ */
+ /* Tue Oct 31 2000 09:41:40 GMT-0800 (PST) */
+ JS_snprintf(buf, sizeof buf,
+ "%s %s %.2d %.4d %.2d:%.2d:%.2d GMT%+.4d%s%s",
+ days[WeekDay(local)],
+ months[MonthFromTime(local)],
+ DateFromTime(local),
+ YearFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ offset,
+ usetz ? " " : "",
+ usetz ? tzbuf : "");
+ break;
+ case FORMATSPEC_DATE:
+ /* Tue Oct 31 2000 */
+ JS_snprintf(buf, sizeof buf,
+ "%s %s %.2d %.4d",
+ days[WeekDay(local)],
+ months[MonthFromTime(local)],
+ DateFromTime(local),
+ YearFromTime(local));
+ break;
+ case FORMATSPEC_TIME:
+ /* 09:41:40 GMT-0800 (PST) */
+ JS_snprintf(buf, sizeof buf,
+ "%.2d:%.2d:%.2d GMT%+.4d%s%s",
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ offset,
+ usetz ? " " : "",
+ usetz ? tzbuf : "");
+ break;
+ }
+ }
+
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+date_toLocaleHelper(JSContext *cx, const char *format, jsval *vp)
+{
+ JSObject *obj;
+ char buf[100];
+ JSString *str;
+ PRMJTime split;
+ jsdouble utctime;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!GetUTCTime(cx, obj, vp, &utctime))
+ return JS_FALSE;
+
+ if (!JSDOUBLE_IS_FINITE(utctime)) {
+ JS_snprintf(buf, sizeof buf, js_NaN_date_str);
+ } else {
+ intN result_len;
+ jsdouble local = LocalTime(utctime);
+ new_explode(local, &split);
+
+ /* let PRMJTime format it. */
+ result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
+
+ /* If it failed, default to toString. */
+ if (result_len == 0)
+ return date_format(cx, utctime, FORMATSPEC_FULL, vp);
+
+ /* Hacked check against undesired 2-digit year 00/00/00 form. */
+ if (strcmp(format, "%x") == 0 && result_len >= 6 &&
+ /* Format %x means use OS settings, which may have 2-digit yr, so
+ hack end of 3/11/22 or 11.03.22 or 11Mar22 to use 4-digit yr...*/
+ !isdigit(buf[result_len - 3]) &&
+ isdigit(buf[result_len - 2]) && isdigit(buf[result_len - 1]) &&
+ /* ...but not if starts with 4-digit year, like 2022/3/11. */
+ !(isdigit(buf[0]) && isdigit(buf[1]) &&
+ isdigit(buf[2]) && isdigit(buf[3]))) {
+ JS_snprintf(buf + (result_len - 2), (sizeof buf) - (result_len - 2),
+ "%d", js_DateGetYear(cx, obj));
+ }
+
+ }
+
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
+ return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
+
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+date_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ /* Use '%#c' for windows, because '%c' is
+ * backward-compatible and non-y2k with msvc; '%#c' requests that a
+ * full year be used in the result string.
+ */
+ return date_toLocaleHelper(cx,
+#if defined(_WIN32) && !defined(__MWERKS__)
+ "%#c"
+#else
+ "%c"
+#endif
+ , vp);
+}
+
+static JSBool
+date_toLocaleDateString(JSContext *cx, uintN argc, jsval *vp)
+{
+ /* Use '%#x' for windows, because '%x' is
+ * backward-compatible and non-y2k with msvc; '%#x' requests that a
+ * full year be used in the result string.
+ */
+ return date_toLocaleHelper(cx,
+#if defined(_WIN32) && !defined(__MWERKS__)
+ "%#x"
+#else
+ "%x"
+#endif
+ , vp);
+}
+
+static JSBool
+date_toLocaleTimeString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return date_toLocaleHelper(cx, "%X", vp);
+}
+
+static JSBool
+date_toLocaleFormat(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *fmt;
+ const char *fmtbytes;
+
+ if (argc == 0)
+ return date_toLocaleString(cx, argc, vp);
+
+ fmt = js_ValueToString(cx, vp[2]);
+ if (!fmt)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(fmt);
+ fmtbytes = js_GetStringBytes(cx, fmt);
+ if (!fmtbytes)
+ return JS_FALSE;
+
+ return date_toLocaleHelper(cx, fmtbytes, vp);
+}
+
+static JSBool
+date_toTimeString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+ return date_format(cx, utctime, FORMATSPEC_TIME, vp);
+}
+
+static JSBool
+date_toDateString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+ return date_format(cx, utctime, FORMATSPEC_DATE, vp);
+}
+
+#if JS_HAS_TOSOURCE
+#include <string.h>
+#include "jsdtoa.h"
+
+static JSBool
+date_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+ char buf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr, *bytes;
+ JSString *str;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+
+ numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, utctime);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
+ if (!bytes) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ str = JS_NewString(cx, bytes, strlen(bytes));
+ if (!str) {
+ free(bytes);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+static JSBool
+date_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, JS_THIS_OBJECT(cx, vp), vp, &utctime))
+ return JS_FALSE;
+ return date_format(cx, utctime, FORMATSPEC_FULL, vp);
+}
+
+#ifdef JS_TRACER
+static jsval FASTCALL
+date_valueOf_tn(JSContext* cx, JSObject* obj, JSString* str)
+{
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_DateClass, NULL));
+ jsdouble t = *JSVAL_TO_DOUBLE(obj->fslots[JSSLOT_UTC_TIME]);
+
+ JSString* number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
+ jsval v;
+ if (js_EqualStrings(str, number_str)) {
+ if (!js_NewNumberInRootedValue(cx, t, &v))
+ return JSVAL_ERROR_COOKIE;
+ } else {
+ if (!date_format(cx, t, FORMATSPEC_FULL, &v))
+ return JSVAL_ERROR_COOKIE;
+ }
+ return v;
+}
+#endif
+
+static JSBool
+date_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *number_str;
+
+ /* It is an error to call date_valueOf on a non-date object, but we don't
+ * need to check for that explicitly here because every path calls
+ * GetUTCTime, which does the check.
+ */
+
+ /* If called directly with no arguments, convert to a time number. */
+ if (argc == 0)
+ return date_getTime(cx, argc, vp);
+
+ /* Convert to number only if the hint was given, otherwise favor string. */
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ number_str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]);
+ if (js_EqualStrings(str, number_str))
+ return date_getTime(cx, argc, vp);
+ return date_toString(cx, argc, vp);
+}
+
+JS_DEFINE_CALLINFO_2(extern, OBJECT, js_FastNewDate, CONTEXT, OBJECT, 0, 0)
+
+// Don't really need an argument here, but we don't support arg-less builtins
+JS_DEFINE_TRCINFO_1(date_now,
+ (1, (static, DOUBLE, date_now_tn, CONTEXT, 0, 0)))
+
+static JSFunctionSpec date_static_methods[] = {
+ JS_FN("UTC", date_UTC, MAXARGS,0),
+ JS_FN("parse", date_parse, 1,0),
+ JS_TN("now", date_now, 0,0, date_now_trcinfo),
+ JS_FS_END
+};
+
+JS_DEFINE_TRCINFO_1(date_valueOf,
+ (3, (static, JSVAL_FAIL, date_valueOf_tn, CONTEXT, THIS, STRING, 0, 0)))
+
+static JSFunctionSpec date_methods[] = {
+ JS_FN("getTime", date_getTime, 0,0),
+ JS_FN("getTimezoneOffset", date_getTimezoneOffset, 0,0),
+ JS_FN("getYear", date_getYear, 0,0),
+ JS_FN("getFullYear", date_getFullYear, 0,0),
+ JS_FN("getUTCFullYear", date_getUTCFullYear, 0,0),
+ JS_FN("getMonth", date_getMonth, 0,0),
+ JS_FN("getUTCMonth", date_getUTCMonth, 0,0),
+ JS_FN("getDate", date_getDate, 0,0),
+ JS_FN("getUTCDate", date_getUTCDate, 0,0),
+ JS_FN("getDay", date_getDay, 0,0),
+ JS_FN("getUTCDay", date_getUTCDay, 0,0),
+ JS_FN("getHours", date_getHours, 0,0),
+ JS_FN("getUTCHours", date_getUTCHours, 0,0),
+ JS_FN("getMinutes", date_getMinutes, 0,0),
+ JS_FN("getUTCMinutes", date_getUTCMinutes, 0,0),
+ JS_FN("getSeconds", date_getUTCSeconds, 0,0),
+ JS_FN("getUTCSeconds", date_getUTCSeconds, 0,0),
+ JS_FN("getMilliseconds", date_getUTCMilliseconds, 0,0),
+ JS_FN("getUTCMilliseconds", date_getUTCMilliseconds, 0,0),
+ JS_FN("setTime", date_setTime, 1,0),
+ JS_FN("setYear", date_setYear, 1,0),
+ JS_FN("setFullYear", date_setFullYear, 3,0),
+ JS_FN("setUTCFullYear", date_setUTCFullYear, 3,0),
+ JS_FN("setMonth", date_setMonth, 2,0),
+ JS_FN("setUTCMonth", date_setUTCMonth, 2,0),
+ JS_FN("setDate", date_setDate, 1,0),
+ JS_FN("setUTCDate", date_setUTCDate, 1,0),
+ JS_FN("setHours", date_setHours, 4,0),
+ JS_FN("setUTCHours", date_setUTCHours, 4,0),
+ JS_FN("setMinutes", date_setMinutes, 3,0),
+ JS_FN("setUTCMinutes", date_setUTCMinutes, 3,0),
+ JS_FN("setSeconds", date_setSeconds, 2,0),
+ JS_FN("setUTCSeconds", date_setUTCSeconds, 2,0),
+ JS_FN("setMilliseconds", date_setMilliseconds, 1,0),
+ JS_FN("setUTCMilliseconds", date_setUTCMilliseconds, 1,0),
+ JS_FN("toUTCString", date_toGMTString, 0,0),
+ JS_FN(js_toLocaleString_str, date_toLocaleString, 0,0),
+ JS_FN("toLocaleDateString", date_toLocaleDateString, 0,0),
+ JS_FN("toLocaleTimeString", date_toLocaleTimeString, 0,0),
+ JS_FN("toLocaleFormat", date_toLocaleFormat, 0,0),
+ JS_FN("toDateString", date_toDateString, 0,0),
+ JS_FN("toTimeString", date_toTimeString, 0,0),
+ JS_FN("toISOString", date_toISOString, 0,0),
+ JS_FN(js_toJSON_str, date_toISOString, 0,0),
+
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, date_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, date_toString, 0,0),
+ JS_TN(js_valueOf_str, date_valueOf, 0,0, date_valueOf_trcinfo),
+ JS_FS_END
+};
+
+static jsdouble *
+date_constructor(JSContext *cx, JSObject* obj)
+{
+ jsdouble *date;
+
+ date = js_NewWeaklyRootedDouble(cx, 0.0);
+ if (!date)
+ return NULL;
+
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return date;
+}
+
+JSBool
+js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsdouble *date;
+ JSString *str;
+ jsdouble d;
+
+ /* Date called as function. */
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ return date_format(cx, PRMJ_Now() / PRMJ_USEC_PER_MSEC,
+ FORMATSPEC_FULL, rval);
+ }
+
+ /* Date called as constructor. */
+ if (argc == 0) {
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+ *date = PRMJ_Now() / PRMJ_USEC_PER_MSEC;
+ } else if (argc == 1) {
+ if (!JSVAL_IS_STRING(argv[0])) {
+ /* the argument is a millisecond number */
+ d = js_ValueToNumber(cx, &argv[0]);
+ if (JSVAL_IS_NULL(argv[0]))
+ return JS_FALSE;
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+ *date = TIMECLIP(d);
+ } else {
+ /* the argument is a string; parse it. */
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+
+ if (!date_parseString(str, date))
+ *date = *cx->runtime->jsNaN;
+ *date = TIMECLIP(*date);
+ }
+ } else {
+ jsdouble *date;
+ jsdouble msec_time;
+
+ if (!date_msecFromArgs(cx, argc, argv, &msec_time))
+ return JS_FALSE;
+
+ date = date_constructor(cx, obj);
+ if (!date)
+ return JS_FALSE;
+
+ if (JSDOUBLE_IS_FINITE(msec_time)) {
+ msec_time = UTC(msec_time);
+ msec_time = TIMECLIP(msec_time);
+ }
+
+ *date = msec_time;
+ }
+ return JS_TRUE;
+}
+
+JS_STATIC_ASSERT(JSSLOT_PRIVATE == JSSLOT_UTC_TIME);
+JS_STATIC_ASSERT(JSSLOT_UTC_TIME + 1 == JSSLOT_LOCAL_TIME);
+
+#ifdef JS_TRACER
+JSObject* FASTCALL
+js_FastNewDate(JSContext* cx, JSObject* proto)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+ JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
+ if (!obj)
+ return NULL;
+
+ JSClass* clasp = &js_DateClass;
+ obj->classword = jsuword(clasp);
+
+ obj->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto);
+ obj->fslots[JSSLOT_PARENT] = proto->fslots[JSSLOT_PARENT];
+
+ jsdouble* date = js_NewWeaklyRootedDouble(cx, 0.0);
+ if (!date)
+ return NULL;
+ *date = date_now_tn(cx);
+ obj->fslots[JSSLOT_UTC_TIME] = DOUBLE_TO_JSVAL(date);
+ obj->fslots[JSSLOT_LOCAL_TIME] = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ for (unsigned i = JSSLOT_LOCAL_TIME + 1; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+ JS_ASSERT(!clasp->getObjectOps);
+ JS_ASSERT(proto->map->ops == &js_ObjectOps);
+ obj->map = js_HoldObjectMap(cx, proto->map);
+ obj->dslots = NULL;
+ return obj;
+}
+#endif
+
+JSObject *
+js_InitDateClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+ jsdouble *proto_date;
+
+ /* set static LocalTZA */
+ LocalTZA = -(PRMJ_LocalGMTDifference() * msPerSecond);
+ proto = JS_InitClass(cx, obj, NULL, &js_DateClass, js_Date, MAXARGS,
+ NULL, date_methods, NULL, date_static_methods);
+ if (!proto)
+ return NULL;
+
+ /* Alias toUTCString with toGMTString. (ECMA B.2.6) */
+ if (!JS_AliasProperty(cx, proto, "toUTCString", "toGMTString"))
+ return NULL;
+
+ /* Set the value of the Date.prototype date to NaN */
+ proto_date = date_constructor(cx, proto);
+ if (!proto_date)
+ return NULL;
+ *proto_date = *cx->runtime->jsNaN;
+
+ return proto;
+}
+
+JS_FRIEND_API(JSObject *)
+js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
+{
+ JSObject *obj;
+ jsdouble *date;
+
+ obj = js_NewObject(cx, &js_DateClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+
+ date = date_constructor(cx, obj);
+ if (!date)
+ return NULL;
+
+ *date = msec_time;
+ return obj;
+}
+
+JS_FRIEND_API(JSObject *)
+js_NewDateObject(JSContext* cx, int year, int mon, int mday,
+ int hour, int min, int sec)
+{
+ JSObject *obj;
+ jsdouble msec_time;
+
+ JS_ASSERT(mon < 12);
+ msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
+ obj = js_NewDateObjectMsec(cx, UTC(msec_time));
+ return obj;
+}
+
+JS_FRIEND_API(JSBool)
+js_DateIsValid(JSContext *cx, JSObject* obj)
+{
+ jsdouble utctime;
+ return GetUTCTime(cx, obj, NULL, &utctime) && !JSDOUBLE_IS_NaN(utctime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetYear(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ /* Preserve legacy API behavior of returning 0 for invalid dates. */
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) YearFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetMonth(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) MonthFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetDate(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) DateFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetHours(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) HourFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetMinutes(JSContext *cx, JSObject* obj)
+{
+ jsdouble localtime;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime) ||
+ JSDOUBLE_IS_NaN(localtime)) {
+ return 0;
+ }
+
+ return (int) MinFromTime(localtime);
+}
+
+JS_FRIEND_API(int)
+js_DateGetSeconds(JSContext *cx, JSObject* obj)
+{
+ jsdouble utctime;
+
+ if (!GetUTCTime(cx, obj, NULL, &utctime) || JSDOUBLE_IS_NaN(utctime))
+ return 0;
+
+ return (int) SecFromTime(utctime);
+}
+
+JS_FRIEND_API(void)
+js_DateSetYear(JSContext *cx, JSObject *obj, int year)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ /* reset date if it was NaN */
+ if (JSDOUBLE_IS_NaN(local))
+ local = 0;
+
+ local = date_msecFromDate(year,
+ MonthFromTime(local),
+ DateFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+
+ /* SetUTCTime also invalidates local time cache. */
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetMonth(JSContext *cx, JSObject *obj, int month)
+{
+ jsdouble local;
+
+ JS_ASSERT(month < 12);
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ /* bail if date was NaN */
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+
+ local = date_msecFromDate(YearFromTime(local),
+ month,
+ DateFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetDate(JSContext *cx, JSObject *obj, int date)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ date,
+ HourFromTime(local),
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetHours(JSContext *cx, JSObject *obj, int hours)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ DateFromTime(local),
+ hours,
+ MinFromTime(local),
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ DateFromTime(local),
+ HourFromTime(local),
+ minutes,
+ SecFromTime(local),
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(void)
+js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds)
+{
+ jsdouble local;
+
+ if (!GetAndCacheLocalTime(cx, obj, NULL, &local))
+ return;
+
+ if (JSDOUBLE_IS_NaN(local))
+ return;
+ local = date_msecFromDate(YearFromTime(local),
+ MonthFromTime(local),
+ DateFromTime(local),
+ HourFromTime(local),
+ MinFromTime(local),
+ seconds,
+ msFromTime(local));
+ SetUTCTime(cx, obj, NULL, UTC(local));
+}
+
+JS_FRIEND_API(jsdouble)
+js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj)
+{
+ jsdouble utctime;
+ if (!GetUTCTime(cx, obj, NULL, &utctime))
+ return 0;
+ return utctime;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdate.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.h
new file mode 100644
index 0000000..6c5b3aa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdate.h
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS Date class interface.
+ */
+
+#ifndef jsdate_h___
+#define jsdate_h___
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_DateClass;
+
+extern JSObject *
+js_InitDateClass(JSContext *cx, JSObject *obj);
+
+/*
+ * These functions provide a C interface to the date/time object
+ */
+
+/*
+ * Construct a new Date Object from a time value given in milliseconds UTC
+ * since the epoch.
+ */
+extern JS_FRIEND_API(JSObject*)
+js_NewDateObjectMsec(JSContext* cx, jsdouble msec_time);
+
+/*
+ * Construct a new Date Object from an exploded local time value.
+ *
+ * Assert that mon < 12 to help catch off-by-one user errors, which are common
+ * due to the 0-based month numbering copied into JS from Java (java.util.Date
+ * in 1995). js_DateSetMonth (below) likewise asserts month < 12.
+ */
+extern JS_FRIEND_API(JSObject*)
+js_NewDateObject(JSContext* cx, int year, int mon, int mday,
+ int hour, int min, int sec);
+
+/*
+ * Detect whether the internal date value is NaN. (Because failure is
+ * out-of-band for js_DateGet*)
+ */
+extern JS_FRIEND_API(JSBool)
+js_DateIsValid(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetYear(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetMonth(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetDate(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetHours(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetMinutes(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(int)
+js_DateGetSeconds(JSContext *cx, JSObject* obj);
+
+extern JS_FRIEND_API(void)
+js_DateSetYear(JSContext *cx, JSObject *obj, int year);
+
+extern JS_FRIEND_API(void)
+js_DateSetMonth(JSContext *cx, JSObject *obj, int month);
+
+extern JS_FRIEND_API(void)
+js_DateSetDate(JSContext *cx, JSObject *obj, int date);
+
+extern JS_FRIEND_API(void)
+js_DateSetHours(JSContext *cx, JSObject *obj, int hours);
+
+extern JS_FRIEND_API(void)
+js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes);
+
+extern JS_FRIEND_API(void)
+js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds);
+
+extern JS_FRIEND_API(jsdouble)
+js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj);
+
+JS_END_EXTERN_C
+
+#endif /* jsdate_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp
new file mode 100644
index 0000000..dad4590
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.cpp
@@ -0,0 +1,1954 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS debugging API.
+ */
+#include "jsstddef.h"
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsclist.h"
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+
+#include "jsautooplen.h"
+
+typedef struct JSTrap {
+ JSCList links;
+ JSScript *script;
+ jsbytecode *pc;
+ JSOp op;
+ JSTrapHandler handler;
+ void *closure;
+} JSTrap;
+
+#define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
+#define DBG_UNLOCK(rt) JS_RELEASE_LOCK((rt)->debuggerLock)
+#define DBG_LOCK_EVAL(rt,expr) (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
+
+/*
+ * NB: FindTrap must be called with rt->debuggerLock acquired.
+ */
+static JSTrap *
+FindTrap(JSRuntime *rt, JSScript *script, jsbytecode *pc)
+{
+ JSTrap *trap;
+
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links != &rt->trapList;
+ trap = (JSTrap *)trap->links.next) {
+ if (trap->script == script && trap->pc == pc)
+ return trap;
+ }
+ return NULL;
+}
+
+jsbytecode *
+js_UntrapScriptCode(JSContext *cx, JSScript *script)
+{
+ jsbytecode *code;
+ JSRuntime *rt;
+ JSTrap *trap;
+
+ code = script->code;
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links !=
+ &rt->trapList;
+ trap = (JSTrap *)trap->links.next) {
+ if (trap->script == script &&
+ (size_t)(trap->pc - script->code) < script->length) {
+ if (code == script->code) {
+ jssrcnote *sn, *notes;
+ size_t nbytes;
+
+ nbytes = script->length * sizeof(jsbytecode);
+ notes = SCRIPT_NOTES(script);
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
+ continue;
+ nbytes += (sn - notes + 1) * sizeof *sn;
+
+ code = (jsbytecode *) JS_malloc(cx, nbytes);
+ if (!code)
+ break;
+ memcpy(code, script->code, nbytes);
+ JS_CLEAR_GSN_CACHE(cx);
+ }
+ code[trap->pc - script->code] = trap->op;
+ }
+ }
+ DBG_UNLOCK(rt);
+ return code;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler handler, void *closure)
+{
+ JSTrap *junk, *trap, *twin;
+ JSRuntime *rt;
+ uint32 sample;
+
+ JS_ASSERT((JSOp) *pc != JSOP_TRAP);
+ junk = NULL;
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ trap = FindTrap(rt, script, pc);
+ if (trap) {
+ JS_ASSERT(trap->script == script && trap->pc == pc);
+ JS_ASSERT(*pc == JSOP_TRAP);
+ } else {
+ sample = rt->debuggerMutations;
+ DBG_UNLOCK(rt);
+ trap = (JSTrap *) JS_malloc(cx, sizeof *trap);
+ if (!trap)
+ return JS_FALSE;
+ trap->closure = NULL;
+ if(!js_AddRoot(cx, &trap->closure, "trap->closure")) {
+ JS_free(cx, trap);
+ return JS_FALSE;
+ }
+ DBG_LOCK(rt);
+ twin = (rt->debuggerMutations != sample)
+ ? FindTrap(rt, script, pc)
+ : NULL;
+ if (twin) {
+ junk = trap;
+ trap = twin;
+ } else {
+ JS_APPEND_LINK(&trap->links, &rt->trapList);
+ ++rt->debuggerMutations;
+ trap->script = script;
+ trap->pc = pc;
+ trap->op = (JSOp)*pc;
+ *pc = JSOP_TRAP;
+ }
+ }
+ trap->handler = handler;
+ trap->closure = closure;
+ DBG_UNLOCK(rt);
+ if (junk) {
+ js_RemoveRoot(rt, &junk->closure);
+ JS_free(cx, junk);
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSOp)
+JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ JSRuntime *rt;
+ JSTrap *trap;
+ JSOp op;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ trap = FindTrap(rt, script, pc);
+ op = trap ? trap->op : (JSOp) *pc;
+ DBG_UNLOCK(rt);
+ return op;
+}
+
+static void
+DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
+{
+ ++cx->runtime->debuggerMutations;
+ JS_REMOVE_LINK(&trap->links);
+ *trap->pc = (jsbytecode)trap->op;
+ DBG_UNLOCK(cx->runtime);
+
+ js_RemoveRoot(cx->runtime, &trap->closure);
+ JS_free(cx, trap);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler *handlerp, void **closurep)
+{
+ JSTrap *trap;
+
+ DBG_LOCK(cx->runtime);
+ trap = FindTrap(cx->runtime, script, pc);
+ if (handlerp)
+ *handlerp = trap ? trap->handler : NULL;
+ if (closurep)
+ *closurep = trap ? trap->closure : NULL;
+ if (trap)
+ DestroyTrapAndUnlock(cx, trap);
+ else
+ DBG_UNLOCK(cx->runtime);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearScriptTraps(JSContext *cx, JSScript *script)
+{
+ JSRuntime *rt;
+ JSTrap *trap, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links != &rt->trapList;
+ trap = next) {
+ next = (JSTrap *)trap->links.next;
+ if (trap->script == script) {
+ sample = rt->debuggerMutations;
+ DestroyTrapAndUnlock(cx, trap);
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSTrap *)rt->trapList.next;
+ }
+ }
+ DBG_UNLOCK(rt);
+}
+
+JS_PUBLIC_API(void)
+JS_ClearAllTraps(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSTrap *trap, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (trap = (JSTrap *)rt->trapList.next;
+ &trap->links != &rt->trapList;
+ trap = next) {
+ next = (JSTrap *)trap->links.next;
+ sample = rt->debuggerMutations;
+ DestroyTrapAndUnlock(cx, trap);
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSTrap *)rt->trapList.next;
+ }
+ DBG_UNLOCK(rt);
+}
+
+JS_PUBLIC_API(JSTrapStatus)
+JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval)
+{
+ JSTrap *trap;
+ jsint op;
+ JSTrapStatus status;
+
+ DBG_LOCK(cx->runtime);
+ trap = FindTrap(cx->runtime, script, pc);
+ JS_ASSERT(!trap || trap->handler);
+ if (!trap) {
+ op = (JSOp) *pc;
+ DBG_UNLOCK(cx->runtime);
+
+ /* Defend against "pc for wrong script" API usage error. */
+ JS_ASSERT(op != JSOP_TRAP);
+
+#ifdef JS_THREADSAFE
+ /* If the API was abused, we must fail for want of the real op. */
+ if (op == JSOP_TRAP)
+ return JSTRAP_ERROR;
+
+ /* Assume a race with a debugger thread and try to carry on. */
+ *rval = INT_TO_JSVAL(op);
+ return JSTRAP_CONTINUE;
+#else
+ /* Always fail if single-threaded (must be an API usage error). */
+ return JSTRAP_ERROR;
+#endif
+ }
+ DBG_UNLOCK(cx->runtime);
+
+ /*
+ * It's important that we not use 'trap->' after calling the callback --
+ * the callback might remove the trap!
+ */
+ op = (jsint)trap->op;
+ status = trap->handler(cx, script, pc, rval, trap->closure);
+ if (status == JSTRAP_CONTINUE) {
+ /* By convention, return the true op to the interpreter in rval. */
+ *rval = INT_TO_JSVAL(op);
+ }
+ return status;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
+{
+ rt->globalDebugHooks.interruptHandler = handler;
+ rt->globalDebugHooks.interruptHandlerData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
+{
+ if (handlerp)
+ *handlerp = (JSTrapHandler)rt->globalDebugHooks.interruptHandler;
+ if (closurep)
+ *closurep = rt->globalDebugHooks.interruptHandlerData;
+ rt->globalDebugHooks.interruptHandler = 0;
+ rt->globalDebugHooks.interruptHandlerData = 0;
+ return JS_TRUE;
+}
+
+/************************************************************************/
+
+typedef struct JSWatchPoint {
+ JSCList links;
+ JSObject *object; /* weak link, see js_FinalizeObject */
+ JSScopeProperty *sprop;
+ JSPropertyOp setter;
+ JSWatchPointHandler handler;
+ void *closure;
+ uintN flags;
+} JSWatchPoint;
+
+#define JSWP_LIVE 0x1 /* live because set and not cleared */
+#define JSWP_HELD 0x2 /* held while running handler/setter */
+
+/*
+ * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
+ */
+static JSBool
+DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
+{
+ JSBool ok, found;
+ JSScopeProperty *sprop;
+ JSScope *scope;
+ JSPropertyOp setter;
+
+ ok = JS_TRUE;
+ wp->flags &= ~flag;
+ if (wp->flags != 0) {
+ DBG_UNLOCK(cx->runtime);
+ return ok;
+ }
+
+ /*
+ * Remove wp from the list, then if there are no other watchpoints for
+ * wp->sprop in any scope, restore wp->sprop->setter from wp.
+ */
+ ++cx->runtime->debuggerMutations;
+ JS_REMOVE_LINK(&wp->links);
+ sprop = wp->sprop;
+
+ /*
+ * Passing null for the scope parameter tells js_GetWatchedSetter to find
+ * any watch point for sprop, and not to lock or unlock rt->debuggerLock.
+ * If js_ChangeNativePropertyAttrs fails, propagate failure after removing
+ * wp->closure's root and freeing wp.
+ */
+ setter = js_GetWatchedSetter(cx->runtime, NULL, sprop);
+ DBG_UNLOCK(cx->runtime);
+ if (!setter) {
+ JS_LOCK_OBJ(cx, wp->object);
+ scope = OBJ_SCOPE(wp->object);
+ found = (scope->object == wp->object &&
+ SCOPE_GET_PROPERTY(scope, sprop->id));
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /*
+ * If the property wasn't found on wp->object or didn't exist, then
+ * someone else has dealt with this sprop, and we don't need to change
+ * the property attributes.
+ */
+ if (found) {
+ sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop,
+ 0, sprop->attrs,
+ sprop->getter,
+ wp->setter);
+ if (!sprop)
+ ok = JS_FALSE;
+ }
+ }
+
+ JS_free(cx, wp);
+ return ok;
+}
+
+/*
+ * NB: js_TraceWatchPoints does not acquire cx->runtime->debuggerLock, since
+ * the debugger should never be racing with the GC (i.e., the debugger must
+ * respect the request model).
+ */
+void
+js_TraceWatchPoints(JSTracer *trc, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp;
+
+ rt = trc->context->runtime;
+
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if (wp->object == obj) {
+ TRACE_SCOPE_PROPERTY(trc, wp->sprop);
+ if ((wp->sprop->attrs & JSPROP_SETTER) && wp->setter) {
+ JS_CALL_OBJECT_TRACER(trc, (JSObject *)wp->setter,
+ "wp->setter");
+ }
+ JS_SET_TRACING_NAME(trc, "wp->closure");
+ js_CallValueTracerIfGCThing(trc, (jsval) wp->closure);
+ }
+ }
+}
+
+void
+js_SweepWatchPoints(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = next) {
+ next = (JSWatchPoint *)wp->links.next;
+ if (js_IsAboutToBeFinalized(cx, wp->object)) {
+ sample = rt->debuggerMutations;
+
+ /* Ignore failures. */
+ DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSWatchPoint *)rt->watchPointList.next;
+ }
+ }
+ DBG_UNLOCK(rt);
+}
+
+
+
+/*
+ * NB: FindWatchPoint must be called with rt->debuggerLock acquired.
+ */
+static JSWatchPoint *
+FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
+{
+ JSWatchPoint *wp;
+
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if (wp->object == scope->object && wp->sprop->id == id)
+ return wp;
+ }
+ return NULL;
+}
+
+JSScopeProperty *
+js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
+{
+ JSWatchPoint *wp;
+ JSScopeProperty *sprop;
+
+ DBG_LOCK(rt);
+ wp = FindWatchPoint(rt, scope, id);
+ sprop = wp ? wp->sprop : NULL;
+ DBG_UNLOCK(rt);
+ return sprop;
+}
+
+/*
+ * Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
+ * caller has acquired rt->debuggerLock, so we don't have to.
+ */
+JSPropertyOp
+js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
+ const JSScopeProperty *sprop)
+{
+ JSPropertyOp setter;
+ JSWatchPoint *wp;
+
+ setter = NULL;
+ if (scope)
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if ((!scope || wp->object == scope->object) && wp->sprop == sprop) {
+ setter = wp->setter;
+ break;
+ }
+ }
+ if (scope)
+ DBG_UNLOCK(rt);
+ return setter;
+}
+
+JSBool
+js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp;
+ JSScopeProperty *sprop;
+ jsval propid, userid;
+ JSScope *scope;
+ JSBool ok;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ sprop = wp->sprop;
+ if (wp->object == obj && SPROP_USERID(sprop) == id &&
+ !(wp->flags & JSWP_HELD)) {
+ wp->flags |= JSWP_HELD;
+ DBG_UNLOCK(rt);
+
+ JS_LOCK_OBJ(cx, obj);
+ propid = ID_TO_VALUE(sprop->id);
+ userid = (sprop->flags & SPROP_HAS_SHORTID)
+ ? INT_TO_JSVAL(sprop->shortid)
+ : propid;
+ scope = OBJ_SCOPE(obj);
+ JS_UNLOCK_OBJ(cx, obj);
+
+ /* NB: wp is held, so we can safely dereference it still. */
+ ok = wp->handler(cx, obj, propid,
+ SPROP_HAS_VALID_SLOT(sprop, scope)
+ ? OBJ_GET_SLOT(cx, obj, sprop->slot)
+ : JSVAL_VOID,
+ vp, wp->closure);
+ if (ok) {
+ /*
+ * Create a pseudo-frame for the setter invocation so that any
+ * stack-walking security code under the setter will correctly
+ * identify the guilty party. So that the watcher appears to
+ * be active to obj_eval and other such code, point frame.pc
+ * at the JSOP_STOP at the end of the script.
+ *
+ * The pseudo-frame is not created for fast natives as they
+ * are treated as interpreter frame extensions and always
+ * trusted.
+ */
+ JSObject *closure;
+ JSClass *clasp;
+ JSFunction *fun;
+ JSScript *script;
+ JSBool injectFrame;
+ uintN nslots;
+ jsval smallv[5];
+ jsval *argv;
+ JSStackFrame frame;
+ JSFrameRegs regs;
+
+ closure = (JSObject *) wp->closure;
+ clasp = OBJ_GET_CLASS(cx, closure);
+ if (clasp == &js_FunctionClass) {
+ fun = GET_FUNCTION_PRIVATE(cx, closure);
+ script = FUN_SCRIPT(fun);
+ } else if (clasp == &js_ScriptClass) {
+ fun = NULL;
+ script = (JSScript *) JS_GetPrivate(cx, closure);
+ } else {
+ fun = NULL;
+ script = NULL;
+ }
+
+ nslots = 2;
+ injectFrame = JS_TRUE;
+ if (fun) {
+ nslots += FUN_MINARGS(fun);
+ if (!FUN_INTERPRETED(fun)) {
+ nslots += fun->u.n.extra;
+ injectFrame = !(fun->flags & JSFUN_FAST_NATIVE);
+ }
+ }
+
+ if (injectFrame) {
+ if (nslots <= JS_ARRAY_LENGTH(smallv)) {
+ argv = smallv;
+ } else {
+ argv = (jsval *) JS_malloc(cx, nslots * sizeof(jsval));
+ if (!argv) {
+ DBG_LOCK(rt);
+ DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
+ return JS_FALSE;
+ }
+ }
+
+ argv[0] = OBJECT_TO_JSVAL(closure);
+ argv[1] = JSVAL_NULL;
+ memset(argv + 2, 0, (nslots - 2) * sizeof(jsval));
+
+ memset(&frame, 0, sizeof(frame));
+ frame.script = script;
+ frame.regs = NULL;
+ if (script) {
+ JS_ASSERT(script->length >= JSOP_STOP_LENGTH);
+ regs.pc = script->code + script->length
+ - JSOP_STOP_LENGTH;
+ regs.sp = NULL;
+ frame.regs = &regs;
+ }
+ frame.callee = closure;
+ frame.fun = fun;
+ frame.argv = argv + 2;
+ frame.down = cx->fp;
+ frame.scopeChain = OBJ_GET_PARENT(cx, closure);
+
+ cx->fp = &frame;
+ }
+#ifdef __GNUC__
+ else
+ argv = NULL; /* suppress bogus gcc warnings */
+#endif
+ ok = !wp->setter ||
+ ((sprop->attrs & JSPROP_SETTER)
+ ? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(wp->setter),
+ 1, vp, vp)
+ : wp->setter(cx, OBJ_THIS_OBJECT(cx, obj), userid, vp));
+ if (injectFrame) {
+ /* Evil code can cause us to have an arguments object. */
+ if (frame.callobj)
+ ok &= js_PutCallObject(cx, &frame);
+ if (frame.argsobj)
+ ok &= js_PutArgsObject(cx, &frame);
+
+ cx->fp = frame.down;
+ if (argv != smallv)
+ JS_free(cx, argv);
+ }
+ }
+ DBG_LOCK(rt);
+ return DropWatchPointAndUnlock(cx, wp, JSWP_HELD) && ok;
+ }
+ }
+ DBG_UNLOCK(rt);
+ return JS_TRUE;
+}
+
+JSBool
+js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSObject *funobj;
+ JSFunction *wrapper;
+ jsval userid;
+
+ funobj = JSVAL_TO_OBJECT(argv[-2]);
+ JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
+ wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
+ userid = ATOM_KEY(wrapper->atom);
+ *rval = argv[0];
+ return js_watch_set(cx, obj, userid, rval);
+}
+
+JSPropertyOp
+js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
+{
+ JSAtom *atom;
+ JSFunction *wrapper;
+
+ if (!(attrs & JSPROP_SETTER))
+ return &js_watch_set; /* & to silence schoolmarmish MSVC */
+
+ if (JSID_IS_ATOM(id)) {
+ atom = JSID_TO_ATOM(id);
+ } else if (JSID_IS_INT(id)) {
+ if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id))
+ return NULL;
+ atom = JSID_TO_ATOM(id);
+ } else {
+ atom = NULL;
+ }
+ wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
+ OBJ_GET_PARENT(cx, (JSObject *)setter),
+ atom);
+ if (!wrapper)
+ return NULL;
+ return (JSPropertyOp) FUN_OBJECT(wrapper);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
+ JSWatchPointHandler handler, void *closure)
+{
+ jsid propid;
+ JSObject *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSRuntime *rt;
+ JSBool ok;
+ JSWatchPoint *wp;
+ JSPropertyOp watcher;
+
+ if (!OBJ_IS_NATIVE(obj)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
+ OBJ_GET_CLASS(cx, obj)->name);
+ return JS_FALSE;
+ }
+
+ if (JSVAL_IS_INT(idval))
+ propid = INT_JSVAL_TO_JSID(idval);
+ else if (!js_ValueToStringId(cx, idval, &propid))
+ return JS_FALSE;
+
+ if (!js_LookupProperty(cx, obj, propid, &pobj, &prop))
+ return JS_FALSE;
+ sprop = (JSScopeProperty *) prop;
+ rt = cx->runtime;
+ if (!sprop) {
+ /* Check for a deleted symbol watchpoint, which holds its property. */
+ sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
+ if (!sprop) {
+ /* Make a new property in obj so we can watch for the first set. */
+ if (!js_DefineProperty(cx, obj, propid, JSVAL_VOID,
+ NULL, NULL, JSPROP_ENUMERATE,
+ &prop)) {
+ return JS_FALSE;
+ }
+ sprop = (JSScopeProperty *) prop;
+ }
+ } else if (pobj != obj) {
+ /* Clone the prototype property so we can watch the right object. */
+ jsval value;
+ JSPropertyOp getter, setter;
+ uintN attrs, flags;
+ intN shortid;
+
+ if (OBJ_IS_NATIVE(pobj)) {
+ value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))
+ ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
+ : JSVAL_VOID;
+ getter = sprop->getter;
+ setter = sprop->setter;
+ attrs = sprop->attrs;
+ flags = sprop->flags;
+ shortid = sprop->shortid;
+ } else {
+ if (!OBJ_GET_PROPERTY(cx, pobj, propid, &value) ||
+ !OBJ_GET_ATTRIBUTES(cx, pobj, propid, prop, &attrs)) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return JS_FALSE;
+ }
+ getter = setter = NULL;
+ flags = 0;
+ shortid = 0;
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ /* Recall that obj is native, whether or not pobj is native. */
+ if (!js_DefineNativeProperty(cx, obj, propid, value, getter, setter,
+ attrs, flags, shortid, &prop)) {
+ return JS_FALSE;
+ }
+ sprop = (JSScopeProperty *) prop;
+ }
+
+ /*
+ * At this point, prop/sprop exists in obj, obj is locked, and we must
+ * OBJ_DROP_PROPERTY(cx, obj, prop) before returning.
+ */
+ ok = JS_TRUE;
+ DBG_LOCK(rt);
+ wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
+ if (!wp) {
+ DBG_UNLOCK(rt);
+ watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter);
+ if (!watcher) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp);
+ if (!wp) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ wp->handler = NULL;
+ wp->closure = NULL;
+ wp->object = obj;
+ JS_ASSERT(sprop->setter != js_watch_set || pobj != obj);
+ wp->setter = sprop->setter;
+ wp->flags = JSWP_LIVE;
+
+ /* XXXbe nest in obj lock here */
+ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs,
+ sprop->getter, watcher);
+ if (!sprop) {
+ /* Self-link so DropWatchPointAndUnlock can JS_REMOVE_LINK it. */
+ JS_INIT_CLIST(&wp->links);
+ DBG_LOCK(rt);
+ DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
+ ok = JS_FALSE;
+ goto out;
+ }
+ wp->sprop = sprop;
+
+ /*
+ * Now that wp is fully initialized, append it to rt's wp list.
+ * Because obj is locked we know that no other thread could have added
+ * a watchpoint for (obj, propid).
+ */
+ DBG_LOCK(rt);
+ JS_ASSERT(!FindWatchPoint(rt, OBJ_SCOPE(obj), propid));
+ JS_APPEND_LINK(&wp->links, &rt->watchPointList);
+ ++rt->debuggerMutations;
+ }
+ wp->handler = handler;
+ wp->closure = closure;
+ DBG_UNLOCK(rt);
+
+out:
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
+ JSWatchPointHandler *handlerp, void **closurep)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = (JSWatchPoint *)wp->links.next) {
+ if (wp->object == obj && SPROP_USERID(wp->sprop) == id) {
+ if (handlerp)
+ *handlerp = wp->handler;
+ if (closurep)
+ *closurep = wp->closure;
+ return DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
+ }
+ }
+ DBG_UNLOCK(rt);
+ if (handlerp)
+ *handlerp = NULL;
+ if (closurep)
+ *closurep = NULL;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = next) {
+ next = (JSWatchPoint *)wp->links.next;
+ if (wp->object == obj) {
+ sample = rt->debuggerMutations;
+ if (!DropWatchPointAndUnlock(cx, wp, JSWP_LIVE))
+ return JS_FALSE;
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSWatchPoint *)rt->watchPointList.next;
+ }
+ }
+ DBG_UNLOCK(rt);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ClearAllWatchPoints(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSWatchPoint *wp, *next;
+ uint32 sample;
+
+ rt = cx->runtime;
+ DBG_LOCK(rt);
+ for (wp = (JSWatchPoint *)rt->watchPointList.next;
+ &wp->links != &rt->watchPointList;
+ wp = next) {
+ next = (JSWatchPoint *)wp->links.next;
+ sample = rt->debuggerMutations;
+ if (!DropWatchPointAndUnlock(cx, wp, JSWP_LIVE))
+ return JS_FALSE;
+ DBG_LOCK(rt);
+ if (rt->debuggerMutations != sample + 1)
+ next = (JSWatchPoint *)rt->watchPointList.next;
+ }
+ DBG_UNLOCK(rt);
+ return JS_TRUE;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(uintN)
+JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ return js_PCToLineNumber(cx, script, pc);
+}
+
+JS_PUBLIC_API(jsbytecode *)
+JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
+{
+ return js_LineNumberToPC(script, lineno);
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
+{
+ return FUN_SCRIPT(fun);
+}
+
+JS_PUBLIC_API(JSNative)
+JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
+{
+ return FUN_NATIVE(fun);
+}
+
+JS_PUBLIC_API(JSFastNative)
+JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
+{
+ return FUN_FAST_NATIVE(fun);
+}
+
+JS_PUBLIC_API(JSPrincipals *)
+JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
+{
+ return script->principals;
+}
+
+/************************************************************************/
+
+/*
+ * Stack Frame Iterator
+ */
+JS_PUBLIC_API(JSStackFrame *)
+JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
+{
+ *iteratorp = (*iteratorp == NULL) ? cx->fp : (*iteratorp)->down;
+ return *iteratorp;
+}
+
+JS_PUBLIC_API(JSScript *)
+JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->script;
+}
+
+JS_PUBLIC_API(jsbytecode *)
+JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->regs ? fp->regs->pc : NULL;
+}
+
+JS_PUBLIC_API(JSStackFrame *)
+JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
+{
+ if (!fp)
+ fp = cx->fp;
+ while (fp) {
+ if (fp->script)
+ return fp;
+ fp = fp->down;
+ }
+ return NULL;
+}
+
+JS_PUBLIC_API(JSPrincipals *)
+JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
+{
+ JSSecurityCallbacks *callbacks;
+
+ if (fp->fun) {
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ if (FUN_OBJECT(fp->fun) != fp->callee)
+ return callbacks->findObjectPrincipals(cx, fp->callee);
+ /* FALL THROUGH */
+ }
+ }
+ if (fp->script)
+ return fp->script->principals;
+ return NULL;
+}
+
+JS_PUBLIC_API(JSPrincipals *)
+JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
+{
+ JSPrincipals *principals, *callerPrincipals;
+ JSSecurityCallbacks *callbacks;
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ principals = callbacks->findObjectPrincipals(cx, fp->callee);
+ } else {
+ principals = NULL;
+ }
+ if (!caller)
+ return principals;
+ callerPrincipals = JS_StackFramePrincipals(cx, caller);
+ return (callerPrincipals && principals &&
+ callerPrincipals->subsume(callerPrincipals, principals))
+ ? principals
+ : callerPrincipals;
+}
+
+JS_PUBLIC_API(void *)
+JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
+{
+ if (fp->annotation && fp->script) {
+ JSPrincipals *principals = JS_StackFramePrincipals(cx, fp);
+
+ if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
+ /*
+ * Give out an annotation only if privileges have not been revoked
+ * or disabled globally.
+ */
+ return fp->annotation;
+ }
+ }
+
+ return NULL;
+}
+
+JS_PUBLIC_API(void)
+JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
+{
+ fp->annotation = annotation;
+}
+
+JS_PUBLIC_API(void *)
+JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
+{
+ JSPrincipals *principals;
+
+ principals = JS_StackFramePrincipals(cx, fp);
+ if (!principals)
+ return NULL;
+ return principals->getPrincipalArray(cx, principals);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
+{
+ return !fp->script;
+}
+
+/* this is deprecated, use JS_GetFrameScopeChain instead */
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->scopeChain;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
+{
+ /* Force creation of argument and call objects if not yet created */
+ (void) JS_GetFrameCallObject(cx, fp);
+ return js_GetScopeChain(cx, fp);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
+{
+ if (! fp->fun)
+ return NULL;
+
+ /* Force creation of argument object if not yet created */
+ (void) js_GetArgsObject(cx, fp);
+
+ /*
+ * XXX ill-defined: null return here means error was reported, unlike a
+ * null returned above or in the #else
+ */
+ return js_GetCallObject(cx, fp, NULL);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
+{
+ JSStackFrame *afp;
+
+ if (fp->flags & JSFRAME_COMPUTED_THIS)
+ return fp->thisp;
+
+ /* js_ComputeThis gets confused if fp != cx->fp, so set it aside. */
+ if (cx->fp != fp) {
+ afp = cx->fp;
+ if (afp) {
+ afp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = afp;
+ cx->fp = fp;
+ }
+ } else {
+ afp = NULL;
+ }
+
+ if (!fp->thisp && fp->argv)
+ fp->thisp = js_ComputeThis(cx, JS_TRUE, fp->argv);
+
+ if (afp) {
+ cx->fp = afp;
+ cx->dormantFrameChain = afp->dormantNext;
+ afp->dormantNext = NULL;
+ }
+
+ return fp->thisp;
+}
+
+JS_PUBLIC_API(JSFunction *)
+JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->fun;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp)
+{
+ if (!fp->fun)
+ return NULL;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, fp->callee) == &js_FunctionClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, fp->callee) == fp->fun);
+ return fp->callee;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
+{
+ return (fp->flags & JSFRAME_CONSTRUCTING) != 0;
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->callee;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
+{
+ return (fp->flags & JSFRAME_DEBUGGER) != 0;
+}
+
+JS_PUBLIC_API(jsval)
+JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
+{
+ return fp->rval;
+}
+
+JS_PUBLIC_API(void)
+JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
+{
+ fp->rval = rval;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(const char *)
+JS_GetScriptFilename(JSContext *cx, JSScript *script)
+{
+ return script->filename;
+}
+
+JS_PUBLIC_API(uintN)
+JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
+{
+ return script->lineno;
+}
+
+JS_PUBLIC_API(uintN)
+JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
+{
+ return js_GetScriptLineExtent(script);
+}
+
+JS_PUBLIC_API(JSVersion)
+JS_GetScriptVersion(JSContext *cx, JSScript *script)
+{
+ return (JSVersion) (script->version & JSVERSION_MASK);
+}
+
+/***************************************************************************/
+
+JS_PUBLIC_API(void)
+JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
+{
+ rt->globalDebugHooks.newScriptHook = hook;
+ rt->globalDebugHooks.newScriptHookData = callerdata;
+}
+
+JS_PUBLIC_API(void)
+JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
+ void *callerdata)
+{
+ rt->globalDebugHooks.destroyScriptHook = hook;
+ rt->globalDebugHooks.destroyScriptHookData = callerdata;
+}
+
+/***************************************************************************/
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ JSObject *scobj;
+ JSScript *script;
+ JSBool ok;
+
+ scobj = JS_GetFrameScopeChain(cx, fp);
+ if (!scobj)
+ return JS_FALSE;
+
+ script = js_CompileScript(cx, scobj, fp, JS_StackFramePrincipals(cx, fp),
+ TCF_COMPILE_N_GO |
+ TCF_PUT_STATIC_DEPTH(fp->script->staticDepth + 1),
+ chars, length, NULL,
+ filename, lineno);
+ if (!script)
+ return JS_FALSE;
+
+ ok = js_Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
+ rval);
+ js_DestroyScript(cx, script);
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval)
+{
+ jschar *chars;
+ JSBool ok;
+ size_t len = length;
+
+ chars = js_InflateString(cx, bytes, &len);
+ if (!chars)
+ return JS_FALSE;
+ length = (uintN) len;
+ ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
+ rval);
+ JS_free(cx, chars);
+
+ return ok;
+}
+
+/************************************************************************/
+
+/* XXXbe this all needs to be reworked to avoid requiring JSScope types. */
+
+JS_PUBLIC_API(JSScopeProperty *)
+JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
+{
+ JSScopeProperty *sprop;
+ JSScope *scope;
+
+ sprop = *iteratorp;
+ scope = OBJ_SCOPE(obj);
+
+ /* XXXbe minor(?) incompatibility: iterate in reverse definition order */
+ if (!sprop) {
+ sprop = SCOPE_LAST_PROP(scope);
+ } else {
+ while ((sprop = sprop->parent) != NULL) {
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
+ break;
+ if (SCOPE_HAS_PROPERTY(scope, sprop))
+ break;
+ }
+ }
+ *iteratorp = sprop;
+ return sprop;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
+ JSPropertyDesc *pd)
+{
+ JSScope *scope;
+ JSScopeProperty *aprop;
+ jsval lastException;
+ JSBool wasThrowing;
+
+ pd->id = ID_TO_VALUE(sprop->id);
+
+ wasThrowing = cx->throwing;
+ if (wasThrowing) {
+ lastException = cx->exception;
+ if (JSVAL_IS_GCTHING(lastException) &&
+ !js_AddRoot(cx, &lastException, "lastException")) {
+ return JS_FALSE;
+ }
+ cx->throwing = JS_FALSE;
+ }
+
+ if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) {
+ if (!cx->throwing) {
+ pd->flags = JSPD_ERROR;
+ pd->value = JSVAL_VOID;
+ } else {
+ pd->flags = JSPD_EXCEPTION;
+ pd->value = cx->exception;
+ }
+ } else {
+ pd->flags = 0;
+ }
+
+ cx->throwing = wasThrowing;
+ if (wasThrowing) {
+ cx->exception = lastException;
+ if (JSVAL_IS_GCTHING(lastException))
+ js_RemoveRoot(cx->runtime, &lastException);
+ }
+
+ pd->flags |= ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
+ | ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
+ | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0);
+ pd->spare = 0;
+ if (sprop->getter == js_GetCallArg) {
+ pd->slot = sprop->shortid;
+ pd->flags |= JSPD_ARGUMENT;
+ } else if (sprop->getter == js_GetCallVar) {
+ pd->slot = sprop->shortid;
+ pd->flags |= JSPD_VARIABLE;
+ } else {
+ pd->slot = 0;
+ }
+ pd->alias = JSVAL_VOID;
+ scope = OBJ_SCOPE(obj);
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) {
+ if (aprop != sprop && aprop->slot == sprop->slot) {
+ pd->alias = ID_TO_VALUE(aprop->id);
+ break;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
+{
+ JSClass *clasp;
+ JSScope *scope;
+ uint32 i, n;
+ JSPropertyDesc *pd;
+ JSScopeProperty *sprop;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (!OBJ_IS_NATIVE(obj) || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
+ return JS_FALSE;
+ }
+ if (!clasp->enumerate(cx, obj))
+ return JS_FALSE;
+
+ /* have no props, or object's scope has not mutated from that of proto */
+ scope = OBJ_SCOPE(obj);
+ if (scope->object != obj || scope->entryCount == 0) {
+ pda->length = 0;
+ pda->array = NULL;
+ return JS_TRUE;
+ }
+
+ n = STOBJ_NSLOTS(obj);
+ if (n > scope->entryCount)
+ n = scope->entryCount;
+ pd = (JSPropertyDesc *) JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc));
+ if (!pd)
+ return JS_FALSE;
+ i = 0;
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
+ continue;
+ if (!js_AddRoot(cx, &pd[i].id, NULL))
+ goto bad;
+ if (!js_AddRoot(cx, &pd[i].value, NULL))
+ goto bad;
+ if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i]))
+ goto bad;
+ if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
+ goto bad;
+ if (++i == n)
+ break;
+ }
+ pda->length = i;
+ pda->array = pd;
+ return JS_TRUE;
+
+bad:
+ pda->length = i + 1;
+ pda->array = pd;
+ JS_PutPropertyDescArray(cx, pda);
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(void)
+JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
+{
+ JSPropertyDesc *pd;
+ uint32 i;
+
+ pd = pda->array;
+ for (i = 0; i < pda->length; i++) {
+ js_RemoveRoot(cx->runtime, &pd[i].id);
+ js_RemoveRoot(cx->runtime, &pd[i].value);
+ if (pd[i].flags & JSPD_ALIAS)
+ js_RemoveRoot(cx->runtime, &pd[i].alias);
+ }
+ JS_free(cx, pd);
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSBool)
+JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
+{
+ rt->globalDebugHooks.debuggerHandler = handler;
+ rt->globalDebugHooks.debuggerHandlerData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
+{
+ rt->globalDebugHooks.sourceHandler = handler;
+ rt->globalDebugHooks.sourceHandlerData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
+{
+ rt->globalDebugHooks.executeHook = hook;
+ rt->globalDebugHooks.executeHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
+{
+ rt->globalDebugHooks.callHook = hook;
+ rt->globalDebugHooks.callHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
+{
+ rt->globalDebugHooks.objectHook = hook;
+ rt->globalDebugHooks.objectHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure)
+{
+ rt->globalDebugHooks.throwHook = hook;
+ rt->globalDebugHooks.throwHookData = closure;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
+{
+ rt->globalDebugHooks.debugErrorHook = hook;
+ rt->globalDebugHooks.debugErrorHookData = closure;
+ return JS_TRUE;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(size_t)
+JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
+{
+ size_t nbytes;
+ JSScope *scope;
+
+ nbytes = sizeof *obj;
+ if (obj->dslots) {
+ nbytes += ((uint32)obj->dslots[-1] - JS_INITIAL_NSLOTS + 1)
+ * sizeof obj->dslots[0];
+ }
+ if (OBJ_IS_NATIVE(obj)) {
+ scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ nbytes += sizeof *scope;
+ nbytes += SCOPE_CAPACITY(scope) * sizeof(JSScopeProperty *);
+ }
+ }
+ return nbytes;
+}
+
+static size_t
+GetAtomTotalSize(JSContext *cx, JSAtom *atom)
+{
+ size_t nbytes;
+
+ nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub);
+ if (ATOM_IS_STRING(atom)) {
+ nbytes += sizeof(JSString);
+ nbytes += (JSFLATSTR_LENGTH(ATOM_TO_STRING(atom)) + 1) * sizeof(jschar);
+ } else if (ATOM_IS_DOUBLE(atom)) {
+ nbytes += sizeof(jsdouble);
+ }
+ return nbytes;
+}
+
+JS_PUBLIC_API(size_t)
+JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
+{
+ size_t nbytes;
+
+ nbytes = sizeof *fun;
+ nbytes += JS_GetObjectTotalSize(cx, FUN_OBJECT(fun));
+ if (FUN_INTERPRETED(fun))
+ nbytes += JS_GetScriptTotalSize(cx, fun->u.i.script);
+ if (fun->atom)
+ nbytes += GetAtomTotalSize(cx, fun->atom);
+ return nbytes;
+}
+
+#include "jsemit.h"
+
+JS_PUBLIC_API(size_t)
+JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
+{
+ size_t nbytes, pbytes;
+ jsatomid i;
+ jssrcnote *sn, *notes;
+ JSObjectArray *objarray;
+ JSPrincipals *principals;
+
+ nbytes = sizeof *script;
+ if (script->u.object)
+ nbytes += JS_GetObjectTotalSize(cx, script->u.object);
+
+ nbytes += script->length * sizeof script->code[0];
+ nbytes += script->atomMap.length * sizeof script->atomMap.vector[0];
+ for (i = 0; i < script->atomMap.length; i++)
+ nbytes += GetAtomTotalSize(cx, script->atomMap.vector[i]);
+
+ if (script->filename)
+ nbytes += strlen(script->filename) + 1;
+
+ notes = SCRIPT_NOTES(script);
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
+ continue;
+ nbytes += (sn - notes + 1) * sizeof *sn;
+
+ if (script->objectsOffset != 0) {
+ objarray = JS_SCRIPT_OBJECTS(script);
+ i = objarray->length;
+ nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
+ do {
+ nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
+ } while (i != 0);
+ }
+
+ if (script->regexpsOffset != 0) {
+ objarray = JS_SCRIPT_REGEXPS(script);
+ i = objarray->length;
+ nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
+ do {
+ nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
+ } while (i != 0);
+ }
+
+ if (script->trynotesOffset != 0) {
+ nbytes += sizeof(JSTryNoteArray) +
+ JS_SCRIPT_TRYNOTES(script)->length * sizeof(JSTryNote);
+ }
+
+ principals = script->principals;
+ if (principals) {
+ JS_ASSERT(principals->refcount);
+ pbytes = sizeof *principals;
+ if (principals->refcount > 1)
+ pbytes = JS_HOWMANY(pbytes, principals->refcount);
+ nbytes += pbytes;
+ }
+
+ return nbytes;
+}
+
+JS_PUBLIC_API(uint32)
+JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp)
+{
+ if (!fp)
+ fp = cx->fp;
+ while (fp) {
+ if (fp->script)
+ return JS_GetScriptFilenameFlags(fp->script);
+ fp = fp->down;
+ }
+ return 0;
+ }
+
+JS_PUBLIC_API(uint32)
+JS_GetScriptFilenameFlags(JSScript *script)
+{
+ JS_ASSERT(script);
+ if (!script->filename)
+ return JSFILENAME_NULL;
+ return js_GetScriptFilenameFlags(script->filename);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags)
+{
+ if (!js_SaveScriptFilenameRT(rt, prefix, flags))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_IsSystemObject(JSContext *cx, JSObject *obj)
+{
+ return STOBJ_IS_SYSTEM(obj);
+}
+
+JS_PUBLIC_API(JSObject *)
+JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, JSBool system)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, clasp, proto, parent, 0);
+ if (obj && system)
+ STOBJ_SET_SYSTEM(obj);
+ return obj;
+}
+
+/************************************************************************/
+
+JS_PUBLIC_API(JSDebugHooks *)
+JS_GetGlobalDebugHooks(JSRuntime *rt)
+{
+ return &rt->globalDebugHooks;
+}
+
+JS_PUBLIC_API(JSDebugHooks *)
+JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks)
+{
+ JSDebugHooks *old;
+
+ JS_ASSERT(hooks);
+ old = cx->debugHooks;
+ cx->debugHooks = hooks;
+ return old;
+}
+
+#ifdef MOZ_SHARK
+
+#include <CHUD/CHUD.h>
+
+JS_PUBLIC_API(JSBool)
+JS_StartChudRemote()
+{
+ if (chudIsRemoteAccessAcquired() &&
+ (chudStartRemotePerfMonitor("Mozilla") == chudSuccess)) {
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_StopChudRemote()
+{
+ if (chudIsRemoteAccessAcquired() &&
+ (chudStopRemotePerfMonitor() == chudSuccess)) {
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ConnectShark()
+{
+ if (!chudIsInitialized() && (chudInitialize() != chudSuccess))
+ return JS_FALSE;
+
+ if (chudAcquireRemoteAccess() != chudSuccess)
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DisconnectShark()
+{
+ if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess))
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StartShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_StartChudRemote()) {
+ JS_ReportError(cx, "Error starting CHUD.");
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StopShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_StopChudRemote()) {
+ JS_ReportError(cx, "Error stopping CHUD.");
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ConnectShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_ConnectShark()) {
+ JS_ReportError(cx, "Error connecting to Shark.");
+ }
+
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_DisconnectShark(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ if (!JS_DisconnectShark()) {
+ JS_ReportError(cx, "Error disconnecting from Shark.");
+ }
+
+ return JS_TRUE;
+}
+
+#endif /* MOZ_SHARK */
+
+#ifdef MOZ_CALLGRIND
+
+#include <valgrind/callgrind.h>
+
+JS_FRIEND_API(JSBool)
+js_StartCallgrind(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ CALLGRIND_START_INSTRUMENTATION;
+ CALLGRIND_ZERO_STATS;
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StopCallgrind(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ CALLGRIND_STOP_INSTRUMENTATION;
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_DumpCallgrind(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ char *cstr;
+
+ if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
+ str = JSVAL_TO_STRING(argv[0]);
+ cstr = js_DeflateString(cx, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+ if (cstr) {
+ CALLGRIND_DUMP_STATS_AT(cstr);
+ JS_free(cx, cstr);
+ return JS_TRUE;
+ }
+ }
+ CALLGRIND_DUMP_STATS;
+
+ return JS_TRUE;
+}
+
+#endif /* MOZ_CALLGRIND */
+
+#ifdef MOZ_VTUNE
+#include <VTuneApi.h>
+
+static const char *vtuneErrorMessages[] = {
+ "unknown, error #0",
+ "invalid 'max samples' field",
+ "invalid 'samples per buffer' field",
+ "invalid 'sample interval' field",
+ "invalid path",
+ "sample file in use",
+ "invalid 'number of events' field",
+ "unknown, error #7",
+ "internal error",
+ "bad event name",
+ "VTStopSampling called without calling VTStartSampling",
+ "no events selected for event-based sampling",
+ "events selected cannot be run together",
+ "no sampling parameters",
+ "sample database already exists",
+ "sampling already started",
+ "time-based sampling not supported",
+ "invalid 'sampling parameters size' field",
+ "invalid 'event size' field",
+ "sampling file already bound",
+ "invalid event path",
+ "invalid license",
+ "invalid 'global options' field",
+
+};
+
+JS_FRIEND_API(JSBool)
+js_StartVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ VTUNE_EVENT events[] = {
+ { 1000000, 0, 0, 0, "CPU_CLK_UNHALTED.CORE" },
+ { 1000000, 0, 0, 0, "INST_RETIRED.ANY" },
+ };
+
+ U32 n_events = sizeof(events) / sizeof(VTUNE_EVENT);
+ char *default_filename = "mozilla-vtune.tb5";
+ JSString *str;
+ U32 status;
+
+ VTUNE_SAMPLING_PARAMS params = {
+ sizeof(VTUNE_SAMPLING_PARAMS),
+ sizeof(VTUNE_EVENT),
+ 0, 0, /* Reserved fields */
+ 1, /* Initialize in "paused" state */
+ 0, /* Max samples, or 0 for "continuous" */
+ 4096, /* Samples per buffer */
+ 0.1, /* Sampling interval in ms */
+ 1, /* 1 for event-based sampling, 0 for time-based */
+
+ n_events,
+ events,
+ default_filename,
+ };
+
+ if (argc > 0 && JSVAL_IS_STRING(argv[0])) {
+ str = JSVAL_TO_STRING(argv[0]);
+ params.tb5Filename = js_DeflateString(cx,
+ JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ }
+
+ status = VTStartSampling(&params);
+
+ if (params.tb5Filename != default_filename)
+ JS_free(cx, params.tb5Filename);
+
+ if (status != 0) {
+ if (status == VTAPI_MULTIPLE_RUNS)
+ VTStopSampling(0);
+ if (status < sizeof(vtuneErrorMessages))
+ JS_ReportError(cx, "Vtune setup error: %s",
+ vtuneErrorMessages[status]);
+ else
+ JS_ReportError(cx, "Vtune setup error: %d",
+ status);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_StopVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ U32 status = VTStopSampling(1);
+ if (status) {
+ if (status < sizeof(vtuneErrorMessages))
+ JS_ReportError(cx, "Vtune shutdown error: %s",
+ vtuneErrorMessages[status]);
+ else
+ JS_ReportError(cx, "Vtune shutdown error: %d",
+ status);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_PauseVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ VTPause();
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_ResumeVtune(JSContext *cx, JSObject *obj,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ VTResume();
+ return JS_TRUE;
+}
+
+#endif /* MOZ_VTUNE */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h
new file mode 100644
index 0000000..b6855b2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdbgapi.h
@@ -0,0 +1,500 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsdbgapi_h___
+#define jsdbgapi_h___
+/*
+ * JS debugger API.
+ */
+#include "jsapi.h"
+#include "jsopcode.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Unexported library-private helper used to unpatch all traps in a script.
+ * Returns script->code if script has no traps, else a JS_malloc'ed copy of
+ * script->code which the caller must JS_free, or null on JS_malloc OOM.
+ */
+extern jsbytecode *
+js_UntrapScriptCode(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSOp)
+JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+extern JS_PUBLIC_API(void)
+JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
+ JSTrapHandler *handlerp, void **closurep);
+
+extern JS_PUBLIC_API(void)
+JS_ClearScriptTraps(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(void)
+JS_ClearAllTraps(JSContext *cx);
+
+extern JS_PUBLIC_API(JSTrapStatus)
+JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval id,
+ JSWatchPointHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
+ JSWatchPointHandler *handlerp, void **closurep);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(JSBool)
+JS_ClearAllWatchPoints(JSContext *cx);
+
+#ifdef JS_HAS_OBJ_WATCHPOINT
+/*
+ * Hide these non-API function prototypes by testing whether the internal
+ * header file "jsversion.h" has been included.
+ */
+extern void
+js_TraceWatchPoints(JSTracer *trc, JSObject *obj);
+
+extern void
+js_SweepWatchPoints(JSContext *cx);
+
+extern JSScopeProperty *
+js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id);
+
+/*
+ * NB: callers outside of jsdbgapi.c must pass non-null scope.
+ */
+extern JSPropertyOp
+js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
+ const JSScopeProperty *sprop);
+
+extern JSBool
+js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JSBool
+js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JSPropertyOp
+js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter);
+
+#endif /* JS_HAS_OBJ_WATCHPOINT */
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(uintN)
+JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+extern JS_PUBLIC_API(jsbytecode *)
+JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(JSNative)
+JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(JSFastNative)
+JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(JSPrincipals *)
+JS_GetScriptPrincipals(JSContext *cx, JSScript *script);
+
+/*
+ * Stack Frame Iterator
+ *
+ * Used to iterate through the JS stack frames to extract
+ * information from the frames.
+ */
+
+extern JS_PUBLIC_API(JSStackFrame *)
+JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp);
+
+extern JS_PUBLIC_API(JSScript *)
+JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(jsbytecode *)
+JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Get the closest scripted frame below fp. If fp is null, start from cx->fp.
+ */
+extern JS_PUBLIC_API(JSStackFrame *)
+JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Return a weak reference to fp's principals. A null return does not denote
+ * an error, it means there are no principals.
+ */
+extern JS_PUBLIC_API(JSPrincipals *)
+JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * This API is like JS_StackFramePrincipals(cx, caller), except that if
+ * cx->runtime->findObjectPrincipals is non-null, it returns the weaker of
+ * the caller's principals and the object principals of fp's callee function
+ * object (fp->argv[-2]), which is eval, Function, or a similar eval-like
+ * method. The caller parameter should be JS_GetScriptedCaller(cx, fp).
+ *
+ * All eval-like methods must use JS_EvalFramePrincipals to acquire a weak
+ * reference to the correct principals for the eval call to be secure, given
+ * an embedding that calls JS_SetObjectPrincipalsFinder (see jsapi.h).
+ */
+extern JS_PUBLIC_API(JSPrincipals *)
+JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller);
+
+extern JS_PUBLIC_API(void *)
+JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(void)
+JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
+
+extern JS_PUBLIC_API(void *)
+JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp);
+
+/* this is deprecated, use JS_GetFrameScopeChain instead */
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameObject(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameThis(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSFunction *)
+JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp);
+
+/* XXXrginda Initially published with typo */
+#define JS_IsContructorFrame JS_IsConstructorFrame
+extern JS_PUBLIC_API(JSBool)
+JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(jsval)
+JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp);
+
+extern JS_PUBLIC_API(void)
+JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval);
+
+/**
+ * Return fp's callee function object (fp->callee) if it has one.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(const char *)
+JS_GetScriptFilename(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(uintN)
+JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(uintN)
+JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_GetScriptVersion(JSContext *cx, JSScript *script);
+
+/************************************************************************/
+
+/*
+ * Hook setters for script creation and destruction, see jsprvtd.h for the
+ * typedefs. These macros provide binary compatibility and newer, shorter
+ * synonyms.
+ */
+#define JS_SetNewScriptHook JS_SetNewScriptHookProc
+#define JS_SetDestroyScriptHook JS_SetDestroyScriptHookProc
+
+extern JS_PUBLIC_API(void)
+JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata);
+
+extern JS_PUBLIC_API(void)
+JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
+ void *callerdata);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const jschar *chars, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+extern JS_PUBLIC_API(JSBool)
+JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
+ const char *bytes, uintN length,
+ const char *filename, uintN lineno,
+ jsval *rval);
+
+/************************************************************************/
+
+typedef struct JSPropertyDesc {
+ jsval id; /* primary id, a string or int */
+ jsval value; /* property value */
+ uint8 flags; /* flags, see below */
+ uint8 spare; /* unused */
+ uint16 slot; /* argument/variable slot */
+ jsval alias; /* alias id if JSPD_ALIAS flag */
+} JSPropertyDesc;
+
+#define JSPD_ENUMERATE 0x01 /* visible to for/in loop */
+#define JSPD_READONLY 0x02 /* assignment is error */
+#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
+#define JSPD_ALIAS 0x08 /* property has an alias id */
+#define JSPD_ARGUMENT 0x10 /* argument to function */
+#define JSPD_VARIABLE 0x20 /* local variable in function */
+#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */
+ /* value is exception */
+#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
+ /* throwing an exception */
+
+typedef struct JSPropertyDescArray {
+ uint32 length; /* number of elements in array */
+ JSPropertyDesc *array; /* alloc'd by Get, freed by Put */
+} JSPropertyDescArray;
+
+extern JS_PUBLIC_API(JSScopeProperty *)
+JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
+ JSPropertyDesc *pd);
+
+extern JS_PUBLIC_API(JSBool)
+JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
+
+extern JS_PUBLIC_API(void)
+JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure);
+
+extern JS_PUBLIC_API(JSBool)
+JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(size_t)
+JS_GetObjectTotalSize(JSContext *cx, JSObject *obj);
+
+extern JS_PUBLIC_API(size_t)
+JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun);
+
+extern JS_PUBLIC_API(size_t)
+JS_GetScriptTotalSize(JSContext *cx, JSScript *script);
+
+/*
+ * Get the top-most running script on cx starting from fp, or from the top of
+ * cx's frame stack if fp is null, and return its script filename flags. If
+ * the script has a null filename member, return JSFILENAME_NULL.
+ */
+extern JS_PUBLIC_API(uint32)
+JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Get the script filename flags for the script. If the script doesn't have a
+ * filename, return JSFILENAME_NULL.
+ */
+extern JS_PUBLIC_API(uint32)
+JS_GetScriptFilenameFlags(JSScript *script);
+
+/*
+ * Associate flags with a script filename prefix in rt, so that any subsequent
+ * script compilation will inherit those flags if the script's filename is the
+ * same as prefix, or if prefix is a substring of the script's filename.
+ *
+ * The API defines only one flag bit, JSFILENAME_SYSTEM, leaving the remaining
+ * 31 bits up to the API client to define. The union of all 32 bits must not
+ * be a legal combination, however, in order to preserve JSFILENAME_NULL as a
+ * unique value. API clients may depend on JSFILENAME_SYSTEM being a set bit
+ * in JSFILENAME_NULL -- a script with a null filename member is presumed to
+ * be a "system" script.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags);
+
+#define JSFILENAME_NULL 0xffffffff /* null script filename */
+#define JSFILENAME_SYSTEM 0x00000001 /* "system" script, see below */
+#define JSFILENAME_PROTECTED 0x00000002 /* scripts need protection */
+
+/*
+ * Return true if obj is a "system" object, that is, one created by
+ * JS_NewSystemObject with the system flag set and not JS_NewObject.
+ *
+ * What "system" means is up to the API client, but it can be used to implement
+ * access control policies based on script filenames and their prefixes, using
+ * JS_FlagScriptFilenamePrefix and JS_GetTopScriptFilenameFlags.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_IsSystemObject(JSContext *cx, JSObject *obj);
+
+/*
+ * Call JS_NewObject(cx, clasp, proto, parent) and, if system is true, mark the
+ * result as a system object, that is an object for which JS_IsSystemObject
+ * returns true.
+ */
+extern JS_PUBLIC_API(JSObject *)
+JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, JSBool system);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(JSDebugHooks *)
+JS_GetGlobalDebugHooks(JSRuntime *rt);
+
+extern JS_PUBLIC_API(JSDebugHooks *)
+JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks);
+
+#ifdef MOZ_SHARK
+
+extern JS_PUBLIC_API(JSBool)
+JS_StartChudRemote();
+
+extern JS_PUBLIC_API(JSBool)
+JS_StopChudRemote();
+
+extern JS_PUBLIC_API(JSBool)
+JS_ConnectShark();
+
+extern JS_PUBLIC_API(JSBool)
+JS_DisconnectShark();
+
+extern JS_FRIEND_API(JSBool)
+js_StopShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_StartShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_ConnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_DisconnectShark(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+#endif /* MOZ_SHARK */
+
+#ifdef MOZ_CALLGRIND
+
+extern JS_FRIEND_API(JSBool)
+js_StopCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_StartCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_DumpCallgrind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+#endif /* MOZ_CALLGRIND */
+
+#ifdef MOZ_VTUNE
+
+extern JS_FRIEND_API(JSBool)
+js_StartVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_StopVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_PauseVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JS_FRIEND_API(JSBool)
+js_ResumeVtune(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+#endif /* MOZ_VTUNE */
+
+JS_END_EXTERN_C
+
+#endif /* jsdbgapi_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp
new file mode 100644
index 0000000..58cd440
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.cpp
@@ -0,0 +1,876 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ * Chris Waterson <waterson@netscape.com>
+ * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Double hashing implementation.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jsbit.h"
+#include "jsdhash.h"
+#include "jsutil.h" /* for JS_ASSERT */
+
+#ifdef JS_DHASHMETER
+# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan
+# include "nsTraceMalloc.h"
+# endif
+# define METER(x) x
+#else
+# define METER(x) /* nothing */
+#endif
+
+/*
+ * The following DEBUG-only code is used to assert that calls to one of
+ * table->ops or to an enumerator do not cause re-entry into a call that
+ * can mutate the table. The recursion level is stored in additional
+ * space allocated at the end of the entry store to avoid changing
+ * JSDHashTable, which could cause issues when mixing DEBUG and
+ * non-DEBUG components.
+ */
+#ifdef DEBUG
+
+#define JSDHASH_ONELINE_ASSERT JS_ASSERT
+#define RECURSION_LEVEL(table_) (*(uint32*)(table_->entryStore + \
+ JS_DHASH_TABLE_SIZE(table_) * \
+ table_->entrySize))
+
+#define ENTRY_STORE_EXTRA sizeof(uint32)
+#define INCREMENT_RECURSION_LEVEL(table_) \
+ JS_BEGIN_MACRO \
+ ++RECURSION_LEVEL(table_); \
+ JS_END_MACRO
+#define DECREMENT_RECURSION_LEVEL(table_) \
+ JS_BEGIN_MACRO \
+ JSDHASH_ONELINE_ASSERT(RECURSION_LEVEL(table_) > 0); \
+ --RECURSION_LEVEL(table_); \
+ JS_END_MACRO
+
+#else
+
+#define ENTRY_STORE_EXTRA 0
+#define INCREMENT_RECURSION_LEVEL(table_) JS_BEGIN_MACRO JS_END_MACRO
+#define DECREMENT_RECURSION_LEVEL(table_) JS_BEGIN_MACRO JS_END_MACRO
+
+#endif /* defined(DEBUG) */
+
+JS_PUBLIC_API(void *)
+JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes)
+{
+ return malloc(nbytes);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashFreeTable(JSDHashTable *table, void *ptr)
+{
+ free(ptr);
+}
+
+JS_PUBLIC_API(JSDHashNumber)
+JS_DHashStringKey(JSDHashTable *table, const void *key)
+{
+ JSDHashNumber h;
+ const unsigned char *s;
+
+ h = 0;
+ for (s = (const unsigned char *) key; *s != '\0'; s++)
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
+ return h;
+}
+
+JS_PUBLIC_API(JSDHashNumber)
+JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key)
+{
+ return (JSDHashNumber)(unsigned long)key >> 2;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DHashMatchEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key)
+{
+ const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
+
+ return stub->key == key;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DHashMatchStringKey(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key)
+{
+ const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
+
+ /* XXX tolerate null keys on account of sloppy Mozilla callers. */
+ return stub->key == key ||
+ (stub->key && key &&
+ strcmp((const char *) stub->key, (const char *) key) == 0);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashMoveEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *from,
+ JSDHashEntryHdr *to)
+{
+ memcpy(to, from, table->entrySize);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry)
+{
+ memset(entry, 0, table->entrySize);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry)
+{
+ const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
+
+ free((void *) stub->key);
+ memset(entry, 0, table->entrySize);
+}
+
+JS_PUBLIC_API(void)
+JS_DHashFinalizeStub(JSDHashTable *table)
+{
+}
+
+static const JSDHashTableOps stub_ops = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ JS_DHashVoidPtrKeyStub,
+ JS_DHashMatchEntryStub,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+JS_PUBLIC_API(const JSDHashTableOps *)
+JS_DHashGetStubOps(void)
+{
+ return &stub_ops;
+}
+
+JS_PUBLIC_API(JSDHashTable *)
+JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize,
+ uint32 capacity)
+{
+ JSDHashTable *table;
+
+ table = (JSDHashTable *) malloc(sizeof *table);
+ if (!table)
+ return NULL;
+ if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) {
+ free(table);
+ return NULL;
+ }
+ return table;
+}
+
+JS_PUBLIC_API(void)
+JS_DHashTableDestroy(JSDHashTable *table)
+{
+ JS_DHashTableFinish(table);
+ free(table);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
+ uint32 entrySize, uint32 capacity)
+{
+ int log2;
+ uint32 nbytes;
+
+#ifdef DEBUG
+ if (entrySize > 10 * sizeof(void *)) {
+ fprintf(stderr,
+ "jsdhash: for the table at address %p, the given entrySize"
+ " of %lu %s favors chaining over double hashing.\n",
+ (void *) table,
+ (unsigned long) entrySize,
+ (entrySize > 16 * sizeof(void*)) ? "definitely" : "probably");
+ }
+#endif
+
+ table->ops = ops;
+ table->data = data;
+ if (capacity < JS_DHASH_MIN_SIZE)
+ capacity = JS_DHASH_MIN_SIZE;
+
+ JS_CEILING_LOG2(log2, capacity);
+
+ capacity = JS_BIT(log2);
+ if (capacity >= JS_DHASH_SIZE_LIMIT)
+ return JS_FALSE;
+ table->hashShift = JS_DHASH_BITS - log2;
+ table->maxAlphaFrac = (uint8)(0x100 * JS_DHASH_DEFAULT_MAX_ALPHA);
+ table->minAlphaFrac = (uint8)(0x100 * JS_DHASH_DEFAULT_MIN_ALPHA);
+ table->entrySize = entrySize;
+ table->entryCount = table->removedCount = 0;
+ table->generation = 0;
+ nbytes = capacity * entrySize;
+
+ table->entryStore = (char *) ops->allocTable(table,
+ nbytes + ENTRY_STORE_EXTRA);
+ if (!table->entryStore)
+ return JS_FALSE;
+ memset(table->entryStore, 0, nbytes);
+ METER(memset(&table->stats, 0, sizeof table->stats));
+
+#ifdef DEBUG
+ RECURSION_LEVEL(table) = 0;
+#endif
+
+ return JS_TRUE;
+}
+
+/*
+ * Compute max and min load numbers (entry counts) from table params.
+ */
+#define MAX_LOAD(table, size) (((table)->maxAlphaFrac * (size)) >> 8)
+#define MIN_LOAD(table, size) (((table)->minAlphaFrac * (size)) >> 8)
+
+JS_PUBLIC_API(void)
+JS_DHashTableSetAlphaBounds(JSDHashTable *table,
+ float maxAlpha,
+ float minAlpha)
+{
+ uint32 size;
+
+ /*
+ * Reject obviously insane bounds, rather than trying to guess what the
+ * buggy caller intended.
+ */
+ JS_ASSERT(0.5 <= maxAlpha && maxAlpha < 1 && 0 <= minAlpha);
+ if (maxAlpha < 0.5 || 1 <= maxAlpha || minAlpha < 0)
+ return;
+
+ /*
+ * Ensure that at least one entry will always be free. If maxAlpha at
+ * minimum size leaves no entries free, reduce maxAlpha based on minimum
+ * size and the precision limit of maxAlphaFrac's fixed point format.
+ */
+ JS_ASSERT(JS_DHASH_MIN_SIZE - (maxAlpha * JS_DHASH_MIN_SIZE) >= 1);
+ if (JS_DHASH_MIN_SIZE - (maxAlpha * JS_DHASH_MIN_SIZE) < 1) {
+ maxAlpha = (float)
+ (JS_DHASH_MIN_SIZE - JS_MAX(JS_DHASH_MIN_SIZE / 256, 1))
+ / JS_DHASH_MIN_SIZE;
+ }
+
+ /*
+ * Ensure that minAlpha is strictly less than half maxAlpha. Take care
+ * not to truncate an entry's worth of alpha when storing in minAlphaFrac
+ * (8-bit fixed point format).
+ */
+ JS_ASSERT(minAlpha < maxAlpha / 2);
+ if (minAlpha >= maxAlpha / 2) {
+ size = JS_DHASH_TABLE_SIZE(table);
+ minAlpha = (size * maxAlpha - JS_MAX(size / 256, 1)) / (2 * size);
+ }
+
+ table->maxAlphaFrac = (uint8)(maxAlpha * 256);
+ table->minAlphaFrac = (uint8)(minAlpha * 256);
+}
+
+/*
+ * Double hashing needs the second hash code to be relatively prime to table
+ * size, so we simply make hash2 odd.
+ */
+#define HASH1(hash0, shift) ((hash0) >> (shift))
+#define HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
+
+/*
+ * Reserve keyHash 0 for free entries and 1 for removed-entry sentinels. Note
+ * that a removed-entry sentinel need be stored only if the removed entry had
+ * a colliding entry added after it. Therefore we can use 1 as the collision
+ * flag in addition to the removed-entry sentinel value. Multiplicative hash
+ * uses the high order bits of keyHash, so this least-significant reservation
+ * should not hurt the hash function's effectiveness much.
+ *
+ * If you change any of these magic numbers, also update JS_DHASH_ENTRY_IS_LIVE
+ * in jsdhash.h. It used to be private to jsdhash.c, but then became public to
+ * assist iterator writers who inspect table->entryStore directly.
+ */
+#define COLLISION_FLAG ((JSDHashNumber) 1)
+#define MARK_ENTRY_FREE(entry) ((entry)->keyHash = 0)
+#define MARK_ENTRY_REMOVED(entry) ((entry)->keyHash = 1)
+#define ENTRY_IS_REMOVED(entry) ((entry)->keyHash == 1)
+#define ENTRY_IS_LIVE(entry) JS_DHASH_ENTRY_IS_LIVE(entry)
+#define ENSURE_LIVE_KEYHASH(hash0) if (hash0 < 2) hash0 -= 2; else (void)0
+
+/* Match an entry's keyHash against an unstored one computed from a key. */
+#define MATCH_ENTRY_KEYHASH(entry,hash0) \
+ (((entry)->keyHash & ~COLLISION_FLAG) == (hash0))
+
+/* Compute the address of the indexed entry in table. */
+#define ADDRESS_ENTRY(table, index) \
+ ((JSDHashEntryHdr *)((table)->entryStore + (index) * (table)->entrySize))
+
+JS_PUBLIC_API(void)
+JS_DHashTableFinish(JSDHashTable *table)
+{
+ char *entryAddr, *entryLimit;
+ uint32 entrySize;
+ JSDHashEntryHdr *entry;
+
+#ifdef DEBUG_XXXbrendan
+ static FILE *dumpfp = NULL;
+ if (!dumpfp) dumpfp = fopen("/tmp/jsdhash.bigdump", "w");
+ if (dumpfp) {
+#ifdef MOZILLA_CLIENT
+ NS_TraceStack(1, dumpfp);
+#endif
+ JS_DHashTableDumpMeter(table, NULL, dumpfp);
+ fputc('\n', dumpfp);
+ }
+#endif
+
+ INCREMENT_RECURSION_LEVEL(table);
+
+ /* Call finalize before clearing entries, so it can enumerate them. */
+ table->ops->finalize(table);
+
+ /* Clear any remaining live entries. */
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ entryLimit = entryAddr + JS_DHASH_TABLE_SIZE(table) * entrySize;
+ while (entryAddr < entryLimit) {
+ entry = (JSDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ METER(table->stats.removeEnums++);
+ table->ops->clearEntry(table, entry);
+ }
+ entryAddr += entrySize;
+ }
+
+ DECREMENT_RECURSION_LEVEL(table);
+ JS_ASSERT(RECURSION_LEVEL(table) == 0);
+
+ /* Free entry storage last. */
+ table->ops->freeTable(table, table->entryStore);
+}
+
+static JSDHashEntryHdr * JS_DHASH_FASTCALL
+SearchTable(JSDHashTable *table, const void *key, JSDHashNumber keyHash,
+ JSDHashOperator op)
+{
+ JSDHashNumber hash1, hash2;
+ int hashShift, sizeLog2;
+ JSDHashEntryHdr *entry, *firstRemoved;
+ JSDHashMatchEntry matchEntry;
+ uint32 sizeMask;
+
+ METER(table->stats.searches++);
+ JS_ASSERT(!(keyHash & COLLISION_FLAG));
+
+ /* Compute the primary hash address. */
+ hashShift = table->hashShift;
+ hash1 = HASH1(keyHash, hashShift);
+ entry = ADDRESS_ENTRY(table, hash1);
+
+ /* Miss: return space for a new entry. */
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+
+ /* Hit: return entry. */
+ matchEntry = table->ops->matchEntry;
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) && matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = JS_DHASH_BITS - table->hashShift;
+ hash2 = HASH2(keyHash, sizeLog2, hashShift);
+ sizeMask = JS_BITMASK(sizeLog2);
+
+ /* Save the first removed entry pointer so JS_DHASH_ADD can recycle it. */
+ firstRemoved = NULL;
+
+ for (;;) {
+ if (JS_UNLIKELY(ENTRY_IS_REMOVED(entry))) {
+ if (!firstRemoved)
+ firstRemoved = entry;
+ } else {
+ if (op == JS_DHASH_ADD)
+ entry->keyHash |= COLLISION_FLAG;
+ }
+
+ METER(table->stats.steps++);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+
+ entry = ADDRESS_ENTRY(table, hash1);
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return (firstRemoved && op == JS_DHASH_ADD) ? firstRemoved : entry;
+ }
+
+ if (MATCH_ENTRY_KEYHASH(entry, keyHash) &&
+ matchEntry(table, entry, key)) {
+ METER(table->stats.hits++);
+ return entry;
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+/*
+ * This is a copy of SearchTable, used by ChangeTable, hardcoded to
+ * 1. assume |op == PL_DHASH_ADD|,
+ * 2. assume that |key| will never match an existing entry, and
+ * 3. assume that no entries have been removed from the current table
+ * structure.
+ * Avoiding the need for |key| means we can avoid needing a way to map
+ * entries to keys, which means callers can use complex key types more
+ * easily.
+ */
+static JSDHashEntryHdr * JS_DHASH_FASTCALL
+FindFreeEntry(JSDHashTable *table, JSDHashNumber keyHash)
+{
+ JSDHashNumber hash1, hash2;
+ int hashShift, sizeLog2;
+ JSDHashEntryHdr *entry;
+ uint32 sizeMask;
+
+ METER(table->stats.searches++);
+ JS_ASSERT(!(keyHash & COLLISION_FLAG));
+
+ /* Compute the primary hash address. */
+ hashShift = table->hashShift;
+ hash1 = HASH1(keyHash, hashShift);
+ entry = ADDRESS_ENTRY(table, hash1);
+
+ /* Miss: return space for a new entry. */
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = JS_DHASH_BITS - table->hashShift;
+ hash2 = HASH2(keyHash, sizeLog2, hashShift);
+ sizeMask = JS_BITMASK(sizeLog2);
+
+ for (;;) {
+ JS_ASSERT(!ENTRY_IS_REMOVED(entry));
+ entry->keyHash |= COLLISION_FLAG;
+
+ METER(table->stats.steps++);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+
+ entry = ADDRESS_ENTRY(table, hash1);
+ if (JS_DHASH_ENTRY_IS_FREE(entry)) {
+ METER(table->stats.misses++);
+ return entry;
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+static JSBool
+ChangeTable(JSDHashTable *table, int deltaLog2)
+{
+ int oldLog2, newLog2;
+ uint32 oldCapacity, newCapacity;
+ char *newEntryStore, *oldEntryStore, *oldEntryAddr;
+ uint32 entrySize, i, nbytes;
+ JSDHashEntryHdr *oldEntry, *newEntry;
+ JSDHashMoveEntry moveEntry;
+#ifdef DEBUG
+ uint32 recursionLevel;
+#endif
+
+ /* Look, but don't touch, until we succeed in getting new entry store. */
+ oldLog2 = JS_DHASH_BITS - table->hashShift;
+ newLog2 = oldLog2 + deltaLog2;
+ oldCapacity = JS_BIT(oldLog2);
+ newCapacity = JS_BIT(newLog2);
+ if (newCapacity >= JS_DHASH_SIZE_LIMIT)
+ return JS_FALSE;
+ entrySize = table->entrySize;
+ nbytes = newCapacity * entrySize;
+
+ newEntryStore = (char *) table->ops->allocTable(table,
+ nbytes + ENTRY_STORE_EXTRA);
+ if (!newEntryStore)
+ return JS_FALSE;
+
+ /* We can't fail from here on, so update table parameters. */
+#ifdef DEBUG
+ recursionLevel = RECURSION_LEVEL(table);
+#endif
+ table->hashShift = JS_DHASH_BITS - newLog2;
+ table->removedCount = 0;
+ table->generation++;
+
+ /* Assign the new entry store to table. */
+ memset(newEntryStore, 0, nbytes);
+ oldEntryAddr = oldEntryStore = table->entryStore;
+ table->entryStore = newEntryStore;
+ moveEntry = table->ops->moveEntry;
+#ifdef DEBUG
+ RECURSION_LEVEL(table) = recursionLevel;
+#endif
+
+ /* Copy only live entries, leaving removed ones behind. */
+ for (i = 0; i < oldCapacity; i++) {
+ oldEntry = (JSDHashEntryHdr *)oldEntryAddr;
+ if (ENTRY_IS_LIVE(oldEntry)) {
+ oldEntry->keyHash &= ~COLLISION_FLAG;
+ newEntry = FindFreeEntry(table, oldEntry->keyHash);
+ JS_ASSERT(JS_DHASH_ENTRY_IS_FREE(newEntry));
+ moveEntry(table, oldEntry, newEntry);
+ newEntry->keyHash = oldEntry->keyHash;
+ }
+ oldEntryAddr += entrySize;
+ }
+
+ table->ops->freeTable(table, oldEntryStore);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL
+JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op)
+{
+ JSDHashNumber keyHash;
+ JSDHashEntryHdr *entry;
+ uint32 size;
+ int deltaLog2;
+
+ JS_ASSERT(op == JS_DHASH_LOOKUP || RECURSION_LEVEL(table) == 0);
+ INCREMENT_RECURSION_LEVEL(table);
+
+ keyHash = table->ops->hashKey(table, key);
+ keyHash *= JS_DHASH_GOLDEN_RATIO;
+
+ /* Avoid 0 and 1 hash codes, they indicate free and removed entries. */
+ ENSURE_LIVE_KEYHASH(keyHash);
+ keyHash &= ~COLLISION_FLAG;
+
+ switch (op) {
+ case JS_DHASH_LOOKUP:
+ METER(table->stats.lookups++);
+ entry = SearchTable(table, key, keyHash, op);
+ break;
+
+ case JS_DHASH_ADD:
+ /*
+ * If alpha is >= .75, grow or compress the table. If key is already
+ * in the table, we may grow once more than necessary, but only if we
+ * are on the edge of being overloaded.
+ */
+ size = JS_DHASH_TABLE_SIZE(table);
+ if (table->entryCount + table->removedCount >= MAX_LOAD(table, size)) {
+ /* Compress if a quarter or more of all entries are removed. */
+ if (table->removedCount >= size >> 2) {
+ METER(table->stats.compresses++);
+ deltaLog2 = 0;
+ } else {
+ METER(table->stats.grows++);
+ deltaLog2 = 1;
+ }
+
+ /*
+ * Grow or compress table, returning null if ChangeTable fails and
+ * falling through might claim the last free entry.
+ */
+ if (!ChangeTable(table, deltaLog2) &&
+ table->entryCount + table->removedCount == size - 1) {
+ METER(table->stats.addFailures++);
+ entry = NULL;
+ break;
+ }
+ }
+
+ /*
+ * Look for entry after possibly growing, so we don't have to add it,
+ * then skip it while growing the table and re-add it after.
+ */
+ entry = SearchTable(table, key, keyHash, op);
+ if (!ENTRY_IS_LIVE(entry)) {
+ /* Initialize the entry, indicating that it's no longer free. */
+ METER(table->stats.addMisses++);
+ if (ENTRY_IS_REMOVED(entry)) {
+ METER(table->stats.addOverRemoved++);
+ table->removedCount--;
+ keyHash |= COLLISION_FLAG;
+ }
+ if (table->ops->initEntry &&
+ !table->ops->initEntry(table, entry, key)) {
+ /* We haven't claimed entry yet; fail with null return. */
+ memset(entry + 1, 0, table->entrySize - sizeof *entry);
+ entry = NULL;
+ break;
+ }
+ entry->keyHash = keyHash;
+ table->entryCount++;
+ }
+ METER(else table->stats.addHits++);
+ break;
+
+ case JS_DHASH_REMOVE:
+ entry = SearchTable(table, key, keyHash, op);
+ if (ENTRY_IS_LIVE(entry)) {
+ /* Clear this entry and mark it as "removed". */
+ METER(table->stats.removeHits++);
+ JS_DHashTableRawRemove(table, entry);
+
+ /* Shrink if alpha is <= .25 and table isn't too small already. */
+ size = JS_DHASH_TABLE_SIZE(table);
+ if (size > JS_DHASH_MIN_SIZE &&
+ table->entryCount <= MIN_LOAD(table, size)) {
+ METER(table->stats.shrinks++);
+ (void) ChangeTable(table, -1);
+ }
+ }
+ METER(else table->stats.removeMisses++);
+ entry = NULL;
+ break;
+
+ default:
+ JS_ASSERT(0);
+ entry = NULL;
+ }
+
+ DECREMENT_RECURSION_LEVEL(table);
+
+ return entry;
+}
+
+JS_PUBLIC_API(void)
+JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry)
+{
+ JSDHashNumber keyHash; /* load first in case clearEntry goofs it */
+
+ JS_ASSERT(JS_DHASH_ENTRY_IS_LIVE(entry));
+ keyHash = entry->keyHash;
+ table->ops->clearEntry(table, entry);
+ if (keyHash & COLLISION_FLAG) {
+ MARK_ENTRY_REMOVED(entry);
+ table->removedCount++;
+ } else {
+ METER(table->stats.removeFrees++);
+ MARK_ENTRY_FREE(entry);
+ }
+ table->entryCount--;
+}
+
+JS_PUBLIC_API(uint32)
+JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg)
+{
+ char *entryAddr, *entryLimit;
+ uint32 i, capacity, entrySize, ceiling;
+ JSBool didRemove;
+ JSDHashEntryHdr *entry;
+ JSDHashOperator op;
+
+ INCREMENT_RECURSION_LEVEL(table);
+
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ capacity = JS_DHASH_TABLE_SIZE(table);
+ entryLimit = entryAddr + capacity * entrySize;
+ i = 0;
+ didRemove = JS_FALSE;
+ while (entryAddr < entryLimit) {
+ entry = (JSDHashEntryHdr *)entryAddr;
+ if (ENTRY_IS_LIVE(entry)) {
+ op = etor(table, entry, i++, arg);
+ if (op & JS_DHASH_REMOVE) {
+ METER(table->stats.removeEnums++);
+ JS_DHashTableRawRemove(table, entry);
+ didRemove = JS_TRUE;
+ }
+ if (op & JS_DHASH_STOP)
+ break;
+ }
+ entryAddr += entrySize;
+ }
+
+ JS_ASSERT(!didRemove || RECURSION_LEVEL(table) == 1);
+
+ /*
+ * Shrink or compress if a quarter or more of all entries are removed, or
+ * if the table is underloaded according to the configured minimum alpha,
+ * and is not minimal-size already. Do this only if we removed above, so
+ * non-removing enumerations can count on stable table->entryStore until
+ * the next non-lookup-Operate or removing-Enumerate.
+ */
+ if (didRemove &&
+ (table->removedCount >= capacity >> 2 ||
+ (capacity > JS_DHASH_MIN_SIZE &&
+ table->entryCount <= MIN_LOAD(table, capacity)))) {
+ METER(table->stats.enumShrinks++);
+ capacity = table->entryCount;
+ capacity += capacity >> 1;
+ if (capacity < JS_DHASH_MIN_SIZE)
+ capacity = JS_DHASH_MIN_SIZE;
+
+ JS_CEILING_LOG2(ceiling, capacity);
+ ceiling -= JS_DHASH_BITS - table->hashShift;
+
+ (void) ChangeTable(table, ceiling);
+ }
+
+ DECREMENT_RECURSION_LEVEL(table);
+
+ return i;
+}
+
+#ifdef JS_DHASHMETER
+#include <math.h>
+
+JS_PUBLIC_API(void)
+JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp)
+{
+ char *entryAddr;
+ uint32 entrySize, entryCount;
+ int hashShift, sizeLog2;
+ uint32 i, tableSize, sizeMask, chainLen, maxChainLen, chainCount;
+ JSDHashNumber hash1, hash2, saveHash1, maxChainHash1, maxChainHash2;
+ double sqsum, mean, variance, sigma;
+ JSDHashEntryHdr *entry, *probe;
+
+ entryAddr = table->entryStore;
+ entrySize = table->entrySize;
+ hashShift = table->hashShift;
+ sizeLog2 = JS_DHASH_BITS - hashShift;
+ tableSize = JS_DHASH_TABLE_SIZE(table);
+ sizeMask = JS_BITMASK(sizeLog2);
+ chainCount = maxChainLen = 0;
+ hash2 = 0;
+ sqsum = 0;
+
+ for (i = 0; i < tableSize; i++) {
+ entry = (JSDHashEntryHdr *)entryAddr;
+ entryAddr += entrySize;
+ if (!ENTRY_IS_LIVE(entry))
+ continue;
+ hash1 = HASH1(entry->keyHash & ~COLLISION_FLAG, hashShift);
+ saveHash1 = hash1;
+ probe = ADDRESS_ENTRY(table, hash1);
+ chainLen = 1;
+ if (probe == entry) {
+ /* Start of a (possibly unit-length) chain. */
+ chainCount++;
+ } else {
+ hash2 = HASH2(entry->keyHash & ~COLLISION_FLAG, sizeLog2,
+ hashShift);
+ do {
+ chainLen++;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ probe = ADDRESS_ENTRY(table, hash1);
+ } while (probe != entry);
+ }
+ sqsum += chainLen * chainLen;
+ if (chainLen > maxChainLen) {
+ maxChainLen = chainLen;
+ maxChainHash1 = saveHash1;
+ maxChainHash2 = hash2;
+ }
+ }
+
+ entryCount = table->entryCount;
+ if (entryCount && chainCount) {
+ mean = (double)entryCount / chainCount;
+ variance = chainCount * sqsum - entryCount * entryCount;
+ if (variance < 0 || chainCount == 1)
+ variance = 0;
+ else
+ variance /= chainCount * (chainCount - 1);
+ sigma = sqrt(variance);
+ } else {
+ mean = sigma = 0;
+ }
+
+ fprintf(fp, "Double hashing statistics:\n");
+ fprintf(fp, " table size (in entries): %u\n", tableSize);
+ fprintf(fp, " number of entries: %u\n", table->entryCount);
+ fprintf(fp, " number of removed entries: %u\n", table->removedCount);
+ fprintf(fp, " number of searches: %u\n", table->stats.searches);
+ fprintf(fp, " number of hits: %u\n", table->stats.hits);
+ fprintf(fp, " number of misses: %u\n", table->stats.misses);
+ fprintf(fp, " mean steps per search: %g\n", table->stats.searches ?
+ (double)table->stats.steps
+ / table->stats.searches :
+ 0.);
+ fprintf(fp, " mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " maximum hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " number of lookups: %u\n", table->stats.lookups);
+ fprintf(fp, " adds that made a new entry: %u\n", table->stats.addMisses);
+ fprintf(fp, "adds that recycled removeds: %u\n", table->stats.addOverRemoved);
+ fprintf(fp, " adds that found an entry: %u\n", table->stats.addHits);
+ fprintf(fp, " add failures: %u\n", table->stats.addFailures);
+ fprintf(fp, " useful removes: %u\n", table->stats.removeHits);
+ fprintf(fp, " useless removes: %u\n", table->stats.removeMisses);
+ fprintf(fp, "removes that freed an entry: %u\n", table->stats.removeFrees);
+ fprintf(fp, " removes while enumerating: %u\n", table->stats.removeEnums);
+ fprintf(fp, " number of grows: %u\n", table->stats.grows);
+ fprintf(fp, " number of shrinks: %u\n", table->stats.shrinks);
+ fprintf(fp, " number of compresses: %u\n", table->stats.compresses);
+ fprintf(fp, "number of enumerate shrinks: %u\n", table->stats.enumShrinks);
+
+ if (dump && maxChainLen && hash2) {
+ fputs("Maximum hash chain:\n", fp);
+ hash1 = maxChainHash1;
+ hash2 = maxChainHash2;
+ entry = ADDRESS_ENTRY(table, hash1);
+ i = 0;
+ do {
+ if (dump(table, entry, i++, fp) != JS_DHASH_NEXT)
+ break;
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ entry = ADDRESS_ENTRY(table, hash1);
+ } while (JS_DHASH_ENTRY_IS_BUSY(entry));
+ }
+}
+#endif /* JS_DHASHMETER */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h
new file mode 100644
index 0000000..5e17b26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdhash.h
@@ -0,0 +1,588 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1999-2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsdhash_h___
+#define jsdhash_h___
+/*
+ * Double hashing, a la Knuth 6.
+ */
+#include "jstypes.h"
+
+JS_BEGIN_EXTERN_C
+
+#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
+#define JS_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
+#elif defined(XP_WIN)
+#define JS_DHASH_FASTCALL __fastcall
+#else
+#define JS_DHASH_FASTCALL
+#endif
+
+#ifdef DEBUG_XXXbrendan
+#define JS_DHASHMETER 1
+#endif
+
+/* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */
+#undef JS_DHASH_SIZE_LIMIT
+#define JS_DHASH_SIZE_LIMIT JS_BIT(24)
+
+/* Minimum table size, or gross entry count (net is at most .75 loaded). */
+#ifndef JS_DHASH_MIN_SIZE
+#define JS_DHASH_MIN_SIZE 16
+#elif (JS_DHASH_MIN_SIZE & (JS_DHASH_MIN_SIZE - 1)) != 0
+#error "JS_DHASH_MIN_SIZE must be a power of two!"
+#endif
+
+/*
+ * Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
+ * expressed as a fixed-point 32-bit fraction.
+ */
+#define JS_DHASH_BITS 32
+#define JS_DHASH_GOLDEN_RATIO 0x9E3779B9U
+
+/* Primitive and forward-struct typedefs. */
+typedef uint32 JSDHashNumber;
+typedef struct JSDHashEntryHdr JSDHashEntryHdr;
+typedef struct JSDHashEntryStub JSDHashEntryStub;
+typedef struct JSDHashTable JSDHashTable;
+typedef struct JSDHashTableOps JSDHashTableOps;
+
+/*
+ * Table entry header structure.
+ *
+ * In order to allow in-line allocation of key and value, we do not declare
+ * either here. Instead, the API uses const void *key as a formal parameter.
+ * The key need not be stored in the entry; it may be part of the value, but
+ * need not be stored at all.
+ *
+ * Callback types are defined below and grouped into the JSDHashTableOps
+ * structure, for single static initialization per hash table sub-type.
+ *
+ * Each hash table sub-type should nest the JSDHashEntryHdr structure at the
+ * front of its particular entry type. The keyHash member contains the result
+ * of multiplying the hash code returned from the hashKey callback (see below)
+ * by JS_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0
+ * and 1 values. The stored keyHash value is table size invariant, and it is
+ * maintained automatically by JS_DHashTableOperate -- users should never set
+ * it, and its only uses should be via the entry macros below.
+ *
+ * The JS_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor
+ * removed. An entry may be either busy or free; if busy, it may be live or
+ * removed. Consumers of this API should not access members of entries that
+ * are not live.
+ *
+ * However, use JS_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
+ * returned by JS_DHashTableOperate, as JS_DHashTableOperate never returns a
+ * non-live, busy (i.e., removed) entry pointer to its caller. See below for
+ * more details on JS_DHashTableOperate's calling rules.
+ */
+struct JSDHashEntryHdr {
+ JSDHashNumber keyHash; /* every entry must begin like this */
+};
+
+#define JS_DHASH_ENTRY_IS_FREE(entry) ((entry)->keyHash == 0)
+#define JS_DHASH_ENTRY_IS_BUSY(entry) (!JS_DHASH_ENTRY_IS_FREE(entry))
+#define JS_DHASH_ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2)
+
+/*
+ * A JSDHashTable is currently 8 words (without the JS_DHASHMETER overhead)
+ * on most architectures, and may be allocated on the stack or within another
+ * structure or class (see below for the Init and Finish functions to use).
+ *
+ * To decide whether to use double hashing vs. chaining, we need to develop a
+ * trade-off relation, as follows:
+ *
+ * Let alpha be the load factor, esize the entry size in words, count the
+ * entry count, and pow2 the power-of-two table size in entries.
+ *
+ * (JSDHashTable overhead) > (JSHashTable overhead)
+ * (unused table entry space) > (malloc and .next overhead per entry) +
+ * (buckets overhead)
+ * (1 - alpha) * esize * pow2 > 2 * count + pow2
+ *
+ * Notice that alpha is by definition (count / pow2):
+ *
+ * (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2
+ * (1 - alpha) * esize > 2 * alpha + 1
+ *
+ * esize > (1 + 2 * alpha) / (1 - alpha)
+ *
+ * This assumes both tables must keep keyHash, key, and value for each entry,
+ * where key and value point to separately allocated strings or structures.
+ * If key and value can be combined into one pointer, then the trade-off is:
+ *
+ * esize > (1 + 3 * alpha) / (1 - alpha)
+ *
+ * If the entry value can be a subtype of JSDHashEntryHdr, rather than a type
+ * that must be allocated separately and referenced by an entry.value pointer
+ * member, and provided key's allocation can be fused with its entry's, then
+ * k (the words wasted per entry with chaining) is 4.
+ *
+ * To see these curves, feed gnuplot input like so:
+ *
+ * gnuplot> f(x,k) = (1 + k * x) / (1 - x)
+ * gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4)
+ *
+ * For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4
+ * words for chaining to be more space-efficient than double hashing.
+ *
+ * Solving for alpha helps us decide when to shrink an underloaded table:
+ *
+ * esize > (1 + k * alpha) / (1 - alpha)
+ * esize - alpha * esize > 1 + k * alpha
+ * esize - 1 > (k + esize) * alpha
+ * (esize - 1) / (k + esize) > alpha
+ *
+ * alpha < (esize - 1) / (esize + k)
+ *
+ * Therefore double hashing should keep alpha >= (esize - 1) / (esize + k),
+ * assuming esize is not too large (in which case, chaining should probably be
+ * used for any alpha). For esize=2 and k=3, we want alpha >= .2; for esize=3
+ * and k=2, we want alpha >= .4. For k=4, esize could be 6, and alpha >= .5
+ * would still obtain. See the JS_DHASH_MIN_ALPHA macro further below.
+ *
+ * The current implementation uses a configurable lower bound on alpha, which
+ * defaults to .25, when deciding to shrink the table (while still respecting
+ * JS_DHASH_MIN_SIZE).
+ *
+ * Note a qualitative difference between chaining and double hashing: under
+ * chaining, entry addresses are stable across table shrinks and grows. With
+ * double hashing, you can't safely hold an entry pointer and use it after an
+ * ADD or REMOVE operation, unless you sample table->generation before adding
+ * or removing, and compare the sample after, dereferencing the entry pointer
+ * only if table->generation has not changed.
+ *
+ * The moral of this story: there is no one-size-fits-all hash table scheme,
+ * but for small table entry size, and assuming entry address stability is not
+ * required, double hashing wins.
+ */
+struct JSDHashTable {
+ const JSDHashTableOps *ops; /* virtual operations, see below */
+ void *data; /* ops- and instance-specific data */
+ int16 hashShift; /* multiplicative hash shift */
+ uint8 maxAlphaFrac; /* 8-bit fixed point max alpha */
+ uint8 minAlphaFrac; /* 8-bit fixed point min alpha */
+ uint32 entrySize; /* number of bytes in an entry */
+ uint32 entryCount; /* number of entries in table */
+ uint32 removedCount; /* removed entry sentinels in table */
+ uint32 generation; /* entry storage generation number */
+ char *entryStore; /* entry storage */
+#ifdef JS_DHASHMETER
+ struct JSDHashStats {
+ uint32 searches; /* total number of table searches */
+ uint32 steps; /* hash chain links traversed */
+ uint32 hits; /* searches that found key */
+ uint32 misses; /* searches that didn't find key */
+ uint32 lookups; /* number of JS_DHASH_LOOKUPs */
+ uint32 addMisses; /* adds that miss, and do work */
+ uint32 addOverRemoved; /* adds that recycled a removed entry */
+ uint32 addHits; /* adds that hit an existing entry */
+ uint32 addFailures; /* out-of-memory during add growth */
+ uint32 removeHits; /* removes that hit, and do work */
+ uint32 removeMisses; /* useless removes that miss */
+ uint32 removeFrees; /* removes that freed entry directly */
+ uint32 removeEnums; /* removes done by Enumerate */
+ uint32 grows; /* table expansions */
+ uint32 shrinks; /* table contractions */
+ uint32 compresses; /* table compressions */
+ uint32 enumShrinks; /* contractions after Enumerate */
+ } stats;
+#endif
+};
+
+/*
+ * Size in entries (gross, not net of free and removed sentinels) for table.
+ * We store hashShift rather than sizeLog2 to optimize the collision-free case
+ * in SearchTable.
+ */
+#define JS_DHASH_TABLE_SIZE(table) JS_BIT(JS_DHASH_BITS - (table)->hashShift)
+
+/*
+ * Table space at entryStore is allocated and freed using these callbacks.
+ * The allocator should return null on error only (not if called with nbytes
+ * equal to 0; but note that jsdhash.c code will never call with 0 nbytes).
+ */
+typedef void *
+(* JSDHashAllocTable)(JSDHashTable *table, uint32 nbytes);
+
+typedef void
+(* JSDHashFreeTable) (JSDHashTable *table, void *ptr);
+
+/*
+ * Compute the hash code for a given key to be looked up, added, or removed
+ * from table. A hash code may have any JSDHashNumber value.
+ */
+typedef JSDHashNumber
+(* JSDHashHashKey) (JSDHashTable *table, const void *key);
+
+/*
+ * Compare the key identifying entry in table with the provided key parameter.
+ * Return JS_TRUE if keys match, JS_FALSE otherwise.
+ */
+typedef JSBool
+(* JSDHashMatchEntry)(JSDHashTable *table, const JSDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Copy the data starting at from to the new entry storage at to. Do not add
+ * reference counts for any strong references in the entry, however, as this
+ * is a "move" operation: the old entry storage at from will be freed without
+ * any reference-decrementing callback shortly.
+ */
+typedef void
+(* JSDHashMoveEntry)(JSDHashTable *table, const JSDHashEntryHdr *from,
+ JSDHashEntryHdr *to);
+
+/*
+ * Clear the entry and drop any strong references it holds. This callback is
+ * invoked during a JS_DHASH_REMOVE operation (see below for operation codes),
+ * but only if the given key is found in the table.
+ */
+typedef void
+(* JSDHashClearEntry)(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+/*
+ * Called when a table (whether allocated dynamically by itself, or nested in
+ * a larger structure, or allocated on the stack) is finished. This callback
+ * allows table->ops-specific code to finalize table->data.
+ */
+typedef void
+(* JSDHashFinalize) (JSDHashTable *table);
+
+/*
+ * Initialize a new entry, apart from keyHash. This function is called when
+ * JS_DHashTableOperate's JS_DHASH_ADD case finds no existing entry for the
+ * given key, and must add a new one. At that point, entry->keyHash is not
+ * set yet, to avoid claiming the last free entry in a severely overloaded
+ * table.
+ */
+typedef JSBool
+(* JSDHashInitEntry)(JSDHashTable *table, JSDHashEntryHdr *entry,
+ const void *key);
+
+/*
+ * Finally, the "vtable" structure for JSDHashTable. The first eight hooks
+ * must be provided by implementations; they're called unconditionally by the
+ * generic jsdhash.c code. Hooks after these may be null.
+ *
+ * Summary of allocation-related hook usage with C++ placement new emphasis:
+ * allocTable Allocate raw bytes with malloc, no ctors run.
+ * freeTable Free raw bytes with free, no dtors run.
+ * initEntry Call placement new using default key-based ctor.
+ * Return JS_TRUE on success, JS_FALSE on error.
+ * moveEntry Call placement new using copy ctor, run dtor on old
+ * entry storage.
+ * clearEntry Run dtor on entry.
+ * finalize Stub unless table->data was initialized and needs to
+ * be finalized.
+ *
+ * Note the reason why initEntry is optional: the default hooks (stubs) clear
+ * entry storage: On successful JS_DHashTableOperate(tbl, key, JS_DHASH_ADD),
+ * the returned entry pointer addresses an entry struct whose keyHash member
+ * has been set non-zero, but all other entry members are still clear (null).
+ * JS_DHASH_ADD callers can test such members to see whether the entry was
+ * newly created by the JS_DHASH_ADD call that just succeeded. If placement
+ * new or similar initialization is required, define an initEntry hook. Of
+ * course, the clearEntry hook must zero or null appropriately.
+ *
+ * XXX assumes 0 is null for pointer types.
+ */
+struct JSDHashTableOps {
+ /* Mandatory hooks. All implementations must provide these. */
+ JSDHashAllocTable allocTable;
+ JSDHashFreeTable freeTable;
+ JSDHashHashKey hashKey;
+ JSDHashMatchEntry matchEntry;
+ JSDHashMoveEntry moveEntry;
+ JSDHashClearEntry clearEntry;
+ JSDHashFinalize finalize;
+
+ /* Optional hooks start here. If null, these are not called. */
+ JSDHashInitEntry initEntry;
+};
+
+/*
+ * Default implementations for the above ops.
+ */
+extern JS_PUBLIC_API(void *)
+JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes);
+
+extern JS_PUBLIC_API(void)
+JS_DHashFreeTable(JSDHashTable *table, void *ptr);
+
+extern JS_PUBLIC_API(JSDHashNumber)
+JS_DHashStringKey(JSDHashTable *table, const void *key);
+
+/* A minimal entry contains a keyHash header and a void key pointer. */
+struct JSDHashEntryStub {
+ JSDHashEntryHdr hdr;
+ const void *key;
+};
+
+extern JS_PUBLIC_API(JSDHashNumber)
+JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DHashMatchEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key);
+
+extern JS_PUBLIC_API(JSBool)
+JS_DHashMatchStringKey(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key);
+
+extern JS_PUBLIC_API(void)
+JS_DHashMoveEntryStub(JSDHashTable *table,
+ const JSDHashEntryHdr *from,
+ JSDHashEntryHdr *to);
+
+extern JS_PUBLIC_API(void)
+JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+extern JS_PUBLIC_API(void)
+JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+extern JS_PUBLIC_API(void)
+JS_DHashFinalizeStub(JSDHashTable *table);
+
+/*
+ * If you use JSDHashEntryStub or a subclass of it as your entry struct, and
+ * if your entries move via memcpy and clear via memset(0), you can use these
+ * stub operations.
+ */
+extern JS_PUBLIC_API(const JSDHashTableOps *)
+JS_DHashGetStubOps(void);
+
+/*
+ * Dynamically allocate a new JSDHashTable using malloc, initialize it using
+ * JS_DHashTableInit, and return its address. Return null on malloc failure.
+ * Note that the entry storage at table->entryStore will be allocated using
+ * the ops->allocTable callback.
+ */
+extern JS_PUBLIC_API(JSDHashTable *)
+JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize,
+ uint32 capacity);
+
+/*
+ * Finalize table's data, free its entry storage (via table->ops->freeTable),
+ * and return the memory starting at table to the malloc heap.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableDestroy(JSDHashTable *table);
+
+/*
+ * Initialize table with ops, data, entrySize, and capacity. Capacity is a
+ * guess for the smallest table size at which the table will usually be less
+ * than 75% loaded (the table will grow or shrink as needed; capacity serves
+ * only to avoid inevitable early growth from JS_DHASH_MIN_SIZE).
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
+ uint32 entrySize, uint32 capacity);
+
+/*
+ * Set maximum and minimum alpha for table. The defaults are 0.75 and .25.
+ * maxAlpha must be in [0.5, 0.9375] for the default JS_DHASH_MIN_SIZE; or if
+ * MinSize=JS_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or
+ * else in [0.5, 255.0/256]. minAlpha must be in [0, maxAlpha / 2), so that
+ * we don't shrink on the very next remove after growing a table upon adding
+ * an entry that brings entryCount past maxAlpha * tableSize.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableSetAlphaBounds(JSDHashTable *table,
+ float maxAlpha,
+ float minAlpha);
+
+/*
+ * Call this macro with k, the number of pointer-sized words wasted per entry
+ * under chaining, to compute the minimum alpha at which double hashing still
+ * beats chaining.
+ */
+#define JS_DHASH_MIN_ALPHA(table, k) \
+ ((float)((table)->entrySize / sizeof(void *) - 1) \
+ / ((table)->entrySize / sizeof(void *) + (k)))
+
+/*
+ * Default max/min alpha, and macros to compute the value for the |capacity|
+ * parameter to JS_NewDHashTable and JS_DHashTableInit, given default or any
+ * max alpha, such that adding entryCount entries right after initializing the
+ * table will not require a reallocation (so JS_DHASH_ADD can't fail for those
+ * JS_DHashTableOperate calls).
+ *
+ * NB: JS_DHASH_CAP is a helper macro meant for use only in JS_DHASH_CAPACITY.
+ * Don't use it directly!
+ */
+#define JS_DHASH_DEFAULT_MAX_ALPHA 0.75
+#define JS_DHASH_DEFAULT_MIN_ALPHA 0.25
+
+#define JS_DHASH_CAP(entryCount, maxAlpha) \
+ ((uint32)((double)(entryCount) / (maxAlpha)))
+
+#define JS_DHASH_CAPACITY(entryCount, maxAlpha) \
+ (JS_DHASH_CAP(entryCount, maxAlpha) + \
+ (((JS_DHASH_CAP(entryCount, maxAlpha) * (uint8)(0x100 * (maxAlpha))) \
+ >> 8) < (entryCount)))
+
+#define JS_DHASH_DEFAULT_CAPACITY(entryCount) \
+ JS_DHASH_CAPACITY(entryCount, JS_DHASH_DEFAULT_MAX_ALPHA)
+
+/*
+ * Finalize table's data, free its entry storage using table->ops->freeTable,
+ * and leave its members unchanged from their last live values (which leaves
+ * pointers dangling). If you want to burn cycles clearing table, it's up to
+ * your code to call memset.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableFinish(JSDHashTable *table);
+
+/*
+ * To consolidate keyHash computation and table grow/shrink code, we use a
+ * single entry point for lookup, add, and remove operations. The operation
+ * codes are declared here, along with codes returned by JSDHashEnumerator
+ * functions, which control JS_DHashTableEnumerate's behavior.
+ */
+typedef enum JSDHashOperator {
+ JS_DHASH_LOOKUP = 0, /* lookup entry */
+ JS_DHASH_ADD = 1, /* add entry */
+ JS_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
+ JS_DHASH_NEXT = 0, /* enumerator says continue */
+ JS_DHASH_STOP = 1 /* enumerator says stop */
+} JSDHashOperator;
+
+/*
+ * To lookup a key in table, call:
+ *
+ * entry = JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP);
+ *
+ * If JS_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies
+ * entry. If JS_DHASH_ENTRY_IS_FREE(entry) is true, key was not found.
+ *
+ * To add an entry identified by key to table, call:
+ *
+ * entry = JS_DHashTableOperate(table, key, JS_DHASH_ADD);
+ *
+ * If entry is null upon return, then either the table is severely overloaded,
+ * and memory can't be allocated for entry storage via table->ops->allocTable;
+ * Or if table->ops->initEntry is non-null, the table->ops->initEntry op may
+ * have returned false.
+ *
+ * Otherwise, entry->keyHash has been set so that JS_DHASH_ENTRY_IS_BUSY(entry)
+ * is true, and it is up to the caller to initialize the key and value parts
+ * of the entry sub-type, if they have not been set already (i.e. if entry was
+ * not already in the table, and if the optional initEntry hook was not used).
+ *
+ * To remove an entry identified by key from table, call:
+ *
+ * (void) JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);
+ *
+ * If key's entry is found, it is cleared (via table->ops->clearEntry) and
+ * the entry is marked so that JS_DHASH_ENTRY_IS_FREE(entry). This operation
+ * returns null unconditionally; you should ignore its return value.
+ */
+extern JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL
+JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op);
+
+/*
+ * Remove an entry already accessed via LOOKUP or ADD.
+ *
+ * NB: this is a "raw" or low-level routine, intended to be used only where
+ * the inefficiency of a full JS_DHashTableOperate (which rehashes in order
+ * to find the entry given its key) is not tolerable. This function does not
+ * shrink the table if it is underloaded. It does not update stats #ifdef
+ * JS_DHASHMETER, either.
+ */
+extern JS_PUBLIC_API(void)
+JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry);
+
+/*
+ * Enumerate entries in table using etor:
+ *
+ * count = JS_DHashTableEnumerate(table, etor, arg);
+ *
+ * JS_DHashTableEnumerate calls etor like so:
+ *
+ * op = etor(table, entry, number, arg);
+ *
+ * where number is a zero-based ordinal assigned to live entries according to
+ * their order in table->entryStore.
+ *
+ * The return value, op, is treated as a set of flags. If op is JS_DHASH_NEXT,
+ * then continue enumerating. If op contains JS_DHASH_REMOVE, then clear (via
+ * table->ops->clearEntry) and free entry. Then we check whether op contains
+ * JS_DHASH_STOP; if so, stop enumerating and return the number of live entries
+ * that were enumerated so far. Return the total number of live entries when
+ * enumeration completes normally.
+ *
+ * If etor calls JS_DHashTableOperate on table with op != JS_DHASH_LOOKUP, it
+ * must return JS_DHASH_STOP; otherwise undefined behavior results.
+ *
+ * If any enumerator returns JS_DHASH_REMOVE, table->entryStore may be shrunk
+ * or compressed after enumeration, but before JS_DHashTableEnumerate returns.
+ * Such an enumerator therefore can't safely set aside entry pointers, but an
+ * enumerator that never returns JS_DHASH_REMOVE can set pointers to entries
+ * aside, e.g., to avoid copying live entries into an array of the entry type.
+ * Copying entry pointers is cheaper, and safe so long as the caller of such a
+ * "stable" Enumerate doesn't use the set-aside pointers after any call either
+ * to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
+ * grow or shrink entryStore.
+ *
+ * If your enumerator wants to remove certain entries, but set aside pointers
+ * to other entries that it retains, it can use JS_DHashTableRawRemove on the
+ * entries to be removed, returning JS_DHASH_NEXT to skip them. Likewise, if
+ * you want to remove entries, but for some reason you do not want entryStore
+ * to be shrunk or compressed, you can call JS_DHashTableRawRemove safely on
+ * the entry being enumerated, rather than returning JS_DHASH_REMOVE.
+ */
+typedef JSDHashOperator
+(* JSDHashEnumerator)(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg);
+
+extern JS_PUBLIC_API(uint32)
+JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg);
+
+#ifdef JS_DHASHMETER
+#include <stdio.h>
+
+extern JS_PUBLIC_API(void)
+JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp);
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsdhash_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp
new file mode 100644
index 0000000..ca9176d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.cpp
@@ -0,0 +1,572 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Portable double to alphanumeric string and back converters.
+ */
+#include "jsstddef.h"
+#include "jslibmath.h"
+#include "jstypes.h"
+#include "jsdtoa.h"
+#include "jsprf.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jspubtd.h"
+#include "jsnum.h"
+#include "jsbit.h"
+
+#ifdef JS_THREADSAFE
+#include "jslock.h"
+#endif
+
+#ifdef IS_LITTLE_ENDIAN
+#define IEEE_8087
+#else
+#define IEEE_MC68k
+#endif
+
+#ifndef Long
+#define Long int32
+#endif
+
+#ifndef ULong
+#define ULong uint32
+#endif
+
+/*
+#ifndef Llong
+#define Llong JSInt64
+#endif
+
+#ifndef ULlong
+#define ULlong JSUint64
+#endif
+*/
+
+#ifdef JS_THREADSAFE
+static PRLock *dtoalock;
+static JSBool _dtoainited = JS_FALSE;
+
+#define LOCK_DTOA() PR_Lock(dtoalock);
+#define UNLOCK_DTOA() PR_Unlock(dtoalock)
+#else
+#define LOCK_DTOA()
+#define UNLOCK_DTOA()
+#endif
+#include "dtoa.c"
+
+JS_FRIEND_API(JSBool)
+js_InitDtoa()
+{
+#ifdef JS_THREADSAFE
+ if (!_dtoainited) {
+ dtoalock = PR_NewLock();
+ JS_ASSERT(dtoalock);
+ _dtoainited = JS_TRUE;
+ }
+
+ return (dtoalock != 0);
+#else
+ return JS_TRUE;
+#endif
+}
+
+JS_FRIEND_API(void)
+js_FinishDtoa()
+{
+#ifdef JS_THREADSAFE
+ if (_dtoainited) {
+ PR_DestroyLock(dtoalock);
+ dtoalock = NULL;
+ _dtoainited = JS_FALSE;
+ }
+#endif
+}
+
+/* Mapping of JSDToStrMode -> js_dtoa mode */
+static const uint8 dtoaModes[] = {
+ 0, /* DTOSTR_STANDARD */
+ 0, /* DTOSTR_STANDARD_EXPONENTIAL, */
+ 3, /* DTOSTR_FIXED, */
+ 2, /* DTOSTR_EXPONENTIAL, */
+ 2}; /* DTOSTR_PRECISION */
+
+JS_FRIEND_API(double)
+JS_strtod(const char *s00, char **se, int *err)
+{
+ double retval;
+ if (err)
+ *err = 0;
+ LOCK_DTOA();
+ retval = _strtod(s00, se);
+ UNLOCK_DTOA();
+ return retval;
+}
+
+JS_FRIEND_API(char *)
+JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dinput)
+{
+ U d;
+ int decPt; /* Offset of decimal point from first digit */
+ int sign; /* Nonzero if the sign bit was set in d */
+ int nDigits; /* Number of significand digits returned by js_dtoa */
+ char *numBegin; /* Pointer to the digits returned by js_dtoa */
+ char *numEnd = 0; /* Pointer past the digits returned by js_dtoa */
+
+ JS_ASSERT(bufferSize >= (size_t)(mode <= DTOSTR_STANDARD_EXPONENTIAL
+ ? DTOSTR_STANDARD_BUFFER_SIZE
+ : DTOSTR_VARIABLE_BUFFER_SIZE(precision)));
+
+ /*
+ * Change mode here rather than below because the buffer may not be large
+ * enough to hold a large integer.
+ */
+ if (mode == DTOSTR_FIXED && (dinput >= 1e21 || dinput <= -1e21))
+ mode = DTOSTR_STANDARD;
+
+ LOCK_DTOA();
+ dval(d) = dinput;
+ numBegin = dtoa(d, dtoaModes[mode], precision, &decPt, &sign, &numEnd);
+ if (!numBegin) {
+ UNLOCK_DTOA();
+ return NULL;
+ }
+
+ nDigits = numEnd - numBegin;
+ JS_ASSERT((size_t) nDigits <= bufferSize - 2);
+ if ((size_t) nDigits > bufferSize - 2) {
+ UNLOCK_DTOA();
+ return NULL;
+ }
+
+ memcpy(buffer + 2, numBegin, nDigits);
+ freedtoa(numBegin);
+ UNLOCK_DTOA();
+ numBegin = buffer + 2; /* +2 leaves space for sign and/or decimal point */
+ numEnd = numBegin + nDigits;
+ *numEnd = '\0';
+
+ /* If Infinity, -Infinity, or NaN, return the string regardless of mode. */
+ if (decPt != 9999) {
+ JSBool exponentialNotation = JS_FALSE;
+ int minNDigits = 0; /* Min number of significant digits required */
+ char *p;
+ char *q;
+
+ switch (mode) {
+ case DTOSTR_STANDARD:
+ if (decPt < -5 || decPt > 21)
+ exponentialNotation = JS_TRUE;
+ else
+ minNDigits = decPt;
+ break;
+
+ case DTOSTR_FIXED:
+ if (precision >= 0)
+ minNDigits = decPt + precision;
+ else
+ minNDigits = decPt;
+ break;
+
+ case DTOSTR_EXPONENTIAL:
+ JS_ASSERT(precision > 0);
+ minNDigits = precision;
+ /* Fall through */
+ case DTOSTR_STANDARD_EXPONENTIAL:
+ exponentialNotation = JS_TRUE;
+ break;
+
+ case DTOSTR_PRECISION:
+ JS_ASSERT(precision > 0);
+ minNDigits = precision;
+ if (decPt < -5 || decPt > precision)
+ exponentialNotation = JS_TRUE;
+ break;
+ }
+
+ /* If the number has fewer than minNDigits, end-pad it with zeros. */
+ if (nDigits < minNDigits) {
+ p = numBegin + minNDigits;
+ nDigits = minNDigits;
+ do {
+ *numEnd++ = '0';
+ } while (numEnd != p);
+ *numEnd = '\0';
+ }
+
+ if (exponentialNotation) {
+ /* Insert a decimal point if more than one significand digit */
+ if (nDigits != 1) {
+ numBegin--;
+ numBegin[0] = numBegin[1];
+ numBegin[1] = '.';
+ }
+ JS_snprintf(numEnd, bufferSize - (numEnd - buffer), "e%+d", decPt-1);
+ } else if (decPt != nDigits) {
+ /* Some kind of a fraction in fixed notation */
+ JS_ASSERT(decPt <= nDigits);
+ if (decPt > 0) {
+ /* dd...dd . dd...dd */
+ p = --numBegin;
+ do {
+ *p = p[1];
+ p++;
+ } while (--decPt);
+ *p = '.';
+ } else {
+ /* 0 . 00...00dd...dd */
+ p = numEnd;
+ numEnd += 1 - decPt;
+ q = numEnd;
+ JS_ASSERT(numEnd < buffer + bufferSize);
+ *numEnd = '\0';
+ while (p != numBegin)
+ *--q = *--p;
+ for (p = numBegin + 1; p != q; p++)
+ *p = '0';
+ *numBegin = '.';
+ *--numBegin = '0';
+ }
+ }
+ }
+
+ /* If negative and neither -0.0 nor NaN, output a leading '-'. */
+ if (sign &&
+ !(word0(d) == Sign_bit && word1(d) == 0) &&
+ !((word0(d) & Exp_mask) == Exp_mask &&
+ (word1(d) || (word0(d) & Frac_mask)))) {
+ *--numBegin = '-';
+ }
+ return numBegin;
+}
+
+
+/* Let b = floor(b / divisor), and return the remainder. b must be nonnegative.
+ * divisor must be between 1 and 65536.
+ * This function cannot run out of memory. */
+static uint32
+divrem(Bigint *b, uint32 divisor)
+{
+ int32 n = b->wds;
+ uint32 remainder = 0;
+ ULong *bx;
+ ULong *bp;
+
+ JS_ASSERT(divisor > 0 && divisor <= 65536);
+
+ if (!n)
+ return 0; /* b is zero */
+ bx = b->x;
+ bp = bx + n;
+ do {
+ ULong a = *--bp;
+ ULong dividend = remainder << 16 | a >> 16;
+ ULong quotientHi = dividend / divisor;
+ ULong quotientLo;
+
+ remainder = dividend - quotientHi*divisor;
+ JS_ASSERT(quotientHi <= 0xFFFF && remainder < divisor);
+ dividend = remainder << 16 | (a & 0xFFFF);
+ quotientLo = dividend / divisor;
+ remainder = dividend - quotientLo*divisor;
+ JS_ASSERT(quotientLo <= 0xFFFF && remainder < divisor);
+ *bp = quotientHi << 16 | quotientLo;
+ } while (bp != bx);
+ /* Decrease the size of the number if its most significant word is now zero. */
+ if (bx[n-1] == 0)
+ b->wds--;
+ return remainder;
+}
+
+/* Return floor(b/2^k) and set b to be the remainder. The returned quotient must be less than 2^32. */
+static uint32 quorem2(Bigint *b, int32 k)
+{
+ ULong mask;
+ ULong result;
+ ULong *bx, *bxe;
+ int32 w;
+ int32 n = k >> 5;
+ k &= 0x1F;
+ mask = (1<<k) - 1;
+
+ w = b->wds - n;
+ if (w <= 0)
+ return 0;
+ JS_ASSERT(w <= 2);
+ bx = b->x;
+ bxe = bx + n;
+ result = *bxe >> k;
+ *bxe &= mask;
+ if (w == 2) {
+ JS_ASSERT(!(bxe[1] & ~mask));
+ if (k)
+ result |= bxe[1] << (32 - k);
+ }
+ n++;
+ while (!*bxe && bxe != bx) {
+ n--;
+ bxe--;
+ }
+ b->wds = n;
+ return result;
+}
+
+
+/* "-0.0000...(1073 zeros after decimal point)...0001\0" is the longest string that we could produce,
+ * which occurs when printing -5e-324 in binary. We could compute a better estimate of the size of
+ * the output string and malloc fewer bytes depending on d and base, but why bother? */
+#define DTOBASESTR_BUFFER_SIZE 1078
+#define BASEDIGIT(digit) ((char)(((digit) >= 10) ? 'a' - 10 + (digit) : '0' + (digit)))
+
+JS_FRIEND_API(char *)
+JS_dtobasestr(int base, double dinput)
+{
+ U d;
+ char *buffer; /* The output string */
+ char *p; /* Pointer to current position in the buffer */
+ char *pInt; /* Pointer to the beginning of the integer part of the string */
+ char *q;
+ uint32 digit;
+ U di; /* d truncated to an integer */
+ U df; /* The fractional part of d */
+
+ JS_ASSERT(base >= 2 && base <= 36);
+
+ dval(d) = dinput;
+ buffer = (char*) malloc(DTOBASESTR_BUFFER_SIZE);
+ if (buffer) {
+ p = buffer;
+ if (dval(d) < 0.0
+#if defined(XP_WIN) || defined(XP_OS2)
+ && !((word0(d) & Exp_mask) == Exp_mask && ((word0(d) & Frac_mask) || word1(d))) /* Visual C++ doesn't know how to compare against NaN */
+#endif
+ ) {
+ *p++ = '-';
+ dval(d) = -dval(d);
+ }
+
+ /* Check for Infinity and NaN */
+ if ((word0(d) & Exp_mask) == Exp_mask) {
+ strcpy(p, !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN");
+ return buffer;
+ }
+
+ LOCK_DTOA();
+ /* Output the integer part of d with the digits in reverse order. */
+ pInt = p;
+ dval(di) = floor(dval(d));
+ if (dval(di) <= 4294967295.0) {
+ uint32 n = (uint32)dval(di);
+ if (n)
+ do {
+ uint32 m = n / base;
+ digit = n - m*base;
+ n = m;
+ JS_ASSERT(digit < (uint32)base);
+ *p++ = BASEDIGIT(digit);
+ } while (n);
+ else *p++ = '0';
+ } else {
+ int e;
+ int bits; /* Number of significant bits in di; not used. */
+ Bigint *b = d2b(di, &e, &bits);
+ if (!b)
+ goto nomem1;
+ b = lshift(b, e);
+ if (!b) {
+ nomem1:
+ Bfree(b);
+ UNLOCK_DTOA();
+ free(buffer);
+ return NULL;
+ }
+ do {
+ digit = divrem(b, base);
+ JS_ASSERT(digit < (uint32)base);
+ *p++ = BASEDIGIT(digit);
+ } while (b->wds);
+ Bfree(b);
+ }
+ /* Reverse the digits of the integer part of d. */
+ q = p-1;
+ while (q > pInt) {
+ char ch = *pInt;
+ *pInt++ = *q;
+ *q-- = ch;
+ }
+
+ dval(df) = dval(d) - dval(di);
+ if (dval(df) != 0.0) {
+ /* We have a fraction. */
+ int e, bbits;
+ int32 s2, done;
+ Bigint *b, *s, *mlo, *mhi;
+
+ b = s = mlo = mhi = NULL;
+
+ *p++ = '.';
+ b = d2b(df, &e, &bbits);
+ if (!b) {
+ nomem2:
+ Bfree(b);
+ Bfree(s);
+ if (mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ UNLOCK_DTOA();
+ free(buffer);
+ return NULL;
+ }
+ JS_ASSERT(e < 0);
+ /* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
+
+ s2 = -(int32)(word0(d) >> Exp_shift1 & Exp_mask>>Exp_shift1);
+#ifndef Sudden_Underflow
+ if (!s2)
+ s2 = -1;
+#endif
+ s2 += Bias + P;
+ /* 1/2^s2 = (nextDouble(d) - d)/2 */
+ JS_ASSERT(-s2 < e);
+ mlo = i2b(1);
+ if (!mlo)
+ goto nomem2;
+ mhi = mlo;
+ if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+ && word0(d) & (Exp_mask & Exp_mask << 1)
+#endif
+ ) {
+ /* The special case. Here we want to be within a quarter of the last input
+ significant digit instead of one half of it when the output string's value is less than d. */
+ s2 += Log2P;
+ mhi = i2b(1<<Log2P);
+ if (!mhi)
+ goto nomem2;
+ }
+ b = lshift(b, e + s2);
+ if (!b)
+ goto nomem2;
+ s = i2b(1);
+ if (!s)
+ goto nomem2;
+ s = lshift(s, s2);
+ if (!s)
+ goto nomem2;
+ /* At this point we have the following:
+ * s = 2^s2;
+ * 1 > df = b/2^s2 > 0;
+ * (d - prevDouble(d))/2 = mlo/2^s2;
+ * (nextDouble(d) - d)/2 = mhi/2^s2. */
+
+ done = JS_FALSE;
+ do {
+ int32 j, j1;
+ Bigint *delta;
+
+ b = multadd(b, base, 0);
+ if (!b)
+ goto nomem2;
+ digit = quorem2(b, s2);
+ if (mlo == mhi) {
+ mlo = mhi = multadd(mlo, base, 0);
+ if (!mhi)
+ goto nomem2;
+ }
+ else {
+ mlo = multadd(mlo, base, 0);
+ if (!mlo)
+ goto nomem2;
+ mhi = multadd(mhi, base, 0);
+ if (!mhi)
+ goto nomem2;
+ }
+
+ /* Do we yet have the shortest string that will round to d? */
+ j = cmp(b, mlo);
+ /* j is b/2^s2 compared with mlo/2^s2. */
+ delta = diff(s, mhi);
+ if (!delta)
+ goto nomem2;
+ j1 = delta->sign ? 1 : cmp(b, delta);
+ Bfree(delta);
+ /* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
+
+#ifndef ROUND_BIASED
+ if (j1 == 0 && !(word1(d) & 1)) {
+ if (j > 0)
+ digit++;
+ done = JS_TRUE;
+ } else
+#endif
+ if (j < 0 || (j == 0
+#ifndef ROUND_BIASED
+ && !(word1(d) & 1)
+#endif
+ )) {
+ if (j1 > 0) {
+ /* Either dig or dig+1 would work here as the least significant digit.
+ Use whichever would produce an output value closer to d. */
+ b = lshift(b, 1);
+ if (!b)
+ goto nomem2;
+ j1 = cmp(b, s);
+ if (j1 > 0) /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output
+ * such as 3.5 in base 3. */
+ digit++;
+ }
+ done = JS_TRUE;
+ } else if (j1 > 0) {
+ digit++;
+ done = JS_TRUE;
+ }
+ JS_ASSERT(digit < (uint32)base);
+ *p++ = BASEDIGIT(digit);
+ } while (!done);
+ Bfree(b);
+ Bfree(s);
+ if (mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ JS_ASSERT(p < buffer + DTOBASESTR_BUFFER_SIZE);
+ *p = '\0';
+ UNLOCK_DTOA();
+ }
+ return buffer;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h
new file mode 100644
index 0000000..b074c9a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtoa.h
@@ -0,0 +1,131 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsdtoa_h___
+#define jsdtoa_h___
+/*
+ * Public interface to portable double-precision floating point to string
+ * and back conversion package.
+ */
+
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * JS_strtod() returns as a double-precision floating-point number
+ * the value represented by the character string pointed to by
+ * s00. The string is scanned up to the first unrecognized
+ * character.
+ * If the value of se is not (char **)NULL, a pointer to
+ * the character terminating the scan is returned in the location pointed
+ * to by se. If no number can be formed, se is set to s00r, and
+ * zero is returned.
+ *
+ * *err is set to zero on success; it's set to JS_DTOA_ERANGE on range
+ * errors and JS_DTOA_ENOMEM on memory failure.
+ */
+#define JS_DTOA_ERANGE 1
+#define JS_DTOA_ENOMEM 2
+JS_FRIEND_API(double)
+JS_strtod(const char *s00, char **se, int *err);
+
+/*
+ * Modes for converting floating-point numbers to strings.
+ *
+ * Some of the modes can round-trip; this means that if the number is converted to
+ * a string using one of these mode and then converted back to a number, the result
+ * will be identical to the original number (except that, due to ECMA, -0 will get converted
+ * to +0). These round-trip modes return the minimum number of significand digits that
+ * permit the round trip.
+ *
+ * Some of the modes take an integer parameter <precision>.
+ */
+/* NB: Keep this in sync with number_constants[]. */
+typedef enum JSDToStrMode {
+ DTOSTR_STANDARD, /* Either fixed or exponential format; round-trip */
+ DTOSTR_STANDARD_EXPONENTIAL, /* Always exponential format; round-trip */
+ DTOSTR_FIXED, /* Round to <precision> digits after the decimal point; exponential if number is large */
+ DTOSTR_EXPONENTIAL, /* Always exponential format; <precision> significant digits */
+ DTOSTR_PRECISION /* Either fixed or exponential format; <precision> significant digits */
+} JSDToStrMode;
+
+
+/* Maximum number of characters (including trailing null) that a DTOSTR_STANDARD or DTOSTR_STANDARD_EXPONENTIAL
+ * conversion can produce. This maximum is reached for a number like -0.0000012345678901234567. */
+#define DTOSTR_STANDARD_BUFFER_SIZE 26
+
+/* Maximum number of characters (including trailing null) that one of the other conversions
+ * can produce. This maximum is reached for TO_FIXED, which can generate up to 21 digits before the decimal point. */
+#define DTOSTR_VARIABLE_BUFFER_SIZE(precision) ((precision)+24 > DTOSTR_STANDARD_BUFFER_SIZE ? (precision)+24 : DTOSTR_STANDARD_BUFFER_SIZE)
+
+/*
+ * Convert dval according to the given mode and return a pointer to the resulting ASCII string.
+ * The result is held somewhere in buffer, but not necessarily at the beginning. The size of
+ * buffer is given in bufferSize, and must be at least as large as given by the above macros.
+ *
+ * Return NULL if out of memory.
+ */
+JS_FRIEND_API(char *)
+JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dval);
+
+/*
+ * Convert d to a string in the given base. The integral part of d will be printed exactly
+ * in that base, regardless of how large it is, because there is no exponential notation for non-base-ten
+ * numbers. The fractional part will be rounded to as few digits as possible while still preserving
+ * the round-trip property (analogous to that of printing decimal numbers). In other words, if one were
+ * to read the resulting string in via a hypothetical base-number-reading routine that rounds to the nearest
+ * IEEE double (and to an even significand if there are two equally near doubles), then the result would
+ * equal d (except for -0.0, which converts to "0", and NaN, which is not equal to itself).
+ *
+ * Return NULL if out of memory. If the result is not NULL, it must be released via free().
+ */
+JS_FRIEND_API(char *)
+JS_dtobasestr(int base, double d);
+
+/*
+ * Clean up any persistent RAM allocated during the execution of DtoA
+ * routines, and remove any locks that might have been created.
+ */
+JS_FRIEND_API(JSBool) js_InitDtoa(void);
+JS_FRIEND_API(void) js_FinishDtoa(void);
+
+JS_END_EXTERN_C
+
+#endif /* jsdtoa_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c
new file mode 100644
index 0000000..8d95b39
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.c
@@ -0,0 +1,318 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsapi.h"
+#include "jsutil.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsobj.h"
+#include "jsscript.h"
+#include "jsstr.h"
+
+#include "jsdtracef.h"
+#include <sys/types.h>
+
+#define TYPEOF(cx,v) (JSVAL_IS_NULL(v) ? JSTYPE_NULL : JS_TypeOfValue(cx,v))
+
+static char dempty[] = "<null>";
+
+char *
+jsdtrace_funcclass_name(JSFunction *fun)
+{
+ return (!FUN_INTERPRETED(fun) &&
+ !(fun->flags & JSFUN_TRACEABLE) &&
+ FUN_CLASP(fun))
+ ? (char *)FUN_CLASP(fun)->name
+ : dempty;
+}
+
+char *
+jsdtrace_filename(JSStackFrame *fp)
+{
+ while (fp && fp->script == NULL)
+ fp = fp->down;
+ return (fp && fp->script && fp->script->filename)
+ ? (char *)fp->script->filename
+ : dempty;
+}
+
+int
+jsdtrace_linenumber(JSContext *cx, JSStackFrame *fp)
+{
+ while (fp && fp->script == NULL)
+ fp = fp->down;
+ return (fp && fp->regs)
+ ? (int) js_PCToLineNumber(cx, fp->script, fp->regs->pc)
+ : -1;
+}
+
+/*
+ * This function is used to convert function arguments and return value (jsval)
+ * into the following based on each value's type tag:
+ *
+ * jsval returned
+ * -------------------
+ * STRING -> char *
+ * INT -> int
+ * DOUBLE -> double *
+ * BOOLEAN -> int
+ * OBJECT -> void *
+ *
+ * All are presented as void * for DTrace consumers to use, after shifting or
+ * masking out the JavaScript type bits. This allows D scripts to use ints and
+ * booleans directly and copyinstr() for string arguments, when types are known
+ * beforehand.
+ *
+ * This is used by the function-args and function-rval probes, which also
+ * provide raw (unmasked) jsvals should type info be useful from D scripts.
+ */
+void *
+jsdtrace_jsvaltovoid(JSContext *cx, jsval argval)
+{
+ JSType type = TYPEOF(cx, argval);
+
+ switch (type) {
+ case JSTYPE_NULL:
+ case JSTYPE_VOID:
+ return (void *)JS_TYPE_STR(type);
+
+ case JSTYPE_BOOLEAN:
+ return (void *)JSVAL_TO_BOOLEAN(argval);
+
+ case JSTYPE_STRING:
+ return (void *)js_GetStringBytes(cx, JSVAL_TO_STRING(argval));
+
+ case JSTYPE_NUMBER:
+ if (JSVAL_IS_INT(argval))
+ return (void *)JSVAL_TO_INT(argval);
+ return JSVAL_TO_DOUBLE(argval);
+
+ default:
+ return JSVAL_TO_GCTHING(argval);
+ }
+ /* NOTREACHED */
+}
+
+char *
+jsdtrace_function_name(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JSAtom *atom;
+ JSFrameRegs *regs;
+ JSScript *script;
+ jsbytecode *pc;
+ char *name;
+
+ atom = fun->atom;
+ if (!atom) {
+ if (fp->fun != fun || !fp->down)
+ return dempty;
+
+ regs = fp->down->regs;
+ if (!regs)
+ return dempty;
+
+ /*
+ * An anonymous function called from an active script or interpreted
+ * function: try to fetch the variable or property name by which the
+ * anonymous function was invoked.
+ */
+ pc = regs->pc;
+ script = fp->down->script;
+ switch ((JSOp) *pc) {
+ case JSOP_CALL:
+ case JSOP_EVAL:
+ JS_ASSERT(fp->argv == regs->sp - (int)GET_ARGC(pc));
+
+ /*
+ * FIXME bug 422864: update this code to use the pc stack from the
+ * decompiler.
+ */
+ break;
+ default: ;
+ }
+
+ switch ((JSOp) *pc) {
+ case JSOP_CALLNAME:
+ case JSOP_CALLPROP:
+ case JSOP_NAME:
+ case JSOP_SETNAME:
+ case JSOP_GETPROP:
+ case JSOP_SETPROP:
+ GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
+ break;
+
+ case JSOP_CALLELEM:
+ case JSOP_GETELEM:
+ case JSOP_SETELEM:
+ case JSOP_CALLGVAR:
+ case JSOP_GETGVAR:
+ case JSOP_SETGVAR:
+ case JSOP_CALLARG:
+ case JSOP_CALLLOCAL:
+ /* FIXME: try to recover a name from these ops. */
+ /* FALL THROUGH */
+
+ default:
+ return dempty;
+ }
+ }
+
+ name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom));
+ return name ? name : dempty;
+}
+
+/*
+ * These functions call the DTrace macros for the JavaScript USDT probes.
+ * Originally this code was inlined in the JavaScript code; however since
+ * a number of operations are called, these have been placed into functions
+ * to reduce any negative compiler optimization effect that the addition of
+ * a number of usually unused lines of code would cause.
+ */
+void
+jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_ENTRY(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun)
+ );
+}
+
+void
+jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
+ JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_INFO(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun),
+ fp->script->lineno,
+ jsdtrace_filename(dfp),
+ jsdtrace_linenumber(cx, dfp)
+ );
+}
+
+void
+jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_ARGS(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun),
+ fp->argc, (void *)fp->argv,
+ (fp->argc > 0) ? jsdtrace_jsvaltovoid(cx, fp->argv[0]) : 0,
+ (fp->argc > 1) ? jsdtrace_jsvaltovoid(cx, fp->argv[1]) : 0,
+ (fp->argc > 2) ? jsdtrace_jsvaltovoid(cx, fp->argv[2]) : 0,
+ (fp->argc > 3) ? jsdtrace_jsvaltovoid(cx, fp->argv[3]) : 0,
+ (fp->argc > 4) ? jsdtrace_jsvaltovoid(cx, fp->argv[4]) : 0
+ );
+}
+
+void
+jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_RVAL(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun),
+ jsdtrace_linenumber(cx, fp), (void *)fp->rval,
+ jsdtrace_jsvaltovoid(cx, fp->rval)
+ );
+}
+
+void
+jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
+{
+ JAVASCRIPT_FUNCTION_RETURN(
+ jsdtrace_filename(fp),
+ jsdtrace_funcclass_name(fun),
+ jsdtrace_function_name(cx, fp, fun)
+ );
+}
+
+void
+jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp)
+{
+ JAVASCRIPT_OBJECT_CREATE_START(jsdtrace_filename(fp), (char *)clasp->name);
+}
+
+void
+jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp)
+{
+ JAVASCRIPT_OBJECT_CREATE_DONE(jsdtrace_filename(fp), (char *)clasp->name);
+}
+
+void
+jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj)
+{
+ JAVASCRIPT_OBJECT_CREATE(
+ jsdtrace_filename(cx->fp),
+ (char *)clasp->name,
+ (uintptr_t)obj,
+ jsdtrace_linenumber(cx, cx->fp)
+ );
+}
+
+void
+jsdtrace_object_finalize(JSObject *obj)
+{
+ JSClass *clasp;
+
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+
+ /* the first arg is NULL - reserved for future use (filename?) */
+ JAVASCRIPT_OBJECT_FINALIZE(NULL, (char *)clasp->name, (uintptr_t)obj);
+}
+
+void
+jsdtrace_execute_start(JSScript *script)
+{
+ JAVASCRIPT_EXECUTE_START(
+ script->filename ? (char *)script->filename : dempty,
+ script->lineno
+ );
+}
+
+void
+jsdtrace_execute_done(JSScript *script)
+{
+ JAVASCRIPT_EXECUTE_DONE(
+ script->filename ? (char *)script->filename : dempty,
+ script->lineno
+ );
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h
new file mode 100644
index 0000000..08f3098
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsdtracef.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Copyright (C) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "javascript-trace.h"
+#include "jspubtd.h"
+#include "jsprvtd.h"
+
+#ifndef _JSDTRACEF_H
+#define _JSDTRACEF_H
+
+JS_BEGIN_EXTERN_C
+
+extern void
+jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
+ JSFunction *fun);
+
+extern void
+jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
+
+extern void
+jsdtrace_object_create_start(JSStackFrame *fp, JSClass *clasp);
+
+extern void
+jsdtrace_object_create_done(JSStackFrame *fp, JSClass *clasp);
+
+extern void
+jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj);
+
+extern void
+jsdtrace_object_finalize(JSObject *obj);
+
+extern void
+jsdtrace_execute_start(JSScript *script);
+
+extern void
+jsdtrace_execute_done(JSScript *script);
+
+JS_END_EXTERN_C
+
+#endif /* _JSDTRACE_H */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp
new file mode 100644
index 0000000..3d2269b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.cpp
@@ -0,0 +1,6857 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS bytecode generation.
+ */
+#include "jsstddef.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsbit.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsnum.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsautooplen.h"
+#include "jsstaticcheck.h"
+
+/* Allocation chunk counts, must be powers of two in general. */
+#define BYTECODE_CHUNK 256 /* code allocation increment */
+#define SRCNOTE_CHUNK 64 /* initial srcnote allocation increment */
+#define TRYNOTE_CHUNK 64 /* trynote allocation increment */
+
+/* Macros to compute byte sizes from typed element counts. */
+#define BYTECODE_SIZE(n) ((n) * sizeof(jsbytecode))
+#define SRCNOTE_SIZE(n) ((n) * sizeof(jssrcnote))
+#define TRYNOTE_SIZE(n) ((n) * sizeof(JSTryNote))
+
+static JSBool
+NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
+ uintN stackDepth, size_t start, size_t end);
+
+JS_FRIEND_API(void)
+js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,
+ JSArenaPool *codePool, JSArenaPool *notePool,
+ uintN lineno)
+{
+ memset(cg, 0, sizeof *cg);
+ TREE_CONTEXT_INIT(&cg->treeContext, pc);
+ cg->codePool = codePool;
+ cg->notePool = notePool;
+ cg->codeMark = JS_ARENA_MARK(codePool);
+ cg->noteMark = JS_ARENA_MARK(notePool);
+ cg->current = &cg->main;
+ cg->firstLine = cg->prolog.currentLine = cg->main.currentLine = lineno;
+ ATOM_LIST_INIT(&cg->atomList);
+ cg->prolog.noteMask = cg->main.noteMask = SRCNOTE_CHUNK - 1;
+ ATOM_LIST_INIT(&cg->constList);
+ ATOM_LIST_INIT(&cg->upvarList);
+}
+
+JS_FRIEND_API(void)
+js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg)
+{
+ TREE_CONTEXT_FINISH(cx, &cg->treeContext);
+ JS_ARENA_RELEASE(cg->codePool, cg->codeMark);
+ JS_ARENA_RELEASE(cg->notePool, cg->noteMark);
+
+ /* NB: non-null only after OOM. */
+ if (cg->spanDeps)
+ JS_free(cx, cg->spanDeps);
+
+ if (cg->upvarMap.vector)
+ JS_free(cx, cg->upvarMap.vector);
+}
+
+static ptrdiff_t
+EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta)
+{
+ jsbytecode *base, *limit, *next;
+ ptrdiff_t offset, length;
+ size_t incr, size;
+
+ base = CG_BASE(cg);
+ next = CG_NEXT(cg);
+ limit = CG_LIMIT(cg);
+ offset = PTRDIFF(next, base, jsbytecode);
+ if (next + delta > limit) {
+ length = offset + delta;
+ length = (length <= BYTECODE_CHUNK)
+ ? BYTECODE_CHUNK
+ : JS_BIT(JS_CeilingLog2(length));
+ incr = BYTECODE_SIZE(length);
+ if (!base) {
+ JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr);
+ } else {
+ size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode));
+ incr -= size;
+ JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
+ }
+ if (!base) {
+ js_ReportOutOfScriptQuota(cx);
+ return -1;
+ }
+ CG_BASE(cg) = base;
+ CG_LIMIT(cg) = base + length;
+ CG_NEXT(cg) = base + offset;
+ }
+ return offset;
+}
+
+static void
+UpdateDepth(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t target)
+{
+ jsbytecode *pc;
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN depth;
+ intN nuses, ndefs;
+
+ pc = CG_CODE(cg, target);
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ if (cs->format & JOF_TMPSLOT_MASK) {
+ depth = (uintN) cg->stackDepth +
+ ((cs->format & JOF_TMPSLOT_MASK) >> JOF_TMPSLOT_SHIFT);
+ if (depth > cg->maxStackDepth)
+ cg->maxStackDepth = depth;
+ }
+ nuses = cs->nuses;
+ if (nuses < 0)
+ nuses = js_GetVariableStackUseLength(op, pc);
+ cg->stackDepth -= nuses;
+ JS_ASSERT(cg->stackDepth >= 0);
+ if (cg->stackDepth < 0) {
+ char numBuf[12];
+ JSTokenStream *ts;
+
+ JS_snprintf(numBuf, sizeof numBuf, "%d", target);
+ ts = &cg->treeContext.parseContext->tokenStream;
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING,
+ js_GetErrorMessage, NULL,
+ JSMSG_STACK_UNDERFLOW,
+ ts->filename ? ts->filename : "stdin",
+ numBuf);
+ }
+ ndefs = cs->ndefs;
+ if (ndefs < 0) {
+ JSObject *blockObj;
+
+ /* We just executed IndexParsedObject */
+ JS_ASSERT(op == JSOP_ENTERBLOCK);
+ JS_ASSERT(nuses == 0);
+ blockObj = cg->objectList.lastPob->object;
+ JS_ASSERT(STOBJ_GET_CLASS(blockObj) == &js_BlockClass);
+ JS_ASSERT(JSVAL_IS_VOID(blockObj->fslots[JSSLOT_BLOCK_DEPTH]));
+
+ OBJ_SET_BLOCK_DEPTH(cx, blockObj, cg->stackDepth);
+ ndefs = OBJ_BLOCK_COUNT(cx, blockObj);
+ }
+ cg->stackDepth += ndefs;
+ if ((uintN)cg->stackDepth > cg->maxStackDepth)
+ cg->maxStackDepth = cg->stackDepth;
+}
+
+ptrdiff_t
+js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op)
+{
+ ptrdiff_t offset = EmitCheck(cx, cg, op, 1);
+
+ if (offset >= 0) {
+ *CG_NEXT(cg)++ = (jsbytecode)op;
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+ptrdiff_t
+js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1)
+{
+ ptrdiff_t offset = EmitCheck(cx, cg, op, 2);
+
+ if (offset >= 0) {
+ jsbytecode *next = CG_NEXT(cg);
+ next[0] = (jsbytecode)op;
+ next[1] = op1;
+ CG_NEXT(cg) = next + 2;
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+ptrdiff_t
+js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
+ jsbytecode op2)
+{
+ ptrdiff_t offset = EmitCheck(cx, cg, op, 3);
+
+ if (offset >= 0) {
+ jsbytecode *next = CG_NEXT(cg);
+ next[0] = (jsbytecode)op;
+ next[1] = op1;
+ next[2] = op2;
+ CG_NEXT(cg) = next + 3;
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+ptrdiff_t
+js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra)
+{
+ ptrdiff_t length = 1 + (ptrdiff_t)extra;
+ ptrdiff_t offset = EmitCheck(cx, cg, op, length);
+
+ if (offset >= 0) {
+ jsbytecode *next = CG_NEXT(cg);
+ *next = (jsbytecode)op;
+ memset(next + 1, 0, BYTECODE_SIZE(extra));
+ CG_NEXT(cg) = next + length;
+
+ /*
+ * Don't UpdateDepth if op's use-count comes from the immediate
+ * operand yet to be stored in the extra bytes after op.
+ */
+ if (js_CodeSpec[op].nuses >= 0)
+ UpdateDepth(cx, cg, offset);
+ }
+ return offset;
+}
+
+/* XXX too many "... statement" L10N gaffes below -- fix via js.msg! */
+const char js_with_statement_str[] = "with statement";
+const char js_finally_block_str[] = "finally block";
+const char js_script_str[] = "script";
+
+static const char *statementName[] = {
+ "label statement", /* LABEL */
+ "if statement", /* IF */
+ "else statement", /* ELSE */
+ "destructuring body", /* BODY */
+ "switch statement", /* SWITCH */
+ "block", /* BLOCK */
+ js_with_statement_str, /* WITH */
+ "catch block", /* CATCH */
+ "try block", /* TRY */
+ js_finally_block_str, /* FINALLY */
+ js_finally_block_str, /* SUBROUTINE */
+ "do loop", /* DO_LOOP */
+ "for loop", /* FOR_LOOP */
+ "for/in loop", /* FOR_IN_LOOP */
+ "while loop", /* WHILE_LOOP */
+};
+
+JS_STATIC_ASSERT(JS_ARRAY_LENGTH(statementName) == STMT_LIMIT);
+
+static const char *
+StatementName(JSCodeGenerator *cg)
+{
+ if (!cg->treeContext.topStmt)
+ return js_script_str;
+ return statementName[cg->treeContext.topStmt->type];
+}
+
+static void
+ReportStatementTooLarge(JSContext *cx, JSCodeGenerator *cg)
+{
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEED_DIET,
+ StatementName(cg));
+}
+
+/**
+ Span-dependent instructions in JS bytecode consist of the jump (JOF_JUMP)
+ and switch (JOF_LOOKUPSWITCH, JOF_TABLESWITCH) format opcodes, subdivided
+ into unconditional (gotos and gosubs), and conditional jumps or branches
+ (which pop a value, test it, and jump depending on its value). Most jumps
+ have just one immediate operand, a signed offset from the jump opcode's pc
+ to the target bytecode. The lookup and table switch opcodes may contain
+ many jump offsets.
+
+ Mozilla bug #80981 (http://bugzilla.mozilla.org/show_bug.cgi?id=80981) was
+ fixed by adding extended "X" counterparts to the opcodes/formats (NB: X is
+ suffixed to prefer JSOP_ORX thereby avoiding a JSOP_XOR name collision for
+ the extended form of the JSOP_OR branch opcode). The unextended or short
+ formats have 16-bit signed immediate offset operands, the extended or long
+ formats have 32-bit signed immediates. The span-dependency problem consists
+ of selecting as few long instructions as possible, or about as few -- since
+ jumps can span other jumps, extending one jump may cause another to need to
+ be extended.
+
+ Most JS scripts are short, so need no extended jumps. We optimize for this
+ case by generating short jumps until we know a long jump is needed. After
+ that point, we keep generating short jumps, but each jump's 16-bit immediate
+ offset operand is actually an unsigned index into cg->spanDeps, an array of
+ JSSpanDep structs. Each struct tells the top offset in the script of the
+ opcode, the "before" offset of the jump (which will be the same as top for
+ simplex jumps, but which will index further into the bytecode array for a
+ non-initial jump offset in a lookup or table switch), the after "offset"
+ adjusted during span-dependent instruction selection (initially the same
+ value as the "before" offset), and the jump target (more below).
+
+ Since we generate cg->spanDeps lazily, from within js_SetJumpOffset, we must
+ ensure that all bytecode generated so far can be inspected to discover where
+ the jump offset immediate operands lie within CG_CODE(cg). But the bonus is
+ that we generate span-dependency records sorted by their offsets, so we can
+ binary-search when trying to find a JSSpanDep for a given bytecode offset,
+ or the nearest JSSpanDep at or above a given pc.
+
+ To avoid limiting scripts to 64K jumps, if the cg->spanDeps index overflows
+ 65534, we store SPANDEP_INDEX_HUGE in the jump's immediate operand. This
+ tells us that we need to binary-search for the cg->spanDeps entry by the
+ jump opcode's bytecode offset (sd->before).
+
+ Jump targets need to be maintained in a data structure that lets us look
+ up an already-known target by its address (jumps may have a common target),
+ and that also lets us update the addresses (script-relative, a.k.a. absolute
+ offsets) of targets that come after a jump target (for when a jump below
+ that target needs to be extended). We use an AVL tree, implemented using
+ recursion, but with some tricky optimizations to its height-balancing code
+ (see http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html).
+
+ A final wrinkle: backpatch chains are linked by jump-to-jump offsets with
+ positive sign, even though they link "backward" (i.e., toward lower bytecode
+ address). We don't want to waste space and search time in the AVL tree for
+ such temporary backpatch deltas, so we use a single-bit wildcard scheme to
+ tag true JSJumpTarget pointers and encode untagged, signed (positive) deltas
+ in JSSpanDep.target pointers, depending on whether the JSSpanDep has a known
+ target, or is still awaiting backpatching.
+
+ Note that backpatch chains would present a problem for BuildSpanDepTable,
+ which inspects bytecode to build cg->spanDeps on demand, when the first
+ short jump offset overflows. To solve this temporary problem, we emit a
+ proxy bytecode (JSOP_BACKPATCH; JSOP_BACKPATCH_POP for branch ops) whose
+ nuses/ndefs counts help keep the stack balanced, but whose opcode format
+ distinguishes its backpatch delta immediate operand from a normal jump
+ offset.
+ */
+static int
+BalanceJumpTargets(JSJumpTarget **jtp)
+{
+ JSJumpTarget *jt, *jt2, *root;
+ int dir, otherDir, heightChanged;
+ JSBool doubleRotate;
+
+ jt = *jtp;
+ JS_ASSERT(jt->balance != 0);
+
+ if (jt->balance < -1) {
+ dir = JT_RIGHT;
+ doubleRotate = (jt->kids[JT_LEFT]->balance > 0);
+ } else if (jt->balance > 1) {
+ dir = JT_LEFT;
+ doubleRotate = (jt->kids[JT_RIGHT]->balance < 0);
+ } else {
+ return 0;
+ }
+
+ otherDir = JT_OTHER_DIR(dir);
+ if (doubleRotate) {
+ jt2 = jt->kids[otherDir];
+ *jtp = root = jt2->kids[dir];
+
+ jt->kids[otherDir] = root->kids[dir];
+ root->kids[dir] = jt;
+
+ jt2->kids[dir] = root->kids[otherDir];
+ root->kids[otherDir] = jt2;
+
+ heightChanged = 1;
+ root->kids[JT_LEFT]->balance = -JS_MAX(root->balance, 0);
+ root->kids[JT_RIGHT]->balance = -JS_MIN(root->balance, 0);
+ root->balance = 0;
+ } else {
+ *jtp = root = jt->kids[otherDir];
+ jt->kids[otherDir] = root->kids[dir];
+ root->kids[dir] = jt;
+
+ heightChanged = (root->balance != 0);
+ jt->balance = -((dir == JT_LEFT) ? --root->balance : ++root->balance);
+ }
+
+ return heightChanged;
+}
+
+typedef struct AddJumpTargetArgs {
+ JSContext *cx;
+ JSCodeGenerator *cg;
+ ptrdiff_t offset;
+ JSJumpTarget *node;
+} AddJumpTargetArgs;
+
+static int
+AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp)
+{
+ JSJumpTarget *jt;
+ int balanceDelta;
+
+ jt = *jtp;
+ if (!jt) {
+ JSCodeGenerator *cg = args->cg;
+
+ jt = cg->jtFreeList;
+ if (jt) {
+ cg->jtFreeList = jt->kids[JT_LEFT];
+ } else {
+ JS_ARENA_ALLOCATE_CAST(jt, JSJumpTarget *, &args->cx->tempPool,
+ sizeof *jt);
+ if (!jt) {
+ js_ReportOutOfScriptQuota(args->cx);
+ return 0;
+ }
+ }
+ jt->offset = args->offset;
+ jt->balance = 0;
+ jt->kids[JT_LEFT] = jt->kids[JT_RIGHT] = NULL;
+ cg->numJumpTargets++;
+ args->node = jt;
+ *jtp = jt;
+ return 1;
+ }
+
+ if (jt->offset == args->offset) {
+ args->node = jt;
+ return 0;
+ }
+
+ if (args->offset < jt->offset)
+ balanceDelta = -AddJumpTarget(args, &jt->kids[JT_LEFT]);
+ else
+ balanceDelta = AddJumpTarget(args, &jt->kids[JT_RIGHT]);
+ if (!args->node)
+ return 0;
+
+ jt->balance += balanceDelta;
+ return (balanceDelta && jt->balance)
+ ? 1 - BalanceJumpTargets(jtp)
+ : 0;
+}
+
+#ifdef DEBUG_brendan
+static int AVLCheck(JSJumpTarget *jt)
+{
+ int lh, rh;
+
+ if (!jt) return 0;
+ JS_ASSERT(-1 <= jt->balance && jt->balance <= 1);
+ lh = AVLCheck(jt->kids[JT_LEFT]);
+ rh = AVLCheck(jt->kids[JT_RIGHT]);
+ JS_ASSERT(jt->balance == rh - lh);
+ return 1 + JS_MAX(lh, rh);
+}
+#endif
+
+static JSBool
+SetSpanDepTarget(JSContext *cx, JSCodeGenerator *cg, JSSpanDep *sd,
+ ptrdiff_t off)
+{
+ AddJumpTargetArgs args;
+
+ if (off < JUMPX_OFFSET_MIN || JUMPX_OFFSET_MAX < off) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ args.cx = cx;
+ args.cg = cg;
+ args.offset = sd->top + off;
+ args.node = NULL;
+ AddJumpTarget(&args, &cg->jumpTargets);
+ if (!args.node)
+ return JS_FALSE;
+
+#ifdef DEBUG_brendan
+ AVLCheck(cg->jumpTargets);
+#endif
+
+ SD_SET_TARGET(sd, args.node);
+ return JS_TRUE;
+}
+
+#define SPANDEPS_MIN 256
+#define SPANDEPS_SIZE(n) ((n) * sizeof(JSSpanDep))
+#define SPANDEPS_SIZE_MIN SPANDEPS_SIZE(SPANDEPS_MIN)
+
+static JSBool
+AddSpanDep(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, jsbytecode *pc2,
+ ptrdiff_t off)
+{
+ uintN index;
+ JSSpanDep *sdbase, *sd;
+ size_t size;
+
+ index = cg->numSpanDeps;
+ if (index + 1 == 0) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ if ((index & (index - 1)) == 0 &&
+ (!(sdbase = cg->spanDeps) || index >= SPANDEPS_MIN)) {
+ size = sdbase ? SPANDEPS_SIZE(index) : SPANDEPS_SIZE_MIN / 2;
+ sdbase = (JSSpanDep *) JS_realloc(cx, sdbase, size + size);
+ if (!sdbase)
+ return JS_FALSE;
+ cg->spanDeps = sdbase;
+ }
+
+ cg->numSpanDeps = index + 1;
+ sd = cg->spanDeps + index;
+ sd->top = PTRDIFF(pc, CG_BASE(cg), jsbytecode);
+ sd->offset = sd->before = PTRDIFF(pc2, CG_BASE(cg), jsbytecode);
+
+ if (js_CodeSpec[*pc].format & JOF_BACKPATCH) {
+ /* Jump offset will be backpatched if off is a non-zero "bpdelta". */
+ if (off != 0) {
+ JS_ASSERT(off >= 1 + JUMP_OFFSET_LEN);
+ if (off > BPDELTA_MAX) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+ }
+ SD_SET_BPDELTA(sd, off);
+ } else if (off == 0) {
+ /* Jump offset will be patched directly, without backpatch chaining. */
+ SD_SET_TARGET(sd, 0);
+ } else {
+ /* The jump offset in off is non-zero, therefore it's already known. */
+ if (!SetSpanDepTarget(cx, cg, sd, off))
+ return JS_FALSE;
+ }
+
+ if (index > SPANDEP_INDEX_MAX)
+ index = SPANDEP_INDEX_HUGE;
+ SET_SPANDEP_INDEX(pc2, index);
+ return JS_TRUE;
+}
+
+static jsbytecode *
+AddSwitchSpanDeps(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc)
+{
+ JSOp op;
+ jsbytecode *pc2;
+ ptrdiff_t off;
+ jsint low, high;
+ uintN njumps, indexlen;
+
+ op = (JSOp) *pc;
+ JS_ASSERT(op == JSOP_TABLESWITCH || op == JSOP_LOOKUPSWITCH);
+ pc2 = pc;
+ off = GET_JUMP_OFFSET(pc2);
+ if (!AddSpanDep(cx, cg, pc, pc2, off))
+ return NULL;
+ pc2 += JUMP_OFFSET_LEN;
+ if (op == JSOP_TABLESWITCH) {
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ njumps = (uintN) (high - low + 1);
+ indexlen = 0;
+ } else {
+ njumps = GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+ indexlen = INDEX_LEN;
+ }
+ while (njumps) {
+ --njumps;
+ pc2 += indexlen;
+ off = GET_JUMP_OFFSET(pc2);
+ if (!AddSpanDep(cx, cg, pc, pc2, off))
+ return NULL;
+ pc2 += JUMP_OFFSET_LEN;
+ }
+ return 1 + pc2;
+}
+
+static JSBool
+BuildSpanDepTable(JSContext *cx, JSCodeGenerator *cg)
+{
+ jsbytecode *pc, *end;
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t off;
+
+ pc = CG_BASE(cg) + cg->spanDepTodo;
+ end = CG_NEXT(cg);
+ while (pc != end) {
+ JS_ASSERT(pc < end);
+ op = (JSOp)*pc;
+ cs = &js_CodeSpec[op];
+
+ switch (JOF_TYPE(cs->format)) {
+ case JOF_TABLESWITCH:
+ case JOF_LOOKUPSWITCH:
+ pc = AddSwitchSpanDeps(cx, cg, pc);
+ if (!pc)
+ return JS_FALSE;
+ break;
+
+ case JOF_JUMP:
+ off = GET_JUMP_OFFSET(pc);
+ if (!AddSpanDep(cx, cg, pc, pc, off))
+ return JS_FALSE;
+ /* FALL THROUGH */
+ default:
+ pc += cs->length;
+ break;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSSpanDep *
+GetSpanDep(JSCodeGenerator *cg, jsbytecode *pc)
+{
+ uintN index;
+ ptrdiff_t offset;
+ int lo, hi, mid;
+ JSSpanDep *sd;
+
+ index = GET_SPANDEP_INDEX(pc);
+ if (index != SPANDEP_INDEX_HUGE)
+ return cg->spanDeps + index;
+
+ offset = PTRDIFF(pc, CG_BASE(cg), jsbytecode);
+ lo = 0;
+ hi = cg->numSpanDeps - 1;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ sd = cg->spanDeps + mid;
+ if (sd->before == offset)
+ return sd;
+ if (sd->before < offset)
+ lo = mid + 1;
+ else
+ hi = mid - 1;
+ }
+
+ JS_ASSERT(0);
+ return NULL;
+}
+
+static JSBool
+SetBackPatchDelta(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
+ ptrdiff_t delta)
+{
+ JSSpanDep *sd;
+
+ JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN);
+ if (!cg->spanDeps && delta < JUMP_OFFSET_MAX) {
+ SET_JUMP_OFFSET(pc, delta);
+ return JS_TRUE;
+ }
+
+ if (delta > BPDELTA_MAX) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ if (!cg->spanDeps && !BuildSpanDepTable(cx, cg))
+ return JS_FALSE;
+
+ sd = GetSpanDep(cg, pc);
+ JS_ASSERT(SD_GET_BPDELTA(sd) == 0);
+ SD_SET_BPDELTA(sd, delta);
+ return JS_TRUE;
+}
+
+static void
+UpdateJumpTargets(JSJumpTarget *jt, ptrdiff_t pivot, ptrdiff_t delta)
+{
+ if (jt->offset > pivot) {
+ jt->offset += delta;
+ if (jt->kids[JT_LEFT])
+ UpdateJumpTargets(jt->kids[JT_LEFT], pivot, delta);
+ }
+ if (jt->kids[JT_RIGHT])
+ UpdateJumpTargets(jt->kids[JT_RIGHT], pivot, delta);
+}
+
+static JSSpanDep *
+FindNearestSpanDep(JSCodeGenerator *cg, ptrdiff_t offset, int lo,
+ JSSpanDep *guard)
+{
+ int num, hi, mid;
+ JSSpanDep *sdbase, *sd;
+
+ num = cg->numSpanDeps;
+ JS_ASSERT(num > 0);
+ hi = num - 1;
+ sdbase = cg->spanDeps;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ sd = sdbase + mid;
+ if (sd->before == offset)
+ return sd;
+ if (sd->before < offset)
+ lo = mid + 1;
+ else
+ hi = mid - 1;
+ }
+ if (lo == num)
+ return guard;
+ sd = sdbase + lo;
+ JS_ASSERT(sd->before >= offset && (lo == 0 || sd[-1].before < offset));
+ return sd;
+}
+
+static void
+FreeJumpTargets(JSCodeGenerator *cg, JSJumpTarget *jt)
+{
+ if (jt->kids[JT_LEFT])
+ FreeJumpTargets(cg, jt->kids[JT_LEFT]);
+ if (jt->kids[JT_RIGHT])
+ FreeJumpTargets(cg, jt->kids[JT_RIGHT]);
+ jt->kids[JT_LEFT] = cg->jtFreeList;
+ cg->jtFreeList = jt;
+}
+
+static JSBool
+OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg)
+{
+ jsbytecode *pc, *oldpc, *base, *limit, *next;
+ JSSpanDep *sd, *sd2, *sdbase, *sdlimit, *sdtop, guard;
+ ptrdiff_t offset, growth, delta, top, pivot, span, length, target;
+ JSBool done;
+ JSOp op;
+ uint32 type;
+ size_t size, incr;
+ jssrcnote *sn, *snlimit;
+ JSSrcNoteSpec *spec;
+ uintN i, n, noteIndex;
+ JSTryNode *tryNode;
+#ifdef DEBUG_brendan
+ int passes = 0;
+#endif
+
+ base = CG_BASE(cg);
+ sdbase = cg->spanDeps;
+ sdlimit = sdbase + cg->numSpanDeps;
+ offset = CG_OFFSET(cg);
+ growth = 0;
+
+ do {
+ done = JS_TRUE;
+ delta = 0;
+ top = pivot = -1;
+ sdtop = NULL;
+ pc = NULL;
+ op = JSOP_NOP;
+ type = 0;
+#ifdef DEBUG_brendan
+ passes++;
+#endif
+
+ for (sd = sdbase; sd < sdlimit; sd++) {
+ JS_ASSERT(JT_HAS_TAG(sd->target));
+ sd->offset += delta;
+
+ if (sd->top != top) {
+ sdtop = sd;
+ top = sd->top;
+ JS_ASSERT(top == sd->before);
+ pivot = sd->offset;
+ pc = base + top;
+ op = (JSOp) *pc;
+ type = JOF_OPTYPE(op);
+ if (JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ /*
+ * We already extended all the jump offset operands for
+ * the opcode at sd->top. Jumps and branches have only
+ * one jump offset operand, but switches have many, all
+ * of which are adjacent in cg->spanDeps.
+ */
+ continue;
+ }
+
+ JS_ASSERT(type == JOF_JUMP ||
+ type == JOF_TABLESWITCH ||
+ type == JOF_LOOKUPSWITCH);
+ }
+
+ if (!JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ span = SD_SPAN(sd, pivot);
+ if (span < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < span) {
+ ptrdiff_t deltaFromTop = 0;
+
+ done = JS_FALSE;
+
+ switch (op) {
+ case JSOP_GOTO: op = JSOP_GOTOX; break;
+ case JSOP_IFEQ: op = JSOP_IFEQX; break;
+ case JSOP_IFNE: op = JSOP_IFNEX; break;
+ case JSOP_OR: op = JSOP_ORX; break;
+ case JSOP_AND: op = JSOP_ANDX; break;
+ case JSOP_GOSUB: op = JSOP_GOSUBX; break;
+ case JSOP_CASE: op = JSOP_CASEX; break;
+ case JSOP_DEFAULT: op = JSOP_DEFAULTX; break;
+ case JSOP_TABLESWITCH: op = JSOP_TABLESWITCHX; break;
+ case JSOP_LOOKUPSWITCH: op = JSOP_LOOKUPSWITCHX; break;
+ default:
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+ *pc = (jsbytecode) op;
+
+ for (sd2 = sdtop; sd2 < sdlimit && sd2->top == top; sd2++) {
+ if (sd2 <= sd) {
+ /*
+ * sd2->offset already includes delta as it stood
+ * before we entered this loop, but it must also
+ * include the delta relative to top due to all the
+ * extended jump offset immediates for the opcode
+ * starting at top, which we extend in this loop.
+ *
+ * If there is only one extended jump offset, then
+ * sd2->offset won't change and this for loop will
+ * iterate once only.
+ */
+ sd2->offset += deltaFromTop;
+ deltaFromTop += JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN;
+ } else {
+ /*
+ * sd2 comes after sd, and won't be revisited by
+ * the outer for loop, so we have to increase its
+ * offset by delta, not merely by deltaFromTop.
+ */
+ sd2->offset += delta;
+ }
+
+ delta += JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN;
+ UpdateJumpTargets(cg->jumpTargets, sd2->offset,
+ JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN);
+ }
+ sd = sd2 - 1;
+ }
+ }
+ }
+
+ growth += delta;
+ } while (!done);
+
+ if (growth) {
+#ifdef DEBUG_brendan
+ JSTokenStream *ts = &cg->treeContext.parseContext->tokenStream;
+
+ printf("%s:%u: %u/%u jumps extended in %d passes (%d=%d+%d)\n",
+ ts->filename ? ts->filename : "stdin", cg->firstLine,
+ growth / (JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN), cg->numSpanDeps,
+ passes, offset + growth, offset, growth);
+#endif
+
+ /*
+ * Ensure that we have room for the extended jumps, but don't round up
+ * to a power of two -- we're done generating code, so we cut to fit.
+ */
+ limit = CG_LIMIT(cg);
+ length = offset + growth;
+ next = base + length;
+ if (next > limit) {
+ JS_ASSERT(length > BYTECODE_CHUNK);
+ size = BYTECODE_SIZE(PTRDIFF(limit, base, jsbytecode));
+ incr = BYTECODE_SIZE(length) - size;
+ JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
+ if (!base) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ CG_BASE(cg) = base;
+ CG_LIMIT(cg) = next = base + length;
+ }
+ CG_NEXT(cg) = next;
+
+ /*
+ * Set up a fake span dependency record to guard the end of the code
+ * being generated. This guard record is returned as a fencepost by
+ * FindNearestSpanDep if there is no real spandep at or above a given
+ * unextended code offset.
+ */
+ guard.top = -1;
+ guard.offset = offset + growth;
+ guard.before = offset;
+ guard.target = NULL;
+ }
+
+ /*
+ * Now work backwards through the span dependencies, copying chunks of
+ * bytecode between each extended jump toward the end of the grown code
+ * space, and restoring immediate offset operands for all jump bytecodes.
+ * The first chunk of bytecodes, starting at base and ending at the first
+ * extended jump offset (NB: this chunk includes the operation bytecode
+ * just before that immediate jump offset), doesn't need to be copied.
+ */
+ JS_ASSERT(sd == sdlimit);
+ top = -1;
+ while (--sd >= sdbase) {
+ if (sd->top != top) {
+ top = sd->top;
+ op = (JSOp) base[top];
+ type = JOF_OPTYPE(op);
+
+ for (sd2 = sd - 1; sd2 >= sdbase && sd2->top == top; sd2--)
+ continue;
+ sd2++;
+ pivot = sd2->offset;
+ JS_ASSERT(top == sd2->before);
+ }
+
+ oldpc = base + sd->before;
+ span = SD_SPAN(sd, pivot);
+
+ /*
+ * If this jump didn't need to be extended, restore its span immediate
+ * offset operand now, overwriting the index of sd within cg->spanDeps
+ * that was stored temporarily after *pc when BuildSpanDepTable ran.
+ *
+ * Note that span might fit in 16 bits even for an extended jump op,
+ * if the op has multiple span operands, not all of which overflowed
+ * (e.g. JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH where some cases are in
+ * range for a short jump, but others are not).
+ */
+ if (!JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ JS_ASSERT(JUMP_OFFSET_MIN <= span && span <= JUMP_OFFSET_MAX);
+ SET_JUMP_OFFSET(oldpc, span);
+ continue;
+ }
+
+ /*
+ * Set up parameters needed to copy the next run of bytecode starting
+ * at offset (which is a cursor into the unextended, original bytecode
+ * vector), down to sd->before (a cursor of the same scale as offset,
+ * it's the index of the original jump pc). Reuse delta to count the
+ * nominal number of bytes to copy.
+ */
+ pc = base + sd->offset;
+ delta = offset - sd->before;
+ JS_ASSERT(delta >= 1 + JUMP_OFFSET_LEN);
+
+ /*
+ * Don't bother copying the jump offset we're about to reset, but do
+ * copy the bytecode at oldpc (which comes just before its immediate
+ * jump offset operand), on the next iteration through the loop, by
+ * including it in offset's new value.
+ */
+ offset = sd->before + 1;
+ size = BYTECODE_SIZE(delta - (1 + JUMP_OFFSET_LEN));
+ if (size) {
+ memmove(pc + 1 + JUMPX_OFFSET_LEN,
+ oldpc + 1 + JUMP_OFFSET_LEN,
+ size);
+ }
+
+ SET_JUMPX_OFFSET(pc, span);
+ }
+
+ if (growth) {
+ /*
+ * Fix source note deltas. Don't hardwire the delta fixup adjustment,
+ * even though currently it must be JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN
+ * at each sd that moved. The future may bring different offset sizes
+ * for span-dependent instruction operands. However, we fix only main
+ * notes here, not prolog notes -- we know that prolog opcodes are not
+ * span-dependent, and aren't likely ever to be.
+ */
+ offset = growth = 0;
+ sd = sdbase;
+ for (sn = cg->main.notes, snlimit = sn + cg->main.noteCount;
+ sn < snlimit;
+ sn = SN_NEXT(sn)) {
+ /*
+ * Recall that the offset of a given note includes its delta, and
+ * tells the offset of the annotated bytecode from the main entry
+ * point of the script.
+ */
+ offset += SN_DELTA(sn);
+ while (sd < sdlimit && sd->before < offset) {
+ /*
+ * To compute the delta to add to sn, we need to look at the
+ * spandep after sd, whose offset - (before + growth) tells by
+ * how many bytes sd's instruction grew.
+ */
+ sd2 = sd + 1;
+ if (sd2 == sdlimit)
+ sd2 = &guard;
+ delta = sd2->offset - (sd2->before + growth);
+ if (delta > 0) {
+ JS_ASSERT(delta == JUMPX_OFFSET_LEN - JUMP_OFFSET_LEN);
+ sn = js_AddToSrcNoteDelta(cx, cg, sn, delta);
+ if (!sn)
+ return JS_FALSE;
+ snlimit = cg->main.notes + cg->main.noteCount;
+ growth += delta;
+ }
+ sd++;
+ }
+
+ /*
+ * If sn has span-dependent offset operands, check whether each
+ * covers further span-dependencies, and increase those operands
+ * accordingly. Some source notes measure offset not from the
+ * annotated pc, but from that pc plus some small bias. NB: we
+ * assume that spec->offsetBias can't itself span span-dependent
+ * instructions!
+ */
+ spec = &js_SrcNoteSpec[SN_TYPE(sn)];
+ if (spec->isSpanDep) {
+ pivot = offset + spec->offsetBias;
+ n = spec->arity;
+ for (i = 0; i < n; i++) {
+ span = js_GetSrcNoteOffset(sn, i);
+ if (span == 0)
+ continue;
+ target = pivot + span * spec->isSpanDep;
+ sd2 = FindNearestSpanDep(cg, target,
+ (target >= pivot)
+ ? sd - sdbase
+ : 0,
+ &guard);
+
+ /*
+ * Increase target by sd2's before-vs-after offset delta,
+ * which is absolute (i.e., relative to start of script,
+ * as is target). Recompute the span by subtracting its
+ * adjusted pivot from target.
+ */
+ target += sd2->offset - sd2->before;
+ span = target - (pivot + growth);
+ span *= spec->isSpanDep;
+ noteIndex = sn - cg->main.notes;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, i, span))
+ return JS_FALSE;
+ sn = cg->main.notes + noteIndex;
+ snlimit = cg->main.notes + cg->main.noteCount;
+ }
+ }
+ }
+ cg->main.lastNoteOffset += growth;
+
+ /*
+ * Fix try/catch notes (O(numTryNotes * log2(numSpanDeps)), but it's
+ * not clear how we can beat that).
+ */
+ for (tryNode = cg->lastTryNode; tryNode; tryNode = tryNode->prev) {
+ /*
+ * First, look for the nearest span dependency at/above tn->start.
+ * There may not be any such spandep, in which case the guard will
+ * be returned.
+ */
+ offset = tryNode->note.start;
+ sd = FindNearestSpanDep(cg, offset, 0, &guard);
+ delta = sd->offset - sd->before;
+ tryNode->note.start = offset + delta;
+
+ /*
+ * Next, find the nearest spandep at/above tn->start + tn->length.
+ * Use its delta minus tn->start's delta to increase tn->length.
+ */
+ length = tryNode->note.length;
+ sd2 = FindNearestSpanDep(cg, offset + length, sd - sdbase, &guard);
+ if (sd2 != sd) {
+ tryNode->note.length =
+ length + sd2->offset - sd2->before - delta;
+ }
+ }
+ }
+
+#ifdef DEBUG_brendan
+ {
+ uintN bigspans = 0;
+ top = -1;
+ for (sd = sdbase; sd < sdlimit; sd++) {
+ offset = sd->offset;
+
+ /* NB: sd->top cursors into the original, unextended bytecode vector. */
+ if (sd->top != top) {
+ JS_ASSERT(top == -1 ||
+ !JOF_TYPE_IS_EXTENDED_JUMP(type) ||
+ bigspans != 0);
+ bigspans = 0;
+ top = sd->top;
+ JS_ASSERT(top == sd->before);
+ op = (JSOp) base[offset];
+ type = JOF_OPTYPE(op);
+ JS_ASSERT(type == JOF_JUMP ||
+ type == JOF_JUMPX ||
+ type == JOF_TABLESWITCH ||
+ type == JOF_TABLESWITCHX ||
+ type == JOF_LOOKUPSWITCH ||
+ type == JOF_LOOKUPSWITCHX);
+ pivot = offset;
+ }
+
+ pc = base + offset;
+ if (JOF_TYPE_IS_EXTENDED_JUMP(type)) {
+ span = GET_JUMPX_OFFSET(pc);
+ if (span < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < span) {
+ bigspans++;
+ } else {
+ JS_ASSERT(type == JOF_TABLESWITCHX ||
+ type == JOF_LOOKUPSWITCHX);
+ }
+ } else {
+ span = GET_JUMP_OFFSET(pc);
+ }
+ JS_ASSERT(SD_SPAN(sd, pivot) == span);
+ }
+ JS_ASSERT(!JOF_TYPE_IS_EXTENDED_JUMP(type) || bigspans != 0);
+ }
+#endif
+
+ /*
+ * Reset so we optimize at most once -- cg may be used for further code
+ * generation of successive, independent, top-level statements. No jump
+ * can span top-level statements, because JS lacks goto.
+ */
+ size = SPANDEPS_SIZE(JS_BIT(JS_CeilingLog2(cg->numSpanDeps)));
+ JS_free(cx, cg->spanDeps);
+ cg->spanDeps = NULL;
+ FreeJumpTargets(cg, cg->jumpTargets);
+ cg->jumpTargets = NULL;
+ cg->numSpanDeps = cg->numJumpTargets = 0;
+ cg->spanDepTodo = CG_OFFSET(cg);
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+EmitJump(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t off)
+{
+ JSBool extend;
+ ptrdiff_t jmp;
+ jsbytecode *pc;
+
+ extend = off < JUMP_OFFSET_MIN || JUMP_OFFSET_MAX < off;
+ if (extend && !cg->spanDeps && !BuildSpanDepTable(cx, cg))
+ return -1;
+
+ jmp = js_Emit3(cx, cg, op, JUMP_OFFSET_HI(off), JUMP_OFFSET_LO(off));
+ if (jmp >= 0 && (extend || cg->spanDeps)) {
+ pc = CG_CODE(cg, jmp);
+ if (!AddSpanDep(cx, cg, pc, pc, off))
+ return -1;
+ }
+ return jmp;
+}
+
+static ptrdiff_t
+GetJumpOffset(JSCodeGenerator *cg, jsbytecode *pc)
+{
+ JSSpanDep *sd;
+ JSJumpTarget *jt;
+ ptrdiff_t top;
+
+ if (!cg->spanDeps)
+ return GET_JUMP_OFFSET(pc);
+
+ sd = GetSpanDep(cg, pc);
+ jt = sd->target;
+ if (!JT_HAS_TAG(jt))
+ return JT_TO_BPDELTA(jt);
+
+ top = sd->top;
+ while (--sd >= cg->spanDeps && sd->top == top)
+ continue;
+ sd++;
+ return JT_CLR_TAG(jt)->offset - sd->offset;
+}
+
+JSBool
+js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
+ ptrdiff_t off)
+{
+ if (!cg->spanDeps) {
+ if (JUMP_OFFSET_MIN <= off && off <= JUMP_OFFSET_MAX) {
+ SET_JUMP_OFFSET(pc, off);
+ return JS_TRUE;
+ }
+
+ if (!BuildSpanDepTable(cx, cg))
+ return JS_FALSE;
+ }
+
+ return SetSpanDepTarget(cx, cg, GetSpanDep(cg, pc), off);
+}
+
+JSBool
+js_InStatement(JSTreeContext *tc, JSStmtType type)
+{
+ JSStmtInfo *stmt;
+
+ for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
+ if (stmt->type == type)
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+void
+js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
+ ptrdiff_t top)
+{
+ stmt->type = type;
+ stmt->flags = 0;
+ SET_STATEMENT_TOP(stmt, top);
+ stmt->u.label = NULL;
+ JS_ASSERT(!stmt->u.blockObj);
+ stmt->down = tc->topStmt;
+ tc->topStmt = stmt;
+ if (STMT_LINKS_SCOPE(stmt)) {
+ stmt->downScope = tc->topScopeStmt;
+ tc->topScopeStmt = stmt;
+ } else {
+ stmt->downScope = NULL;
+ }
+}
+
+void
+js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
+ ptrdiff_t top)
+{
+
+ js_PushStatement(tc, stmt, STMT_BLOCK, top);
+ stmt->flags |= SIF_SCOPE;
+ STOBJ_SET_PARENT(blockObj, tc->blockChain);
+ stmt->downScope = tc->topScopeStmt;
+ tc->topScopeStmt = stmt;
+ tc->blockChain = blockObj;
+ stmt->u.blockObj = blockObj;
+}
+
+/*
+ * Emit a backpatch op with offset pointing to the previous jump of this type,
+ * so that we can walk back up the chain fixing up the op and jump offset.
+ */
+static ptrdiff_t
+EmitBackPatchOp(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t *lastp)
+{
+ ptrdiff_t offset, delta;
+
+ offset = CG_OFFSET(cg);
+ delta = offset - *lastp;
+ *lastp = offset;
+ JS_ASSERT(delta > 0);
+ return EmitJump(cx, cg, op, delta);
+}
+
+/*
+ * Macro to emit a bytecode followed by a uint16 immediate operand stored in
+ * big-endian order, used for arg and var numbers as well as for atomIndexes.
+ * NB: We use cx and cg from our caller's lexical environment, and return
+ * false on error.
+ */
+#define EMIT_UINT16_IMM_OP(op, i) \
+ JS_BEGIN_MACRO \
+ if (js_Emit3(cx, cg, op, UINT16_HI(i), UINT16_LO(i)) < 0) \
+ return JS_FALSE; \
+ JS_END_MACRO
+
+static JSBool
+FlushPops(JSContext *cx, JSCodeGenerator *cg, intN *npops)
+{
+ JS_ASSERT(*npops != 0);
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_POPN, *npops);
+ *npops = 0;
+ return JS_TRUE;
+}
+
+/*
+ * Emit additional bytecode(s) for non-local jumps.
+ */
+static JSBool
+EmitNonLocalJumpFixup(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt)
+{
+ intN depth, npops;
+ JSStmtInfo *stmt;
+
+ /*
+ * The non-local jump fixup we emit will unbalance cg->stackDepth, because
+ * the fixup replicates balanced code such as JSOP_LEAVEWITH emitted at the
+ * end of a with statement, so we save cg->stackDepth here and restore it
+ * just before a successful return.
+ */
+ depth = cg->stackDepth;
+ npops = 0;
+
+#define FLUSH_POPS() if (npops && !FlushPops(cx, cg, &npops)) return JS_FALSE
+
+ for (stmt = cg->treeContext.topStmt; stmt != toStmt; stmt = stmt->down) {
+ switch (stmt->type) {
+ case STMT_FINALLY:
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &GOSUBS(*stmt)) < 0)
+ return JS_FALSE;
+ break;
+
+ case STMT_WITH:
+ /* There's a With object on the stack that we need to pop. */
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)
+ return JS_FALSE;
+ break;
+
+ case STMT_FOR_IN_LOOP:
+ /*
+ * The iterator and the object being iterated need to be popped.
+ */
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENDITER) < 0)
+ return JS_FALSE;
+ break;
+
+ case STMT_SUBROUTINE:
+ /*
+ * There's a [exception or hole, retsub pc-index] pair on the
+ * stack that we need to pop.
+ */
+ npops += 2;
+ break;
+
+ default:;
+ }
+
+ if (stmt->flags & SIF_SCOPE) {
+ uintN i;
+
+ /* There is a Block object with locals on the stack to pop. */
+ FLUSH_POPS();
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ i = OBJ_BLOCK_COUNT(cx, stmt->u.blockObj);
+ EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, i);
+ }
+ }
+
+ FLUSH_POPS();
+ cg->stackDepth = depth;
+ return JS_TRUE;
+
+#undef FLUSH_POPS
+}
+
+static ptrdiff_t
+EmitGoto(JSContext *cx, JSCodeGenerator *cg, JSStmtInfo *toStmt,
+ ptrdiff_t *lastp, JSAtomListElement *label, JSSrcNoteType noteType)
+{
+ intN index;
+
+ if (!EmitNonLocalJumpFixup(cx, cg, toStmt))
+ return -1;
+
+ if (label)
+ index = js_NewSrcNote2(cx, cg, noteType, (ptrdiff_t) ALE_INDEX(label));
+ else if (noteType != SRC_NULL)
+ index = js_NewSrcNote(cx, cg, noteType);
+ else
+ index = 0;
+ if (index < 0)
+ return -1;
+
+ return EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, lastp);
+}
+
+static JSBool
+BackPatch(JSContext *cx, JSCodeGenerator *cg, ptrdiff_t last,
+ jsbytecode *target, jsbytecode op)
+{
+ jsbytecode *pc, *stop;
+ ptrdiff_t delta, span;
+
+ pc = CG_CODE(cg, last);
+ stop = CG_CODE(cg, -1);
+ while (pc != stop) {
+ delta = GetJumpOffset(cg, pc);
+ span = PTRDIFF(target, pc, jsbytecode);
+ CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, span);
+
+ /*
+ * Set *pc after jump offset in case bpdelta didn't overflow, but span
+ * does (if so, CHECK_AND_SET_JUMP_OFFSET might call BuildSpanDepTable
+ * and need to see the JSOP_BACKPATCH* op at *pc).
+ */
+ *pc = op;
+ pc -= delta;
+ }
+ return JS_TRUE;
+}
+
+void
+js_PopStatement(JSTreeContext *tc)
+{
+ JSStmtInfo *stmt;
+
+ stmt = tc->topStmt;
+ tc->topStmt = stmt->down;
+ if (STMT_LINKS_SCOPE(stmt)) {
+ tc->topScopeStmt = stmt->downScope;
+ if (stmt->flags & SIF_SCOPE) {
+ tc->blockChain = STOBJ_GET_PARENT(stmt->u.blockObj);
+ JS_SCOPE_DEPTH_METERING(--tc->scopeDepth);
+ }
+ }
+}
+
+JSBool
+js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg)
+{
+ JSStmtInfo *stmt;
+
+ stmt = cg->treeContext.topStmt;
+ if (!STMT_IS_TRYING(stmt) &&
+ (!BackPatch(cx, cg, stmt->breaks, CG_NEXT(cg), JSOP_GOTO) ||
+ !BackPatch(cx, cg, stmt->continues, CG_CODE(cg, stmt->update),
+ JSOP_GOTO))) {
+ return JS_FALSE;
+ }
+ js_PopStatement(&cg->treeContext);
+ return JS_TRUE;
+}
+
+JSBool
+js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
+ JSParseNode *pn)
+{
+ jsdouble dval;
+ jsint ival;
+ JSAtom *valueAtom;
+ jsval v;
+ JSAtomListElement *ale;
+
+ /* XXX just do numbers for now */
+ if (pn->pn_type == TOK_NUMBER) {
+ dval = pn->pn_dval;
+ if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) {
+ v = INT_TO_JSVAL(ival);
+ } else {
+ /*
+ * We atomize double to root a jsdouble instance that we wrap as
+ * jsval and store in cg->constList. This works because atoms are
+ * protected from GC during compilation.
+ */
+ valueAtom = js_AtomizeDouble(cx, dval);
+ if (!valueAtom)
+ return JS_FALSE;
+ v = ATOM_KEY(valueAtom);
+ }
+ ale = js_IndexAtom(cx, atom, &cg->constList);
+ if (!ale)
+ return JS_FALSE;
+ ALE_SET_VALUE(ale, v);
+ }
+ return JS_TRUE;
+}
+
+JSStmtInfo *
+js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp)
+{
+ JSStmtInfo *stmt;
+ JSObject *obj;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ for (stmt = tc->topScopeStmt; stmt; stmt = stmt->downScope) {
+ if (stmt->type == STMT_WITH)
+ break;
+
+ /* Skip "maybe scope" statements that don't contain let bindings. */
+ if (!(stmt->flags & SIF_SCOPE))
+ continue;
+
+ obj = stmt->u.blockObj;
+ JS_ASSERT(LOCKED_OBJ_GET_CLASS(obj) == &js_BlockClass);
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_GET_PROPERTY(scope, ATOM_TO_JSID(atom));
+ if (sprop) {
+ JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
+
+ if (slotp) {
+ JS_ASSERT(JSVAL_IS_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]));
+ *slotp = JSVAL_TO_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]) +
+ sprop->shortid;
+ }
+ return stmt;
+ }
+ }
+
+ if (slotp)
+ *slotp = -1;
+ return stmt;
+}
+
+/*
+ * Check if the attributes describe a property holding a compile-time constant
+ * or a permanent, read-only property without a getter.
+ */
+#define IS_CONSTANT_PROPERTY(attrs) \
+ (((attrs) & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_GETTER)) == \
+ (JSPROP_READONLY | JSPROP_PERMANENT))
+
+/*
+ * The function sets vp to JSVAL_HOLE when the atom does not corresponds to a
+ * name defining a constant.
+ */
+static JSBool
+LookupCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
+ jsval *vp)
+{
+ JSBool ok;
+ JSStmtInfo *stmt;
+ JSAtomListElement *ale;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+ uintN attrs;
+
+ /*
+ * Chase down the cg stack, but only until we reach the outermost cg.
+ * This enables propagating consts from top-level into switch cases in a
+ * function compiled along with the top-level script.
+ */
+ *vp = JSVAL_HOLE;
+ do {
+ if (cg->treeContext.flags & (TCF_IN_FUNCTION | TCF_COMPILE_N_GO)) {
+ /* XXX this will need revising when 'let const' is added. */
+ stmt = js_LexicalLookup(&cg->treeContext, atom, NULL);
+ if (stmt)
+ return JS_TRUE;
+
+ ATOM_LIST_SEARCH(ale, &cg->constList, atom);
+ if (ale) {
+ JS_ASSERT(ALE_VALUE(ale) != JSVAL_HOLE);
+ *vp = ALE_VALUE(ale);
+ return JS_TRUE;
+ }
+
+ /*
+ * Try looking in the variable object for a direct property that
+ * is readonly and permanent. We know such a property can't be
+ * shadowed by another property on obj's prototype chain, or a
+ * with object or catch variable; nor can prop's value be changed,
+ * nor can prop be deleted.
+ */
+ if (cg->treeContext.flags & TCF_IN_FUNCTION) {
+ if (js_LookupLocal(cx, cg->treeContext.u.fun, atom, NULL) !=
+ JSLOCAL_NONE) {
+ break;
+ }
+ } else {
+ JS_ASSERT(cg->treeContext.flags & TCF_COMPILE_N_GO);
+ obj = cg->treeContext.u.scopeChain;
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &pobj,
+ &prop);
+ if (!ok)
+ return JS_FALSE;
+ if (pobj == obj) {
+ /*
+ * We're compiling code that will be executed immediately,
+ * not re-executed against a different scope chain and/or
+ * variable object. Therefore we can get constant values
+ * from our variable object here.
+ */
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, ATOM_TO_JSID(atom), prop,
+ &attrs);
+ if (ok && IS_CONSTANT_PROPERTY(attrs)) {
+ ok = OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp);
+ JS_ASSERT_IF(ok, *vp != JSVAL_HOLE);
+ }
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ if (!ok)
+ return JS_FALSE;
+ if (prop)
+ break;
+ }
+ }
+ } while ((cg = cg->parent) != NULL);
+ return JS_TRUE;
+}
+
+/*
+ * Return JSOP_NOP to indicate that index fits 2 bytes and no index segment
+ * reset instruction is necessary, JSOP_FALSE to indicate an error or either
+ * JSOP_RESETBASE0 or JSOP_RESETBASE1 to indicate the reset bytecode to issue
+ * after the main bytecode sequence.
+ */
+static JSOp
+EmitBigIndexPrefix(JSContext *cx, JSCodeGenerator *cg, uintN index)
+{
+ uintN indexBase;
+
+ /*
+ * We have max 3 bytes for indexes and check for INDEX_LIMIT overflow only
+ * for big indexes.
+ */
+ JS_STATIC_ASSERT(INDEX_LIMIT <= JS_BIT(24));
+ JS_STATIC_ASSERT(INDEX_LIMIT >=
+ (JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 2) << 16);
+
+ if (index < JS_BIT(16))
+ return JSOP_NOP;
+ indexBase = index >> 16;
+ if (indexBase <= JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 1) {
+ if (js_Emit1(cx, cg, (JSOp)(JSOP_INDEXBASE1 + indexBase - 1)) < 0)
+ return JSOP_FALSE;
+ return JSOP_RESETBASE0;
+ }
+
+ if (index >= INDEX_LIMIT) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_LITERALS);
+ return JSOP_FALSE;
+ }
+
+ if (js_Emit2(cx, cg, JSOP_INDEXBASE, (JSOp)indexBase) < 0)
+ return JSOP_FALSE;
+ return JSOP_RESETBASE;
+}
+
+/*
+ * Emit a bytecode and its 2-byte constant index immediate operand. If the
+ * index requires more than 2 bytes, emit a prefix op whose 8-bit immediate
+ * operand effectively extends the 16-bit immediate of the prefixed opcode,
+ * by changing index "segment" (see jsinterp.c). We optimize segments 1-3
+ * with single-byte JSOP_INDEXBASE[123] codes.
+ *
+ * Such prefixing currently requires a suffix to restore the "zero segment"
+ * register setting, but this could be optimized further.
+ */
+static JSBool
+EmitIndexOp(JSContext *cx, JSOp op, uintN index, JSCodeGenerator *cg)
+{
+ JSOp bigSuffix;
+
+ bigSuffix = EmitBigIndexPrefix(cx, cg, index);
+ if (bigSuffix == JSOP_FALSE)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(op, index);
+ return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0;
+}
+
+/*
+ * Slight sugar for EmitIndexOp, again accessing cx and cg from the macro
+ * caller's lexical environment, and embedding a false return on error.
+ */
+#define EMIT_INDEX_OP(op, index) \
+ JS_BEGIN_MACRO \
+ if (!EmitIndexOp(cx, op, index, cg)) \
+ return JS_FALSE; \
+ JS_END_MACRO
+
+
+static JSBool
+EmitAtomOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
+{
+ JSAtomListElement *ale;
+
+ JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
+ if (op == JSOP_GETPROP &&
+ pn->pn_atom == cx->runtime->atomState.lengthAtom) {
+ return js_Emit1(cx, cg, JSOP_LENGTH) >= 0;
+ }
+ ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ return EmitIndexOp(cx, op, ALE_INDEX(ale), cg);
+}
+
+static uintN
+IndexParsedObject(JSParsedObjectBox *pob, JSEmittedObjectList *list);
+
+static JSBool
+EmitObjectOp(JSContext *cx, JSParsedObjectBox *pob, JSOp op,
+ JSCodeGenerator *cg)
+{
+ JS_ASSERT(JOF_OPTYPE(op) == JOF_OBJECT);
+ return EmitIndexOp(cx, op, IndexParsedObject(pob, &cg->objectList), cg);
+}
+
+/*
+ * What good are ARGNO_LEN and SLOTNO_LEN, you ask? The answer is that, apart
+ * from EmitSlotIndexOp, they abstract out the detail that both are 2, and in
+ * other parts of the code there's no necessary relationship between the two.
+ * The abstraction cracks here in order to share EmitSlotIndexOp code among
+ * the JSOP_DEFLOCALFUN and JSOP_GET{ARG,VAR,LOCAL}PROP cases.
+ */
+JS_STATIC_ASSERT(ARGNO_LEN == 2);
+JS_STATIC_ASSERT(SLOTNO_LEN == 2);
+
+static JSBool
+EmitSlotIndexOp(JSContext *cx, JSOp op, uintN slot, uintN index,
+ JSCodeGenerator *cg)
+{
+ JSOp bigSuffix;
+ ptrdiff_t off;
+ jsbytecode *pc;
+
+ JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTATOM ||
+ JOF_OPTYPE(op) == JOF_SLOTOBJECT);
+ bigSuffix = EmitBigIndexPrefix(cx, cg, index);
+ if (bigSuffix == JSOP_FALSE)
+ return JS_FALSE;
+
+ /* Emit [op, slot, index]. */
+ off = js_EmitN(cx, cg, op, 2 + INDEX_LEN);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_UINT16(pc, slot);
+ pc += 2;
+ SET_INDEX(pc, index);
+ return bigSuffix == JSOP_NOP || js_Emit1(cx, cg, bigSuffix) >= 0;
+}
+
+/*
+ * Adjust the slot for a block local to account for the number of variables
+ * that share the same index space with locals. Due to the incremental code
+ * generation for top-level script, we do the adjustment via code patching in
+ * js_CompileScript; see comments there.
+ *
+ * The function returns -1 on failures.
+ */
+static jsint
+AdjustBlockSlot(JSContext *cx, JSCodeGenerator *cg, jsint slot)
+{
+ JS_ASSERT((jsuint) slot < cg->maxStackDepth);
+ if (cg->treeContext.flags & TCF_IN_FUNCTION) {
+ slot += cg->treeContext.u.fun->u.i.nvars;
+ if ((uintN) slot >= SLOTNO_LIMIT) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), NULL,
+ JSREPORT_ERROR,
+ JSMSG_TOO_MANY_LOCALS);
+ slot = -1;
+ }
+ }
+ return slot;
+}
+
+/*
+ * This routine tries to optimize name gets and sets to stack slot loads and
+ * stores, given the variables object and scope chain in cx's top frame, the
+ * compile-time context in tc, and a TOK_NAME node pn. It returns false on
+ * error, true on success.
+ *
+ * The caller can inspect pn->pn_slot for a non-negative slot number to tell
+ * whether optimization occurred, in which case BindNameToSlot also updated
+ * pn->pn_op. If pn->pn_slot is still -1 on return, pn->pn_op nevertheless
+ * may have been optimized, e.g., from JSOP_NAME to JSOP_ARGUMENTS. Whether
+ * or not pn->pn_op was modified, if this function finds an argument or local
+ * variable name, pn->pn_const will be true for const properties after a
+ * successful return.
+ *
+ * NB: if you add more opcodes specialized from JSOP_NAME, etc., don't forget
+ * to update the TOK_FOR (for-in) and TOK_ASSIGN (op=, e.g. +=) special cases
+ * in js_EmitTree.
+ */
+static JSBool
+BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ JSTreeContext *tc;
+ JSAtom *atom;
+ JSStmtInfo *stmt;
+ jsint slot;
+ JSOp op;
+ JSLocalKind localKind;
+ uintN index;
+ JSAtomListElement *ale;
+ JSBool constOp;
+
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ if (pn->pn_slot >= 0 || pn->pn_op == JSOP_ARGUMENTS)
+ return JS_TRUE;
+
+ /* QNAME references can never be optimized to use arg/var storage. */
+ if (pn->pn_op == JSOP_QNAMEPART)
+ return JS_TRUE;
+
+ /*
+ * We can't optimize if we are compiling a with statement and its body,
+ * or we're in a catch block whose exception variable has the same name
+ * as this node. FIXME: we should be able to optimize catch vars to be
+ * block-locals.
+ */
+ tc = &cg->treeContext;
+ atom = pn->pn_atom;
+ stmt = js_LexicalLookup(tc, atom, &slot);
+ if (stmt) {
+ if (stmt->type == STMT_WITH)
+ return JS_TRUE;
+
+ JS_ASSERT(stmt->flags & SIF_SCOPE);
+ JS_ASSERT(slot >= 0);
+ op = PN_OP(pn);
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETLOCAL; break;
+ case JSOP_SETNAME: op = JSOP_SETLOCAL; break;
+ case JSOP_INCNAME: op = JSOP_INCLOCAL; break;
+ case JSOP_NAMEINC: op = JSOP_LOCALINC; break;
+ case JSOP_DECNAME: op = JSOP_DECLOCAL; break;
+ case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break;
+ case JSOP_FORNAME: op = JSOP_FORLOCAL; break;
+ case JSOP_DELNAME: op = JSOP_FALSE; break;
+ default: JS_ASSERT(0);
+ }
+ if (op != pn->pn_op) {
+ slot = AdjustBlockSlot(cx, cg, slot);
+ if (slot < 0)
+ return JS_FALSE;
+ pn->pn_op = op;
+ pn->pn_slot = slot;
+ }
+ return JS_TRUE;
+ }
+
+ /*
+ * We can't optimize if var and closure (a local function not in a larger
+ * expression and not at top-level within another's body) collide.
+ * XXX suboptimal: keep track of colliding names and deoptimize only those
+ */
+ if (tc->flags & TCF_FUN_CLOSURE_VS_VAR)
+ return JS_TRUE;
+
+ if (!(tc->flags & TCF_IN_FUNCTION)) {
+ JSStackFrame *caller;
+
+ caller = tc->parseContext->callerFrame;
+ if (caller) {
+ JS_ASSERT(tc->flags & TCF_COMPILE_N_GO);
+ JS_ASSERT(caller->script);
+ if (!caller->fun || caller->varobj != tc->u.scopeChain)
+ return JS_TRUE;
+
+ /*
+ * We are compiling eval or debug script inside a function frame
+ * and the scope chain matches function's variable object.
+ * Optimize access to function's arguments and variable and the
+ * arguments object.
+ */
+ if (PN_OP(pn) != JSOP_NAME || cg->staticDepth > JS_DISPLAY_SIZE)
+ goto arguments_check;
+ localKind = js_LookupLocal(cx, caller->fun, atom, &index);
+ if (localKind == JSLOCAL_NONE)
+ goto arguments_check;
+
+ ATOM_LIST_SEARCH(ale, &cg->upvarList, atom);
+ if (!ale) {
+ uint32 length, *vector;
+
+ ale = js_IndexAtom(cx, atom, &cg->upvarList);
+ if (!ale)
+ return JS_FALSE;
+ JS_ASSERT(ALE_INDEX(ale) == cg->upvarList.count - 1);
+
+ length = cg->upvarMap.length;
+ JS_ASSERT(ALE_INDEX(ale) <= length);
+ if (ALE_INDEX(ale) == length) {
+ length = 2 * JS_MAX(2, length);
+ vector = (uint32 *)
+ JS_realloc(cx, cg->upvarMap.vector,
+ length * sizeof *vector);
+ if (!vector)
+ return JS_FALSE;
+ cg->upvarMap.vector = vector;
+ cg->upvarMap.length = length;
+ }
+
+ if (localKind != JSLOCAL_ARG)
+ index += caller->fun->nargs;
+ if (index >= JS_BIT(16)) {
+ cg->treeContext.flags |= TCF_FUN_USES_NONLOCALS;
+ return JS_TRUE;
+ }
+
+ JS_ASSERT(cg->staticDepth > caller->fun->u.i.script->staticDepth);
+ uintN skip = cg->staticDepth - caller->fun->u.i.script->staticDepth;
+ cg->upvarMap.vector[ALE_INDEX(ale)] = MAKE_UPVAR_COOKIE(skip, index);
+ }
+
+ pn->pn_op = JSOP_GETUPVAR;
+ pn->pn_slot = ALE_INDEX(ale);
+ return JS_TRUE;
+ }
+
+ /*
+ * We are optimizing global variables and there may be no pre-existing
+ * global property named atom. If atom was declared via const or var,
+ * optimize pn to access fp->vars using the appropriate JSOP_*GVAR op.
+ */
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ if (!ale) {
+ /* Use precedes declaration, or name is never declared. */
+ return JS_TRUE;
+ }
+ constOp = (ALE_JSOP(ale) == JSOP_DEFCONST);
+
+ /* Index atom so we can map fast global number to name. */
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+
+ /* Defend against tc->ngvars 16-bit overflow. */
+ slot = ALE_INDEX(ale);
+ if ((slot + 1) >> 16)
+ return JS_TRUE;
+
+ if ((uint16)(slot + 1) > tc->ngvars)
+ tc->ngvars = (uint16)(slot + 1);
+
+ op = PN_OP(pn);
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETGVAR; break;
+ case JSOP_SETNAME: op = JSOP_SETGVAR; break;
+ case JSOP_SETCONST: /* NB: no change */ break;
+ case JSOP_INCNAME: op = JSOP_INCGVAR; break;
+ case JSOP_NAMEINC: op = JSOP_GVARINC; break;
+ case JSOP_DECNAME: op = JSOP_DECGVAR; break;
+ case JSOP_NAMEDEC: op = JSOP_GVARDEC; break;
+ case JSOP_FORNAME: /* NB: no change */ break;
+ case JSOP_DELNAME: /* NB: no change */ break;
+ default: JS_NOT_REACHED("gvar");
+ }
+ pn->pn_const = constOp;
+ if (op != pn->pn_op) {
+ pn->pn_op = op;
+ pn->pn_slot = slot;
+ }
+ return JS_TRUE;
+ }
+
+ if (tc->flags & TCF_IN_FUNCTION) {
+ /*
+ * We are compiling a function body and may be able to optimize name
+ * to stack slot. Look for an argument or variable in the function and
+ * rewrite pn_op and update pn accordingly.
+ */
+ localKind = js_LookupLocal(cx, tc->u.fun, atom, &index);
+ if (localKind != JSLOCAL_NONE) {
+ op = PN_OP(pn);
+ if (localKind == JSLOCAL_ARG) {
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETARG; break;
+ case JSOP_SETNAME: op = JSOP_SETARG; break;
+ case JSOP_INCNAME: op = JSOP_INCARG; break;
+ case JSOP_NAMEINC: op = JSOP_ARGINC; break;
+ case JSOP_DECNAME: op = JSOP_DECARG; break;
+ case JSOP_NAMEDEC: op = JSOP_ARGDEC; break;
+ case JSOP_FORNAME: op = JSOP_FORARG; break;
+ case JSOP_DELNAME: op = JSOP_FALSE; break;
+ default: JS_NOT_REACHED("arg");
+ }
+ pn->pn_const = JS_FALSE;
+ } else {
+ JS_ASSERT(localKind == JSLOCAL_VAR ||
+ localKind == JSLOCAL_CONST);
+ switch (op) {
+ case JSOP_NAME: op = JSOP_GETLOCAL; break;
+ case JSOP_SETNAME: op = JSOP_SETLOCAL; break;
+ case JSOP_SETCONST: op = JSOP_SETLOCAL; break;
+ case JSOP_INCNAME: op = JSOP_INCLOCAL; break;
+ case JSOP_NAMEINC: op = JSOP_LOCALINC; break;
+ case JSOP_DECNAME: op = JSOP_DECLOCAL; break;
+ case JSOP_NAMEDEC: op = JSOP_LOCALDEC; break;
+ case JSOP_FORNAME: op = JSOP_FORLOCAL; break;
+ case JSOP_DELNAME: op = JSOP_FALSE; break;
+ default: JS_NOT_REACHED("local");
+ }
+ pn->pn_const = (localKind == JSLOCAL_CONST);
+ }
+ pn->pn_op = op;
+ pn->pn_slot = index;
+ return JS_TRUE;
+ }
+ tc->flags |= TCF_FUN_USES_NONLOCALS;
+ }
+
+ arguments_check:
+ /*
+ * Here we either compiling a function body or an eval or debug script
+ * inside a function and couldn't optimize pn, so it's not a global or
+ * local slot name. We are also outside of any with blocks. Check if we
+ * can optimize the predefined arguments variable.
+ */
+ JS_ASSERT((tc->flags & TCF_IN_FUNCTION) ||
+ (tc->parseContext->callerFrame &&
+ tc->parseContext->callerFrame->fun &&
+ tc->parseContext->callerFrame->varobj == tc->u.scopeChain));
+ if (pn->pn_op == JSOP_NAME &&
+ atom == cx->runtime->atomState.argumentsAtom) {
+ pn->pn_op = JSOP_ARGUMENTS;
+ return JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * If pn contains a useful expression, return true with *answer set to true.
+ * If pn contains a useless expression, return true with *answer set to false.
+ * Return false on error.
+ *
+ * The caller should initialize *answer to false and invoke this function on
+ * an expression statement or similar subtree to decide whether the tree could
+ * produce code that has any side effects. For an expression statement, we
+ * define useless code as code with no side effects, because the main effect,
+ * the value left on the stack after the code executes, will be discarded by a
+ * pop bytecode.
+ */
+static JSBool
+CheckSideEffects(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSBool *answer)
+{
+ JSBool ok;
+ JSFunction *fun;
+ JSParseNode *pn2;
+
+ ok = JS_TRUE;
+ if (!pn || *answer)
+ return ok;
+
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ /*
+ * A named function is presumed useful: we can't yet know that it is
+ * not called. The side effects are the creation of a scope object
+ * to parent this function object, and the binding of the function's
+ * name in that scope object. See comments at case JSOP_NAMEDFUNOBJ:
+ * in jsinterp.c.
+ */
+ fun = (JSFunction *) pn->pn_funpob->object;
+ if (fun->atom)
+ *answer = JS_TRUE;
+ break;
+
+ case PN_LIST:
+ if (pn->pn_op == JSOP_NOP ||
+ pn->pn_op == JSOP_OR || pn->pn_op == JSOP_AND ||
+ pn->pn_op == JSOP_STRICTEQ || pn->pn_op == JSOP_STRICTNE) {
+ /*
+ * Non-operators along with ||, &&, ===, and !== never invoke
+ * toString or valueOf.
+ */
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next)
+ ok &= CheckSideEffects(cx, cg, pn2, answer);
+ } else {
+ /*
+ * All invocation operations (construct: TOK_NEW, call: TOK_LP)
+ * are presumed to be useful, because they may have side effects
+ * even if their main effect (their return value) is discarded.
+ *
+ * TOK_LB binary trees of 3 or more nodes are flattened into lists
+ * to avoid too much recursion. All such lists must be presumed
+ * to be useful because each index operation could invoke a getter
+ * (the JSOP_ARGUMENTS special case below, in the PN_BINARY case,
+ * does not apply here: arguments[i][j] might invoke a getter).
+ *
+ * Likewise, array and object initialisers may call prototype
+ * setters (the __defineSetter__ built-in, and writable __proto__
+ * on Array.prototype create this hazard). Initialiser list nodes
+ * have JSOP_NEWINIT in their pn_op.
+ */
+ *answer = JS_TRUE;
+ }
+ break;
+
+ case PN_TERNARY:
+ ok = CheckSideEffects(cx, cg, pn->pn_kid1, answer) &&
+ CheckSideEffects(cx, cg, pn->pn_kid2, answer) &&
+ CheckSideEffects(cx, cg, pn->pn_kid3, answer);
+ break;
+
+ case PN_BINARY:
+ if (pn->pn_type == TOK_ASSIGN) {
+ /*
+ * Assignment is presumed to be useful, even if the next operation
+ * is another assignment overwriting this one's ostensible effect,
+ * because the left operand may be a property with a setter that
+ * has side effects.
+ *
+ * The only exception is assignment of a useless value to a const
+ * declared in the function currently being compiled.
+ */
+ pn2 = pn->pn_left;
+ if (pn2->pn_type != TOK_NAME) {
+ *answer = JS_TRUE;
+ } else {
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (!CheckSideEffects(cx, cg, pn->pn_right, answer))
+ return JS_FALSE;
+ if (!*answer &&
+ (pn->pn_op != JSOP_NOP ||
+ pn2->pn_slot < 0 ||
+ !pn2->pn_const)) {
+ *answer = JS_TRUE;
+ }
+ }
+ } else {
+ if (pn->pn_op == JSOP_OR || pn->pn_op == JSOP_AND ||
+ pn->pn_op == JSOP_STRICTEQ || pn->pn_op == JSOP_STRICTNE) {
+ /*
+ * ||, &&, ===, and !== do not convert their operands via
+ * toString or valueOf method calls.
+ */
+ ok = CheckSideEffects(cx, cg, pn->pn_left, answer) &&
+ CheckSideEffects(cx, cg, pn->pn_right, answer);
+ } else {
+ /*
+ * We can't easily prove that neither operand ever denotes an
+ * object with a toString or valueOf method.
+ */
+ *answer = JS_TRUE;
+ }
+ }
+ break;
+
+ case PN_UNARY:
+ switch (pn->pn_type) {
+ case TOK_RP:
+ ok = CheckSideEffects(cx, cg, pn->pn_kid, answer);
+ break;
+
+ case TOK_DELETE:
+ pn2 = pn->pn_kid;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ case TOK_DOT:
+#if JS_HAS_XML_SUPPORT
+ case TOK_DBLDOT:
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+#endif
+ case TOK_LB:
+ /* All these delete addressing modes have effects too. */
+ *answer = JS_TRUE;
+ break;
+ default:
+ ok = CheckSideEffects(cx, cg, pn2, answer);
+ break;
+ }
+ break;
+
+ case TOK_UNARYOP:
+ if (pn->pn_op == JSOP_NOT) {
+ /* ! does not convert its operand via toString or valueOf. */
+ ok = CheckSideEffects(cx, cg, pn->pn_kid, answer);
+ break;
+ }
+ /* FALL THROUGH */
+
+ default:
+ /*
+ * All of TOK_INC, TOK_DEC, TOK_THROW, TOK_YIELD, and TOK_DEFSHARP
+ * have direct effects. Of the remaining unary-arity node types,
+ * we can't easily prove that the operand never denotes an object
+ * with a toString or valueOf method.
+ */
+ *answer = JS_TRUE;
+ break;
+ }
+ break;
+
+ case PN_NAME:
+ /*
+ * Take care to avoid trying to bind a label name (labels, both for
+ * statements and property values in object initialisers, have pn_op
+ * defaulted to JSOP_NOP).
+ */
+ if (pn->pn_type == TOK_NAME && pn->pn_op != JSOP_NOP) {
+ if (!BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+ if (pn->pn_slot < 0 && pn->pn_op != JSOP_ARGUMENTS) {
+ /*
+ * Not an argument or local variable use, so this expression
+ * could invoke a getter that has side effects.
+ */
+ *answer = JS_TRUE;
+ }
+ }
+ pn2 = pn->pn_expr;
+ if (pn->pn_type == TOK_DOT) {
+ if (pn2->pn_type == TOK_NAME && !BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (!(pn2->pn_op == JSOP_ARGUMENTS &&
+ pn->pn_atom == cx->runtime->atomState.lengthAtom)) {
+ /*
+ * Any dotted property reference could call a getter, except
+ * for arguments.length where arguments is unambiguous.
+ */
+ *answer = JS_TRUE;
+ }
+ }
+ ok = CheckSideEffects(cx, cg, pn2, answer);
+ break;
+
+ case PN_NULLARY:
+ if (pn->pn_type == TOK_DEBUGGER)
+ *answer = JS_TRUE;
+ break;
+ }
+ return ok;
+}
+
+static JSBool
+EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSBool callContext)
+{
+ JSOp op;
+
+ if (!BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+ op = PN_OP(pn);
+
+ if (callContext) {
+ switch (op) {
+ case JSOP_NAME:
+ op = JSOP_CALLNAME;
+ break;
+ case JSOP_GETGVAR:
+ op = JSOP_CALLGVAR;
+ break;
+ case JSOP_GETARG:
+ op = JSOP_CALLARG;
+ break;
+ case JSOP_GETLOCAL:
+ op = JSOP_CALLLOCAL;
+ break;
+ case JSOP_GETUPVAR:
+ op = JSOP_CALLUPVAR;
+ break;
+ default:
+ JS_ASSERT(op == JSOP_ARGUMENTS);
+ break;
+ }
+ }
+
+ if (op == JSOP_ARGUMENTS) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ if (callContext && js_Emit1(cx, cg, JSOP_NULL) < 0)
+ return JS_FALSE;
+ } else {
+ if (pn->pn_slot >= 0) {
+ EMIT_UINT16_IMM_OP(op, pn->pn_slot);
+ } else {
+ if (!EmitAtomOp(cx, pn, op, cg))
+ return JS_FALSE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+#if JS_HAS_XML_SUPPORT
+static JSBool
+EmitXMLName(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
+{
+ JSParseNode *pn2;
+ uintN oldflags;
+
+ JS_ASSERT(pn->pn_type == TOK_UNARYOP);
+ JS_ASSERT(pn->pn_op == JSOP_XMLNAME);
+ JS_ASSERT(op == JSOP_XMLNAME || op == JSOP_CALLXMLNAME);
+
+ pn2 = pn->pn_kid;
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pn2->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+
+ return js_Emit1(cx, cg, op) >= 0;
+}
+#endif
+
+static JSBool
+EmitPropOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg,
+ JSBool callContext)
+{
+ JSParseNode *pn2, *pndot, *pnup, *pndown;
+ ptrdiff_t top;
+
+ pn2 = pn->pn_expr;
+ if (callContext) {
+ JS_ASSERT(pn->pn_type == TOK_DOT);
+ JS_ASSERT(op == JSOP_GETPROP);
+ op = JSOP_CALLPROP;
+ } else if (op == JSOP_GETPROP && pn->pn_type == TOK_DOT) {
+ if (pn2->pn_op == JSOP_THIS) {
+ if (pn->pn_atom != cx->runtime->atomState.lengthAtom) {
+ /* Fast path for gets of |this.foo|. */
+ return EmitAtomOp(cx, pn, JSOP_GETTHISPROP, cg);
+ }
+ } else if (pn2->pn_type == TOK_NAME) {
+ /*
+ * Try to optimize:
+ * - arguments.length into JSOP_ARGCNT
+ * - argname.prop into JSOP_GETARGPROP
+ * - localname.prop into JSOP_GETLOCALPROP
+ * but don't do this if the property is 'length' -- prefer to emit
+ * JSOP_GETARG, etc., and then JSOP_LENGTH.
+ */
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn->pn_atom == cx->runtime->atomState.lengthAtom) {
+ if (pn2->pn_op == JSOP_ARGUMENTS)
+ return js_Emit1(cx, cg, JSOP_ARGCNT) >= 0;
+ } else {
+ switch (pn2->pn_op) {
+ case JSOP_GETARG:
+ op = JSOP_GETARGPROP;
+ goto do_indexconst;
+ case JSOP_GETLOCAL:
+ op = JSOP_GETLOCALPROP;
+ do_indexconst: {
+ JSAtomListElement *ale;
+ jsatomid atomIndex;
+
+ ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ return EmitSlotIndexOp(cx, op, pn2->pn_slot, atomIndex, cg);
+ }
+
+ default:;
+ }
+ }
+ }
+ }
+
+ /*
+ * If the object operand is also a dotted property reference, reverse the
+ * list linked via pn_expr temporarily so we can iterate over it from the
+ * bottom up (reversing again as we go), to avoid excessive recursion.
+ */
+ if (pn2->pn_type == TOK_DOT) {
+ pndot = pn2;
+ pnup = NULL;
+ top = CG_OFFSET(cg);
+ for (;;) {
+ /* Reverse pndot->pn_expr to point up, not down. */
+ pndot->pn_offset = top;
+ pndown = pndot->pn_expr;
+ pndot->pn_expr = pnup;
+ if (pndown->pn_type != TOK_DOT)
+ break;
+ pnup = pndot;
+ pndot = pndown;
+ }
+
+ /* pndown is a primary expression, not a dotted property reference. */
+ if (!js_EmitTree(cx, cg, pndown))
+ return JS_FALSE;
+
+ do {
+ /* Walk back up the list, emitting annotated name ops. */
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pndown->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+ if (!EmitAtomOp(cx, pndot, PN_OP(pndot), cg))
+ return JS_FALSE;
+
+ /* Reverse the pn_expr link again. */
+ pnup = pndot->pn_expr;
+ pndot->pn_expr = pndown;
+ pndown = pndot;
+ } while ((pndot = pnup) != NULL);
+ } else {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pn2->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+
+ return EmitAtomOp(cx, pn, op, cg);
+}
+
+static JSBool
+EmitElemOp(JSContext *cx, JSParseNode *pn, JSOp op, JSCodeGenerator *cg)
+{
+ ptrdiff_t top;
+ JSParseNode *left, *right, *next, ltmp, rtmp;
+ jsint slot;
+
+ top = CG_OFFSET(cg);
+ if (pn->pn_arity == PN_LIST) {
+ /* Left-associative operator chain to avoid too much recursion. */
+ JS_ASSERT(pn->pn_op == JSOP_GETELEM);
+ JS_ASSERT(pn->pn_count >= 3);
+ left = pn->pn_head;
+ right = PN_LAST(pn);
+ next = left->pn_next;
+ JS_ASSERT(next != right);
+
+ /*
+ * Try to optimize arguments[0][j]... into JSOP_ARGSUB<0> followed by
+ * one or more index expression and JSOP_GETELEM op pairs.
+ */
+ if (left->pn_type == TOK_NAME && next->pn_type == TOK_NUMBER) {
+ if (!BindNameToSlot(cx, cg, left))
+ return JS_FALSE;
+ if (left->pn_op == JSOP_ARGUMENTS &&
+ JSDOUBLE_IS_INT(next->pn_dval, slot) &&
+ (jsuint)slot < JS_BIT(16)) {
+ /*
+ * arguments[i]() requires arguments object as "this".
+ * Check that we never generates list for that usage.
+ */
+ JS_ASSERT(op != JSOP_CALLELEM || next->pn_next);
+ left->pn_offset = next->pn_offset = top;
+ EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
+ left = next;
+ next = left->pn_next;
+ }
+ }
+
+ /*
+ * Check whether we generated JSOP_ARGSUB, just above, and have only
+ * one more index expression to emit. Given arguments[0][j], we must
+ * skip the while loop altogether, falling through to emit code for j
+ * (in the subtree referenced by right), followed by the annotated op,
+ * at the bottom of this function.
+ */
+ JS_ASSERT(next != right || pn->pn_count == 3);
+ if (left == pn->pn_head) {
+ if (!js_EmitTree(cx, cg, left))
+ return JS_FALSE;
+ }
+ while (next != right) {
+ if (!js_EmitTree(cx, cg, next))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
+ return JS_FALSE;
+ next = next->pn_next;
+ }
+ } else {
+ if (pn->pn_arity == PN_NAME) {
+ /*
+ * Set left and right so pn appears to be a TOK_LB node, instead
+ * of a TOK_DOT node. See the TOK_FOR/IN case in js_EmitTree, and
+ * EmitDestructuringOps nearer below. In the destructuring case,
+ * the base expression (pn_expr) of the name may be null, which
+ * means we have to emit a JSOP_BINDNAME.
+ */
+ left = pn->pn_expr;
+ if (!left) {
+ left = &ltmp;
+ left->pn_type = TOK_STRING;
+ left->pn_op = JSOP_BINDNAME;
+ left->pn_arity = PN_NULLARY;
+ left->pn_pos = pn->pn_pos;
+ left->pn_atom = pn->pn_atom;
+ }
+ right = &rtmp;
+ right->pn_type = TOK_STRING;
+ JS_ASSERT(ATOM_IS_STRING(pn->pn_atom));
+ right->pn_op = js_IsIdentifier(ATOM_TO_STRING(pn->pn_atom))
+ ? JSOP_QNAMEPART
+ : JSOP_STRING;
+ right->pn_arity = PN_NULLARY;
+ right->pn_pos = pn->pn_pos;
+ right->pn_atom = pn->pn_atom;
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_BINARY);
+ left = pn->pn_left;
+ right = pn->pn_right;
+ }
+
+ /* Try to optimize arguments[0] (e.g.) into JSOP_ARGSUB<0>. */
+ if (op == JSOP_GETELEM &&
+ left->pn_type == TOK_NAME &&
+ right->pn_type == TOK_NUMBER) {
+ if (!BindNameToSlot(cx, cg, left))
+ return JS_FALSE;
+ if (left->pn_op == JSOP_ARGUMENTS &&
+ JSDOUBLE_IS_INT(right->pn_dval, slot) &&
+ (jsuint)slot < JS_BIT(16)) {
+ left->pn_offset = right->pn_offset = top;
+ EMIT_UINT16_IMM_OP(JSOP_ARGSUB, (jsatomid)slot);
+ return JS_TRUE;
+ }
+ }
+
+ if (!js_EmitTree(cx, cg, left))
+ return JS_FALSE;
+ }
+
+ /* The right side of the descendant operator is implicitly quoted. */
+ JS_ASSERT(op != JSOP_DESCENDANTS || right->pn_type != TOK_STRING ||
+ right->pn_op == JSOP_QNAMEPART);
+ if (!js_EmitTree(cx, cg, right))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ return js_Emit1(cx, cg, op) >= 0;
+}
+
+static JSBool
+EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
+{
+ jsint ival;
+ uint32 u;
+ ptrdiff_t off;
+ jsbytecode *pc;
+ JSAtom *atom;
+ JSAtomListElement *ale;
+
+ if (JSDOUBLE_IS_INT(dval, ival) && INT_FITS_IN_JSVAL(ival)) {
+ if (ival == 0)
+ return js_Emit1(cx, cg, JSOP_ZERO) >= 0;
+ if (ival == 1)
+ return js_Emit1(cx, cg, JSOP_ONE) >= 0;
+ if ((jsint)(int8)ival == ival)
+ return js_Emit2(cx, cg, JSOP_INT8, (jsbytecode)(int8)ival) >= 0;
+
+ u = (uint32)ival;
+ if (u < JS_BIT(16)) {
+ EMIT_UINT16_IMM_OP(JSOP_UINT16, u);
+ } else if (u < JS_BIT(24)) {
+ off = js_EmitN(cx, cg, JSOP_UINT24, 3);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_UINT24(pc, u);
+ } else {
+ off = js_EmitN(cx, cg, JSOP_INT32, 4);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_INT32(pc, ival);
+ }
+ return JS_TRUE;
+ }
+
+ atom = js_AtomizeDouble(cx, dval);
+ if (!atom)
+ return JS_FALSE;
+
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ return EmitIndexOp(cx, JSOP_DOUBLE, ALE_INDEX(ale), cg);
+}
+
+static JSBool
+EmitSwitch(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSStmtInfo *stmtInfo)
+{
+ JSOp switchOp;
+ JSBool ok, hasDefault, constPropagated;
+ ptrdiff_t top, off, defaultOffset;
+ JSParseNode *pn2, *pn3, *pn4;
+ uint32 caseCount, tableLength;
+ JSParseNode **table;
+ jsdouble d;
+ jsint i, low, high;
+ jsval v;
+ JSAtom *atom;
+ JSAtomListElement *ale;
+ intN noteIndex;
+ size_t switchSize, tableSize;
+ jsbytecode *pc, *savepc;
+#if JS_HAS_BLOCK_SCOPE
+ jsint count;
+#endif
+
+ /* Try for most optimal, fall back if not dense ints, and per ECMAv2. */
+ switchOp = JSOP_TABLESWITCH;
+ ok = JS_TRUE;
+ hasDefault = constPropagated = JS_FALSE;
+ defaultOffset = -1;
+
+ /*
+ * If the switch contains let variables scoped by its body, model the
+ * resulting block on the stack first, before emitting the discriminant's
+ * bytecode (in case the discriminant contains a stack-model dependency
+ * such as a let expression).
+ */
+ pn2 = pn->pn_right;
+#if JS_HAS_BLOCK_SCOPE
+ if (pn2->pn_type == TOK_LEXICALSCOPE) {
+ /*
+ * Push the body's block scope before discriminant code-gen for proper
+ * static block scope linkage in case the discriminant contains a let
+ * expression. The block's locals must lie under the discriminant on
+ * the stack so that case-dispatch bytecodes can find the discriminant
+ * on top of stack.
+ */
+ count = OBJ_BLOCK_COUNT(cx, pn2->pn_pob->object);
+ js_PushBlockScope(&cg->treeContext, stmtInfo, pn2->pn_pob->object, -1);
+ stmtInfo->type = STMT_SWITCH;
+
+ /* Emit JSOP_ENTERBLOCK before code to evaluate the discriminant. */
+ if (!EmitObjectOp(cx, pn2->pn_pob, JSOP_ENTERBLOCK, cg))
+ return JS_FALSE;
+
+ /*
+ * Pop the switch's statement info around discriminant code-gen. Note
+ * how this leaves cg->treeContext.blockChain referencing the switch's
+ * block scope object, which is necessary for correct block parenting
+ * in the case where the discriminant contains a let expression.
+ */
+ cg->treeContext.topStmt = stmtInfo->down;
+ cg->treeContext.topScopeStmt = stmtInfo->downScope;
+ }
+#ifdef __GNUC__
+ else {
+ count = 0;
+ }
+#endif
+#endif
+
+ /*
+ * Emit code for the discriminant first (or nearly first, in the case of a
+ * switch whose body is a block scope).
+ */
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+
+ /* Switch bytecodes run from here till end of final case. */
+ top = CG_OFFSET(cg);
+#if !JS_HAS_BLOCK_SCOPE
+ js_PushStatement(&cg->treeContext, stmtInfo, STMT_SWITCH, top);
+#else
+ if (pn2->pn_type == TOK_LC) {
+ js_PushStatement(&cg->treeContext, stmtInfo, STMT_SWITCH, top);
+ } else {
+ /* Re-push the switch's statement info record. */
+ cg->treeContext.topStmt = cg->treeContext.topScopeStmt = stmtInfo;
+
+ /* Set the statement info record's idea of top. */
+ stmtInfo->update = top;
+
+ /* Advance pn2 to refer to the switch case list. */
+ pn2 = pn2->pn_expr;
+ }
+#endif
+
+ caseCount = pn2->pn_count;
+ tableLength = 0;
+ table = NULL;
+
+ if (caseCount == 0 ||
+ (caseCount == 1 &&
+ (hasDefault = (pn2->pn_head->pn_type == TOK_DEFAULT)))) {
+ caseCount = 0;
+ low = 0;
+ high = -1;
+ } else {
+#define INTMAP_LENGTH 256
+ jsbitmap intmap_space[INTMAP_LENGTH];
+ jsbitmap *intmap = NULL;
+ int32 intmap_bitlen = 0;
+
+ low = JSVAL_INT_MAX;
+ high = JSVAL_INT_MIN;
+
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (pn3->pn_type == TOK_DEFAULT) {
+ hasDefault = JS_TRUE;
+ caseCount--; /* one of the "cases" was the default */
+ continue;
+ }
+
+ JS_ASSERT(pn3->pn_type == TOK_CASE);
+ if (switchOp == JSOP_CONDSWITCH)
+ continue;
+
+ pn4 = pn3->pn_left;
+ switch (pn4->pn_type) {
+ case TOK_NUMBER:
+ d = pn4->pn_dval;
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
+ pn3->pn_val = INT_TO_JSVAL(i);
+ } else {
+ atom = js_AtomizeDouble(cx, d);
+ if (!atom) {
+ ok = JS_FALSE;
+ goto release;
+ }
+ pn3->pn_val = ATOM_KEY(atom);
+ }
+ break;
+ case TOK_STRING:
+ pn3->pn_val = ATOM_KEY(pn4->pn_atom);
+ break;
+ case TOK_NAME:
+ if (!pn4->pn_expr) {
+ ok = LookupCompileTimeConstant(cx, cg, pn4->pn_atom, &v);
+ if (!ok)
+ goto release;
+ if (v != JSVAL_HOLE) {
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ /*
+ * XXX JSOP_LOOKUPSWITCH does not support const-
+ * propagated object values, see bug 407186.
+ */
+ switchOp = JSOP_CONDSWITCH;
+ continue;
+ }
+ pn3->pn_val = v;
+ constPropagated = JS_TRUE;
+ break;
+ }
+ }
+ /* FALL THROUGH */
+ case TOK_PRIMARY:
+ if (pn4->pn_op == JSOP_TRUE) {
+ pn3->pn_val = JSVAL_TRUE;
+ break;
+ }
+ if (pn4->pn_op == JSOP_FALSE) {
+ pn3->pn_val = JSVAL_FALSE;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ switchOp = JSOP_CONDSWITCH;
+ continue;
+ }
+
+ JS_ASSERT(JSVAL_IS_PRIMITIVE(pn3->pn_val));
+
+ if (switchOp != JSOP_TABLESWITCH)
+ continue;
+ if (!JSVAL_IS_INT(pn3->pn_val)) {
+ switchOp = JSOP_LOOKUPSWITCH;
+ continue;
+ }
+ i = JSVAL_TO_INT(pn3->pn_val);
+ if ((jsuint)(i + (jsint)JS_BIT(15)) >= (jsuint)JS_BIT(16)) {
+ switchOp = JSOP_LOOKUPSWITCH;
+ continue;
+ }
+ if (i < low)
+ low = i;
+ if (high < i)
+ high = i;
+
+ /*
+ * Check for duplicates, which require a JSOP_LOOKUPSWITCH.
+ * We bias i by 65536 if it's negative, and hope that's a rare
+ * case (because it requires a malloc'd bitmap).
+ */
+ if (i < 0)
+ i += JS_BIT(16);
+ if (i >= intmap_bitlen) {
+ if (!intmap &&
+ i < (INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2)) {
+ intmap = intmap_space;
+ intmap_bitlen = INTMAP_LENGTH << JS_BITS_PER_WORD_LOG2;
+ } else {
+ /* Just grab 8K for the worst-case bitmap. */
+ intmap_bitlen = JS_BIT(16);
+ intmap = (jsbitmap *)
+ JS_malloc(cx,
+ (JS_BIT(16) >> JS_BITS_PER_WORD_LOG2)
+ * sizeof(jsbitmap));
+ if (!intmap) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ }
+ memset(intmap, 0, intmap_bitlen >> JS_BITS_PER_BYTE_LOG2);
+ }
+ if (JS_TEST_BIT(intmap, i)) {
+ switchOp = JSOP_LOOKUPSWITCH;
+ continue;
+ }
+ JS_SET_BIT(intmap, i);
+ }
+
+ release:
+ if (intmap && intmap != intmap_space)
+ JS_free(cx, intmap);
+ if (!ok)
+ return JS_FALSE;
+
+ /*
+ * Compute table length and select lookup instead if overlarge or
+ * more than half-sparse.
+ */
+ if (switchOp == JSOP_TABLESWITCH) {
+ tableLength = (uint32)(high - low + 1);
+ if (tableLength >= JS_BIT(16) || tableLength > 2 * caseCount)
+ switchOp = JSOP_LOOKUPSWITCH;
+ } else if (switchOp == JSOP_LOOKUPSWITCH) {
+ /*
+ * Lookup switch supports only atom indexes below 64K limit.
+ * Conservatively estimate the maximum possible index during
+ * switch generation and use conditional switch if it exceeds
+ * the limit.
+ */
+ if (caseCount + cg->atomList.count > JS_BIT(16))
+ switchOp = JSOP_CONDSWITCH;
+ }
+ }
+
+ /*
+ * Emit a note with two offsets: first tells total switch code length,
+ * second tells offset to first JSOP_CASE if condswitch.
+ */
+ noteIndex = js_NewSrcNote3(cx, cg, SRC_SWITCH, 0, 0);
+ if (noteIndex < 0)
+ return JS_FALSE;
+
+ if (switchOp == JSOP_CONDSWITCH) {
+ /*
+ * 0 bytes of immediate for unoptimized ECMAv2 switch.
+ */
+ switchSize = 0;
+ } else if (switchOp == JSOP_TABLESWITCH) {
+ /*
+ * 3 offsets (len, low, high) before the table, 1 per entry.
+ */
+ switchSize = (size_t)(JUMP_OFFSET_LEN * (3 + tableLength));
+ } else {
+ /*
+ * JSOP_LOOKUPSWITCH:
+ * 1 offset (len) and 1 atom index (npairs) before the table,
+ * 1 atom index and 1 jump offset per entry.
+ */
+ switchSize = (size_t)(JUMP_OFFSET_LEN + INDEX_LEN +
+ (INDEX_LEN + JUMP_OFFSET_LEN) * caseCount);
+ }
+
+ /*
+ * Emit switchOp followed by switchSize bytes of jump or lookup table.
+ *
+ * If switchOp is JSOP_LOOKUPSWITCH or JSOP_TABLESWITCH, it is crucial
+ * to emit the immediate operand(s) by which bytecode readers such as
+ * BuildSpanDepTable discover the length of the switch opcode *before*
+ * calling js_SetJumpOffset (which may call BuildSpanDepTable). It's
+ * also important to zero all unknown jump offset immediate operands,
+ * so they can be converted to span dependencies with null targets to
+ * be computed later (js_EmitN zeros switchSize bytes after switchOp).
+ */
+ if (js_EmitN(cx, cg, switchOp, switchSize) < 0)
+ return JS_FALSE;
+
+ off = -1;
+ if (switchOp == JSOP_CONDSWITCH) {
+ intN caseNoteIndex = -1;
+ JSBool beforeCases = JS_TRUE;
+
+ /* Emit code for evaluating cases and jumping to case statements. */
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ pn4 = pn3->pn_left;
+ if (pn4 && !js_EmitTree(cx, cg, pn4))
+ return JS_FALSE;
+ if (caseNoteIndex >= 0) {
+ /* off is the previous JSOP_CASE's bytecode offset. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0,
+ CG_OFFSET(cg) - off)) {
+ return JS_FALSE;
+ }
+ }
+ if (!pn4) {
+ JS_ASSERT(pn3->pn_type == TOK_DEFAULT);
+ continue;
+ }
+ caseNoteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (caseNoteIndex < 0)
+ return JS_FALSE;
+ off = EmitJump(cx, cg, JSOP_CASE, 0);
+ if (off < 0)
+ return JS_FALSE;
+ pn3->pn_offset = off;
+ if (beforeCases) {
+ uintN noteCount, noteCountDelta;
+
+ /* Switch note's second offset is to first JSOP_CASE. */
+ noteCount = CG_NOTE_COUNT(cg);
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
+ off - top)) {
+ return JS_FALSE;
+ }
+ noteCountDelta = CG_NOTE_COUNT(cg) - noteCount;
+ if (noteCountDelta != 0)
+ caseNoteIndex += noteCountDelta;
+ beforeCases = JS_FALSE;
+ }
+ }
+
+ /*
+ * If we didn't have an explicit default (which could fall in between
+ * cases, preventing us from fusing this js_SetSrcNoteOffset with the
+ * call in the loop above), link the last case to the implicit default
+ * for the decompiler.
+ */
+ if (!hasDefault &&
+ caseNoteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)caseNoteIndex, 0,
+ CG_OFFSET(cg) - off)) {
+ return JS_FALSE;
+ }
+
+ /* Emit default even if no explicit default statement. */
+ defaultOffset = EmitJump(cx, cg, JSOP_DEFAULT, 0);
+ if (defaultOffset < 0)
+ return JS_FALSE;
+ } else {
+ pc = CG_CODE(cg, top + JUMP_OFFSET_LEN);
+
+ if (switchOp == JSOP_TABLESWITCH) {
+ /* Fill in switch bounds, which we know fit in 16-bit offsets. */
+ SET_JUMP_OFFSET(pc, low);
+ pc += JUMP_OFFSET_LEN;
+ SET_JUMP_OFFSET(pc, high);
+ pc += JUMP_OFFSET_LEN;
+
+ /*
+ * Use malloc to avoid arena bloat for programs with many switches.
+ * We free table if non-null at label out, so all control flow must
+ * exit this function through goto out or goto bad.
+ */
+ if (tableLength != 0) {
+ tableSize = (size_t)tableLength * sizeof *table;
+ table = (JSParseNode **) JS_malloc(cx, tableSize);
+ if (!table)
+ return JS_FALSE;
+ memset(table, 0, tableSize);
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (pn3->pn_type == TOK_DEFAULT)
+ continue;
+ i = JSVAL_TO_INT(pn3->pn_val);
+ i -= low;
+ JS_ASSERT((uint32)i < tableLength);
+ table[i] = pn3;
+ }
+ }
+ } else {
+ JS_ASSERT(switchOp == JSOP_LOOKUPSWITCH);
+
+ /* Fill in the number of cases. */
+ SET_INDEX(pc, caseCount);
+ pc += INDEX_LEN;
+ }
+
+ /*
+ * After this point, all control flow involving JSOP_TABLESWITCH
+ * must set ok and goto out to exit this function. To keep things
+ * simple, all switchOp cases exit that way.
+ */
+ MUST_FLOW_THROUGH("out");
+ if (cg->spanDeps) {
+ /*
+ * We have already generated at least one big jump so we must
+ * explicitly add span dependencies for the switch jumps. When
+ * called below, js_SetJumpOffset can only do it when patching
+ * the first big jump or when cg->spanDeps is null.
+ */
+ if (!AddSwitchSpanDeps(cx, cg, CG_CODE(cg, top)))
+ goto bad;
+ }
+
+ if (constPropagated) {
+ /*
+ * Skip switchOp, as we are not setting jump offsets in the two
+ * for loops below. We'll restore CG_NEXT(cg) from savepc after,
+ * unless there was an error.
+ */
+ savepc = CG_NEXT(cg);
+ CG_NEXT(cg) = pc + 1;
+ if (switchOp == JSOP_TABLESWITCH) {
+ for (i = 0; i < (jsint)tableLength; i++) {
+ pn3 = table[i];
+ if (pn3 &&
+ (pn4 = pn3->pn_left) != NULL &&
+ pn4->pn_type == TOK_NAME) {
+ /* Note a propagated constant with the const's name. */
+ JS_ASSERT(!pn4->pn_expr);
+ ale = js_IndexAtom(cx, pn4->pn_atom, &cg->atomList);
+ if (!ale)
+ goto bad;
+ CG_NEXT(cg) = pc;
+ if (js_NewSrcNote2(cx, cg, SRC_LABEL, (ptrdiff_t)
+ ALE_INDEX(ale)) < 0) {
+ goto bad;
+ }
+ }
+ pc += JUMP_OFFSET_LEN;
+ }
+ } else {
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ pn4 = pn3->pn_left;
+ if (pn4 && pn4->pn_type == TOK_NAME) {
+ /* Note a propagated constant with the const's name. */
+ JS_ASSERT(!pn4->pn_expr);
+ ale = js_IndexAtom(cx, pn4->pn_atom, &cg->atomList);
+ if (!ale)
+ goto bad;
+ CG_NEXT(cg) = pc;
+ if (js_NewSrcNote2(cx, cg, SRC_LABEL, (ptrdiff_t)
+ ALE_INDEX(ale)) < 0) {
+ goto bad;
+ }
+ }
+ pc += INDEX_LEN + JUMP_OFFSET_LEN;
+ }
+ }
+ CG_NEXT(cg) = savepc;
+ }
+ }
+
+ /* Emit code for each case's statements, copying pn_offset up to pn3. */
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (switchOp == JSOP_CONDSWITCH && pn3->pn_type != TOK_DEFAULT)
+ CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, pn3->pn_offset, goto bad);
+ pn4 = pn3->pn_right;
+ ok = js_EmitTree(cx, cg, pn4);
+ if (!ok)
+ goto out;
+ pn3->pn_offset = pn4->pn_offset;
+ if (pn3->pn_type == TOK_DEFAULT)
+ off = pn3->pn_offset - top;
+ }
+
+ if (!hasDefault) {
+ /* If no default case, offset for default is to end of switch. */
+ off = CG_OFFSET(cg) - top;
+ }
+
+ /* We better have set "off" by now. */
+ JS_ASSERT(off != -1);
+
+ /* Set the default offset (to end of switch if no default). */
+ if (switchOp == JSOP_CONDSWITCH) {
+ pc = NULL;
+ JS_ASSERT(defaultOffset != -1);
+ ok = js_SetJumpOffset(cx, cg, CG_CODE(cg, defaultOffset),
+ off - (defaultOffset - top));
+ if (!ok)
+ goto out;
+ } else {
+ pc = CG_CODE(cg, top);
+ ok = js_SetJumpOffset(cx, cg, pc, off);
+ if (!ok)
+ goto out;
+ pc += JUMP_OFFSET_LEN;
+ }
+
+ /* Set the SRC_SWITCH note's offset operand to tell end of switch. */
+ off = CG_OFFSET(cg) - top;
+ ok = js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, off);
+ if (!ok)
+ goto out;
+
+ if (switchOp == JSOP_TABLESWITCH) {
+ /* Skip over the already-initialized switch bounds. */
+ pc += 2 * JUMP_OFFSET_LEN;
+
+ /* Fill in the jump table, if there is one. */
+ for (i = 0; i < (jsint)tableLength; i++) {
+ pn3 = table[i];
+ off = pn3 ? pn3->pn_offset - top : 0;
+ ok = js_SetJumpOffset(cx, cg, pc, off);
+ if (!ok)
+ goto out;
+ pc += JUMP_OFFSET_LEN;
+ }
+ } else if (switchOp == JSOP_LOOKUPSWITCH) {
+ /* Skip over the already-initialized number of cases. */
+ pc += INDEX_LEN;
+
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ if (pn3->pn_type == TOK_DEFAULT)
+ continue;
+ if (!js_AtomizePrimitiveValue(cx, pn3->pn_val, &atom))
+ goto bad;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ goto bad;
+ SET_INDEX(pc, ALE_INDEX(ale));
+ pc += INDEX_LEN;
+
+ off = pn3->pn_offset - top;
+ ok = js_SetJumpOffset(cx, cg, pc, off);
+ if (!ok)
+ goto out;
+ pc += JUMP_OFFSET_LEN;
+ }
+ }
+
+out:
+ if (table)
+ JS_free(cx, table);
+ if (ok) {
+ ok = js_PopStatementCG(cx, cg);
+
+#if JS_HAS_BLOCK_SCOPE
+ if (ok && pn->pn_right->pn_type == TOK_LEXICALSCOPE)
+ EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, count);
+#endif
+ }
+ return ok;
+
+bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+JSBool
+js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body)
+{
+ if (cg->treeContext.flags & TCF_FUN_IS_GENERATOR) {
+ /* JSOP_GENERATOR must be the first instruction. */
+ CG_SWITCH_TO_PROLOG(cg);
+ JS_ASSERT(CG_NEXT(cg) == CG_BASE(cg));
+ if (js_Emit1(cx, cg, JSOP_GENERATOR) < 0)
+ return JS_FALSE;
+ CG_SWITCH_TO_MAIN(cg);
+ }
+
+ return js_EmitTree(cx, cg, body) &&
+ js_Emit1(cx, cg, JSOP_STOP) >= 0 &&
+ js_NewScriptFromCG(cx, cg);
+}
+
+/* A macro for inlining at the top of js_EmitTree (whence it came). */
+#define UPDATE_LINE_NUMBER_NOTES(cx, cg, pn) \
+ JS_BEGIN_MACRO \
+ uintN line_ = (pn)->pn_pos.begin.lineno; \
+ uintN delta_ = line_ - CG_CURRENT_LINE(cg); \
+ if (delta_ != 0) { \
+ /* \
+ * Encode any change in the current source line number by using \
+ * either several SRC_NEWLINE notes or just one SRC_SETLINE note, \
+ * whichever consumes less space. \
+ * \
+ * NB: We handle backward line number deltas (possible with for \
+ * loops where the update part is emitted after the body, but its \
+ * line number is <= any line number in the body) here by letting \
+ * unsigned delta_ wrap to a very large number, which triggers a \
+ * SRC_SETLINE. \
+ */ \
+ CG_CURRENT_LINE(cg) = line_; \
+ if (delta_ >= (uintN)(2 + ((line_ > SN_3BYTE_OFFSET_MASK)<<1))) { \
+ if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)line_) < 0)\
+ return JS_FALSE; \
+ } else { \
+ do { \
+ if (js_NewSrcNote(cx, cg, SRC_NEWLINE) < 0) \
+ return JS_FALSE; \
+ } while (--delta_ != 0); \
+ } \
+ } \
+ JS_END_MACRO
+
+/* A function, so that we avoid macro-bloating all the other callsites. */
+static JSBool
+UpdateLineNumberNotes(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ UPDATE_LINE_NUMBER_NOTES(cx, cg, pn);
+ return JS_TRUE;
+}
+
+static JSBool
+MaybeEmitVarDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn, jsatomid *result)
+{
+ jsatomid atomIndex;
+ JSAtomListElement *ale;
+
+ if (pn->pn_slot >= 0) {
+ atomIndex = (jsatomid) pn->pn_slot;
+ } else {
+ ale = js_IndexAtom(cx, pn->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ }
+
+ if (JOF_OPTYPE(pn->pn_op) == JOF_ATOM &&
+ (!(cg->treeContext.flags & TCF_IN_FUNCTION) ||
+ (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT))) {
+ /* Emit a prolog bytecode to predefine the variable. */
+ CG_SWITCH_TO_PROLOG(cg);
+ if (!UpdateLineNumberNotes(cx, cg, pn))
+ return JS_FALSE;
+ EMIT_INDEX_OP(prologOp, atomIndex);
+ CG_SWITCH_TO_MAIN(cg);
+ }
+
+ if (result)
+ *result = atomIndex;
+ return JS_TRUE;
+}
+
+#if JS_HAS_DESTRUCTURING
+
+typedef JSBool
+(*DestructuringDeclEmitter)(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn);
+
+static JSBool
+EmitDestructuringDecl(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn)
+{
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ if (!BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+
+ JS_ASSERT(pn->pn_op != JSOP_ARGUMENTS);
+ return MaybeEmitVarDecl(cx, cg, prologOp, pn, NULL);
+}
+
+static JSBool
+EmitDestructuringDecls(JSContext *cx, JSCodeGenerator *cg, JSOp prologOp,
+ JSParseNode *pn)
+{
+ JSParseNode *pn2, *pn3;
+ DestructuringDeclEmitter emitter;
+
+ if (pn->pn_type == TOK_RB) {
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_COMMA)
+ continue;
+ emitter = (pn2->pn_type == TOK_NAME)
+ ? EmitDestructuringDecl
+ : EmitDestructuringDecls;
+ if (!emitter(cx, cg, prologOp, pn2))
+ return JS_FALSE;
+ }
+ } else {
+ JS_ASSERT(pn->pn_type == TOK_RC);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ pn3 = pn2->pn_right;
+ emitter = (pn3->pn_type == TOK_NAME)
+ ? EmitDestructuringDecl
+ : EmitDestructuringDecls;
+ if (!emitter(cx, cg, prologOp, pn3))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
+
+static JSBool
+EmitDestructuringLHS(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ jsuint slot;
+
+ /* Skip any parenthesization. */
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+
+ /*
+ * Now emit the lvalue opcode sequence. If the lvalue is a nested
+ * destructuring initialiser-form, call ourselves to handle it, then
+ * pop the matched value. Otherwise emit an lvalue bytecode sequence
+ * ending with a JSOP_ENUMELEM or equivalent op.
+ */
+ if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
+ if (!EmitDestructuringOpsHelper(cx, cg, pn))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else {
+ if (pn->pn_type == TOK_NAME && !BindNameToSlot(cx, cg, pn))
+ return JS_FALSE;
+
+ switch (pn->pn_op) {
+ case JSOP_SETNAME:
+ /*
+ * NB: pn is a PN_NAME node, not a PN_BINARY. Nevertheless,
+ * we want to emit JSOP_ENUMELEM, which has format JOF_ELEM.
+ * So here and for JSOP_ENUMCONSTELEM, we use EmitElemOp.
+ */
+ if (!EmitElemOp(cx, pn, JSOP_ENUMELEM, cg))
+ return JS_FALSE;
+ break;
+
+ case JSOP_SETCONST:
+ if (!EmitElemOp(cx, pn, JSOP_ENUMCONSTELEM, cg))
+ return JS_FALSE;
+ break;
+
+ case JSOP_SETLOCAL:
+ slot = (jsuint) pn->pn_slot;
+ EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, slot);
+ break;
+
+ case JSOP_SETARG:
+ case JSOP_SETGVAR:
+ slot = (jsuint) pn->pn_slot;
+ EMIT_UINT16_IMM_OP(PN_OP(pn), slot);
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ break;
+
+ default:
+#if JS_HAS_LVALUE_RETURN || JS_HAS_XML_SUPPORT
+ {
+ ptrdiff_t top;
+
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif
+ case JSOP_ENUMELEM:
+ JS_ASSERT(0);
+ }
+ }
+
+ return JS_TRUE;
+}
+
+/*
+ * Recursive helper for EmitDestructuringOps.
+ *
+ * Given a value to destructure on the stack, walk over an object or array
+ * initialiser at pn, emitting bytecodes to match property values and store
+ * them in the lvalues identified by the matched property names.
+ */
+static JSBool
+EmitDestructuringOpsHelper(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ jsuint index;
+ JSParseNode *pn2, *pn3;
+ JSBool doElemOp;
+
+#ifdef DEBUG
+ intN stackDepth = cg->stackDepth;
+ JS_ASSERT(stackDepth != 0);
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ JS_ASSERT(pn->pn_type == TOK_RB || pn->pn_type == TOK_RC);
+#endif
+
+ if (pn->pn_count == 0) {
+ /* Emit a DUP;POP sequence for the decompiler. */
+ return js_Emit1(cx, cg, JSOP_DUP) >= 0 &&
+ js_Emit1(cx, cg, JSOP_POP) >= 0;
+ }
+
+ index = 0;
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ /*
+ * Duplicate the value being destructured to use as a reference base.
+ */
+ if (js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+
+ /*
+ * Now push the property name currently being matched, which is either
+ * the array initialiser's current index, or the current property name
+ * "label" on the left of a colon in the object initialiser. Set pn3
+ * to the lvalue node, which is in the value-initializing position.
+ */
+ doElemOp = JS_TRUE;
+ if (pn->pn_type == TOK_RB) {
+ if (!EmitNumberOp(cx, index, cg))
+ return JS_FALSE;
+ pn3 = pn2;
+ } else {
+ JS_ASSERT(pn->pn_type == TOK_RC);
+ JS_ASSERT(pn2->pn_type == TOK_COLON);
+ pn3 = pn2->pn_left;
+ if (pn3->pn_type == TOK_NUMBER) {
+ /*
+ * If we are emitting an object destructuring initialiser,
+ * annotate the index op with SRC_INITPROP so we know we are
+ * not decompiling an array initialiser.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_INITPROP) < 0)
+ return JS_FALSE;
+ if (!EmitNumberOp(cx, pn3->pn_dval, cg))
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(pn3->pn_type == TOK_STRING ||
+ pn3->pn_type == TOK_NAME);
+ if (!EmitAtomOp(cx, pn3, JSOP_GETPROP, cg))
+ return JS_FALSE;
+ doElemOp = JS_FALSE;
+ }
+ pn3 = pn2->pn_right;
+ }
+
+ if (doElemOp) {
+ /*
+ * Ok, get the value of the matching property name. This leaves
+ * that value on top of the value being destructured, so the stack
+ * is one deeper than when we started.
+ */
+ if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
+ return JS_FALSE;
+ JS_ASSERT(cg->stackDepth == stackDepth + 1);
+ }
+
+ /* Nullary comma node makes a hole in the array destructurer. */
+ if (pn3->pn_type == TOK_COMMA && pn3->pn_arity == PN_NULLARY) {
+ JS_ASSERT(pn->pn_type == TOK_RB);
+ JS_ASSERT(pn2 == pn3);
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else {
+ if (!EmitDestructuringLHS(cx, cg, pn3))
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(cg->stackDepth == stackDepth);
+ ++index;
+ }
+
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+OpToDeclType(JSOp op)
+{
+ switch (op) {
+ case JSOP_NOP:
+ return SRC_DECL_LET;
+ case JSOP_DEFCONST:
+ return SRC_DECL_CONST;
+ case JSOP_DEFVAR:
+ return SRC_DECL_VAR;
+ default:
+ return SRC_DECL_NONE;
+ }
+}
+
+static JSBool
+EmitDestructuringOps(JSContext *cx, JSCodeGenerator *cg, JSOp declOp,
+ JSParseNode *pn)
+{
+ /*
+ * If we're called from a variable declaration, help the decompiler by
+ * annotating the first JSOP_DUP that EmitDestructuringOpsHelper emits.
+ * If the destructuring initialiser is empty, our helper will emit a
+ * JSOP_DUP followed by a JSOP_POP for the decompiler.
+ */
+ if (js_NewSrcNote2(cx, cg, SRC_DESTRUCT, OpToDeclType(declOp)) < 0)
+ return JS_FALSE;
+
+ /*
+ * Call our recursive helper to emit the destructuring assignments and
+ * related stack manipulations.
+ */
+ return EmitDestructuringOpsHelper(cx, cg, pn);
+}
+
+static JSBool
+EmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp declOp,
+ JSParseNode *lhs, JSParseNode *rhs)
+{
+ jsuint depth, limit, i, nslots;
+ JSParseNode *pn;
+
+ depth = limit = (uintN) cg->stackDepth;
+ for (pn = rhs->pn_head; pn; pn = pn->pn_next) {
+ if (limit == JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), rhs, JSREPORT_ERROR,
+ JSMSG_ARRAY_INIT_TOO_BIG);
+ return JS_FALSE;
+ }
+
+ if (pn->pn_type == TOK_COMMA) {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(pn->pn_type != TOK_DEFSHARP);
+ if (!js_EmitTree(cx, cg, pn))
+ return JS_FALSE;
+ }
+ ++limit;
+ }
+
+ if (js_NewSrcNote2(cx, cg, SRC_GROUPASSIGN, OpToDeclType(declOp)) < 0)
+ return JS_FALSE;
+
+ i = depth;
+ for (pn = lhs->pn_head; pn; pn = pn->pn_next, ++i) {
+ if (i < limit) {
+ jsint slot;
+
+ slot = AdjustBlockSlot(cx, cg, i);
+ if (slot < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_GETLOCAL, slot);
+ } else {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ }
+ if (pn->pn_type == TOK_COMMA && pn->pn_arity == PN_NULLARY) {
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else {
+ if (!EmitDestructuringLHS(cx, cg, pn))
+ return JS_FALSE;
+ }
+ }
+
+ nslots = limit - depth;
+ EMIT_UINT16_IMM_OP(JSOP_POPN, nslots);
+ cg->stackDepth = (uintN) depth;
+ return JS_TRUE;
+}
+
+/*
+ * Helper called with pop out param initialized to a JSOP_POP* opcode. If we
+ * can emit a group assignment sequence, which results in 0 stack depth delta,
+ * we set *pop to JSOP_NOP so callers can veto emitting pn followed by a pop.
+ */
+static JSBool
+MaybeEmitGroupAssignment(JSContext *cx, JSCodeGenerator *cg, JSOp declOp,
+ JSParseNode *pn, JSOp *pop)
+{
+ JSParseNode *lhs, *rhs;
+
+ JS_ASSERT(pn->pn_type == TOK_ASSIGN);
+ JS_ASSERT(*pop == JSOP_POP || *pop == JSOP_POPV);
+ lhs = pn->pn_left;
+ rhs = pn->pn_right;
+ if (lhs->pn_type == TOK_RB && rhs->pn_type == TOK_RB &&
+ lhs->pn_count <= rhs->pn_count &&
+ (rhs->pn_count == 0 ||
+ rhs->pn_head->pn_type != TOK_DEFSHARP)) {
+ if (!EmitGroupAssignment(cx, cg, declOp, lhs, rhs))
+ return JS_FALSE;
+ *pop = JSOP_NOP;
+ }
+ return JS_TRUE;
+}
+
+#endif /* JS_HAS_DESTRUCTURING */
+
+static JSBool
+EmitVariables(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
+ JSBool inLetHead, ptrdiff_t *headNoteIndex)
+{
+ JSTreeContext *tc;
+ JSBool let, forInVar;
+#if JS_HAS_BLOCK_SCOPE
+ JSBool forInLet, popScope;
+ JSStmtInfo *stmt, *scopeStmt;
+#endif
+ ptrdiff_t off, noteIndex, tmp;
+ JSParseNode *pn2, *pn3;
+ JSOp op;
+ jsatomid atomIndex;
+ uintN oldflags;
+
+ /* Default in case of JS_HAS_BLOCK_SCOPE early return, below. */
+ *headNoteIndex = -1;
+
+ /*
+ * Let blocks and expressions have a parenthesized head in which the new
+ * scope is not yet open. Initializer evaluation uses the parent node's
+ * lexical scope. If popScope is true below, then we hide the top lexical
+ * block from any calls to BindNameToSlot hiding in pn2->pn_expr so that
+ * it won't find any names in the new let block.
+ *
+ * The same goes for let declarations in the head of any kind of for loop.
+ * Unlike a let declaration 'let x = i' within a block, where x is hoisted
+ * to the start of the block, a 'for (let x = i...) ...' loop evaluates i
+ * in the containing scope, and puts x in the loop body's scope.
+ */
+ tc = &cg->treeContext;
+ let = (pn->pn_op == JSOP_NOP);
+ forInVar = (pn->pn_extra & PNX_FORINVAR) != 0;
+#if JS_HAS_BLOCK_SCOPE
+ forInLet = let && forInVar;
+ popScope = (inLetHead || (let && (tc->flags & TCF_IN_FOR_INIT)));
+ JS_ASSERT(!popScope || let);
+#endif
+
+ off = noteIndex = -1;
+ for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {
+#if JS_HAS_DESTRUCTURING
+ if (pn2->pn_type != TOK_NAME) {
+ if (pn2->pn_type == TOK_RB || pn2->pn_type == TOK_RC) {
+ /*
+ * Emit variable binding ops, but not destructuring ops.
+ * The parser (see Variables, jsparse.c) has ensured that
+ * our caller will be the TOK_FOR/TOK_IN case in js_EmitTree,
+ * and that case will emit the destructuring code only after
+ * emitting an enumerating opcode and a branch that tests
+ * whether the enumeration ended.
+ */
+ JS_ASSERT(forInVar);
+ JS_ASSERT(pn->pn_count == 1);
+ if (!EmitDestructuringDecls(cx, cg, PN_OP(pn), pn2))
+ return JS_FALSE;
+ break;
+ }
+
+ /*
+ * A destructuring initialiser assignment preceded by var will
+ * never occur to the left of 'in' in a for-in loop. As with 'for
+ * (var x = i in o)...', this will cause the entire 'var [a, b] =
+ * i' to be hoisted out of the loop.
+ */
+ JS_ASSERT(pn2->pn_type == TOK_ASSIGN);
+ JS_ASSERT(!forInVar);
+ if (pn->pn_count == 1) {
+ /*
+ * If this is the only destructuring assignment in the list,
+ * try to optimize to a group assignment. If we're in a let
+ * head, pass JSOP_POP rather than the pseudo-prolog JSOP_NOP
+ * in pn->pn_op, to suppress a second (and misplaced) 'let'.
+ */
+ JS_ASSERT(noteIndex < 0 && !pn2->pn_next);
+ op = JSOP_POP;
+ if (!MaybeEmitGroupAssignment(cx, cg,
+ inLetHead ? JSOP_POP : PN_OP(pn),
+ pn2, &op)) {
+ return JS_FALSE;
+ }
+ if (op == JSOP_NOP) {
+ pn->pn_extra = (pn->pn_extra & ~PNX_POPVAR) | PNX_GROUPINIT;
+ break;
+ }
+ }
+
+ pn3 = pn2->pn_left;
+ if (!EmitDestructuringDecls(cx, cg, PN_OP(pn), pn3))
+ return JS_FALSE;
+
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+
+ /*
+ * Veto pn->pn_op if inLetHead to avoid emitting a SRC_DESTRUCT
+ * that's redundant with respect to the SRC_DECL/SRC_DECL_LET that
+ * we will emit at the bottom of this function.
+ */
+ if (!EmitDestructuringOps(cx, cg,
+ inLetHead ? JSOP_POP : PN_OP(pn),
+ pn3)) {
+ return JS_FALSE;
+ }
+ goto emit_note_pop;
+ }
+#else
+ JS_ASSERT(pn2->pn_type == TOK_NAME);
+#endif
+
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ JS_ASSERT(pn2->pn_slot >= 0 || !let);
+
+ op = PN_OP(pn2);
+ if (op == JSOP_ARGUMENTS) {
+ /* JSOP_ARGUMENTS => no initializer */
+ JS_ASSERT(!pn2->pn_expr && !let);
+ pn3 = NULL;
+#ifdef __GNUC__
+ atomIndex = 0; /* quell GCC overwarning */
+#endif
+ } else {
+ if (!MaybeEmitVarDecl(cx, cg, PN_OP(pn), pn2, &atomIndex))
+ return JS_FALSE;
+
+ pn3 = pn2->pn_expr;
+ if (pn3) {
+ JS_ASSERT(!forInVar);
+ if (op == JSOP_SETNAME) {
+ JS_ASSERT(!let);
+ EMIT_INDEX_OP(JSOP_BINDNAME, atomIndex);
+ }
+ if (pn->pn_op == JSOP_DEFCONST &&
+ !js_DefineCompileTimeConstant(cx, cg, pn2->pn_atom,
+ pn3)) {
+ return JS_FALSE;
+ }
+
+#if JS_HAS_BLOCK_SCOPE
+ /* Evaluate expr in the outer lexical scope if requested. */
+ if (popScope) {
+ stmt = tc->topStmt;
+ scopeStmt = tc->topScopeStmt;
+
+ tc->topStmt = stmt->down;
+ tc->topScopeStmt = scopeStmt->downScope;
+ }
+# ifdef __GNUC__
+ else stmt = scopeStmt = NULL; /* quell GCC overwarning */
+# endif
+#endif
+
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+
+#if JS_HAS_BLOCK_SCOPE
+ if (popScope) {
+ tc->topStmt = stmt;
+ tc->topScopeStmt = scopeStmt;
+ }
+#endif
+ }
+ }
+
+ /*
+ * The parser rewrites 'for (var x = i in o)' to hoist 'var x = i' --
+ * likewise 'for (let x = i in o)' becomes 'i; for (let x in o)' using
+ * a TOK_SEQ node to make the two statements appear as one. Therefore
+ * if this declaration is part of a for-in loop head, we do not need to
+ * emit op or any source note. Our caller, the TOK_FOR/TOK_IN case in
+ * js_EmitTree, will annotate appropriately.
+ */
+ JS_ASSERT(pn3 == pn2->pn_expr);
+ if (forInVar) {
+ JS_ASSERT(pn->pn_count == 1);
+ JS_ASSERT(!pn3);
+ break;
+ }
+
+ if (pn2 == pn->pn_head &&
+ !inLetHead &&
+ js_NewSrcNote2(cx, cg, SRC_DECL,
+ (pn->pn_op == JSOP_DEFCONST)
+ ? SRC_DECL_CONST
+ : (pn->pn_op == JSOP_DEFVAR)
+ ? SRC_DECL_VAR
+ : SRC_DECL_LET) < 0) {
+ return JS_FALSE;
+ }
+ if (op == JSOP_ARGUMENTS) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ } else if (pn2->pn_slot >= 0) {
+ EMIT_UINT16_IMM_OP(op, atomIndex);
+ } else {
+ EMIT_INDEX_OP(op, atomIndex);
+ }
+
+#if JS_HAS_DESTRUCTURING
+ emit_note_pop:
+#endif
+ tmp = CG_OFFSET(cg);
+ if (noteIndex >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
+ return JS_FALSE;
+ }
+ if (!pn2->pn_next)
+ break;
+ off = tmp;
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ }
+
+ /* If this is a let head, emit and return a srcnote on the pop. */
+ if (inLetHead) {
+ *headNoteIndex = js_NewSrcNote(cx, cg, SRC_DECL);
+ if (*headNoteIndex < 0)
+ return JS_FALSE;
+ if (!(pn->pn_extra & PNX_POPVAR))
+ return js_Emit1(cx, cg, JSOP_NOP) >= 0;
+ }
+
+ return !(pn->pn_extra & PNX_POPVAR) || js_Emit1(cx, cg, JSOP_POP) >= 0;
+}
+
+#if defined DEBUG_brendanXXX || defined DEBUG_mrbkap
+static JSBool
+GettableNoteForNextOp(JSCodeGenerator *cg)
+{
+ ptrdiff_t offset, target;
+ jssrcnote *sn, *end;
+
+ offset = 0;
+ target = CG_OFFSET(cg);
+ for (sn = CG_NOTES(cg), end = sn + CG_NOTE_COUNT(cg); sn < end;
+ sn = SN_NEXT(sn)) {
+ if (offset == target && SN_IS_GETTABLE(sn))
+ return JS_TRUE;
+ offset += SN_DELTA(sn);
+ }
+ return JS_FALSE;
+}
+#endif
+
+/* Top-level named functions need a nop for decompilation. */
+static JSBool
+EmitFunctionDefNop(JSContext *cx, JSCodeGenerator *cg, uintN index)
+{
+ return js_NewSrcNote2(cx, cg, SRC_FUNCDEF, (ptrdiff_t)index) >= 0 &&
+ js_Emit1(cx, cg, JSOP_NOP) >= 0;
+}
+
+/* See the SRC_FOR source note offsetBias comments later in this file. */
+JS_STATIC_ASSERT(JSOP_NOP_LENGTH == 1);
+JS_STATIC_ASSERT(JSOP_POP_LENGTH == 1);
+
+JSBool
+js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
+{
+ JSBool ok, useful, wantval;
+ JSStmtInfo *stmt, stmtInfo;
+ ptrdiff_t top, off, tmp, beq, jmp;
+ JSParseNode *pn2, *pn3;
+ JSAtom *atom;
+ JSAtomListElement *ale;
+ jsatomid atomIndex;
+ uintN index;
+ ptrdiff_t noteIndex;
+ JSSrcNoteType noteType;
+ jsbytecode *pc;
+ JSOp op;
+ JSTokenType type;
+ uint32 argc;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ ok = JS_TRUE;
+ cg->emitLevel++;
+ pn->pn_offset = top = CG_OFFSET(cg);
+
+ /* Emit notes to tell the current bytecode's source line number. */
+ UPDATE_LINE_NUMBER_NOTES(cx, cg, pn);
+
+ switch (pn->pn_type) {
+ case TOK_FUNCTION:
+ {
+ JSFunction *fun;
+ void *cg2mark;
+ JSCodeGenerator *cg2;
+ uintN slot;
+
+#if JS_HAS_XML_SUPPORT
+ if (pn->pn_arity == PN_NULLARY) {
+ if (js_Emit1(cx, cg, JSOP_GETFUNNS) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif
+
+ fun = (JSFunction *) pn->pn_funpob->object;
+ if (fun->u.i.script) {
+ /*
+ * This second pass is needed to emit JSOP_NOP with a source note
+ * for the already-emitted function definition prolog opcode. See
+ * comments in the TOK_LC case.
+ */
+ JS_ASSERT(pn->pn_op == JSOP_NOP);
+ JS_ASSERT(cg->treeContext.flags & TCF_IN_FUNCTION);
+ JS_ASSERT(pn->pn_index != (uint32) -1);
+ if (!EmitFunctionDefNop(cx, cg, pn->pn_index))
+ return JS_FALSE;
+ break;
+ }
+
+ /*
+ * Limit static nesting depth to fit in 16 bits. See cg2->staticDepth
+ * assignment below.
+ */
+ if (cg->staticDepth == JS_BITMASK(16)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TOO_DEEP,
+ js_function_str);
+ return JS_FALSE;
+ }
+
+ /* Generate code for the function's body. */
+ cg2mark = JS_ARENA_MARK(cg->codePool);
+ JS_ARENA_ALLOCATE_TYPE(cg2, JSCodeGenerator, cg->codePool);
+ if (!cg2) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ js_InitCodeGenerator(cx, cg2, cg->treeContext.parseContext,
+ cg->codePool, cg->notePool,
+ pn->pn_pos.begin.lineno);
+ cg2->treeContext.flags = (uint16) (pn->pn_flags | TCF_IN_FUNCTION);
+ cg2->treeContext.u.fun = fun;
+ cg2->staticDepth = cg->staticDepth + 1;
+ cg2->parent = cg;
+
+ /* We metered the max scope depth when parsed the function. */
+ JS_SCOPE_DEPTH_METERING(cg2->treeContext.maxScopeDepth = (uintN) -1);
+ if (!js_EmitFunctionScript(cx, cg2, pn->pn_body)) {
+ pn = NULL;
+ } else {
+ /*
+ * We need an activation object if an inner peeks out, or if such
+ * inner-peeking caused one of our inners to become heavyweight.
+ */
+ if (cg2->treeContext.flags &
+ (TCF_FUN_USES_NONLOCALS | TCF_FUN_HEAVYWEIGHT)) {
+ cg->treeContext.flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+ }
+
+ js_FinishCodeGenerator(cx, cg2);
+ JS_ARENA_RELEASE(cg->codePool, cg2mark);
+ cg2 = NULL;
+ if (!pn)
+ return JS_FALSE;
+
+ /* Make the function object a literal in the outer script's pool. */
+ index = IndexParsedObject(pn->pn_funpob, &cg->objectList);
+
+ /* Emit a bytecode pointing to the closure object in its immediate. */
+ if (pn->pn_op != JSOP_NOP) {
+ if ((pn->pn_flags & TCF_GENEXP_LAMBDA) &&
+ js_NewSrcNote(cx, cg, SRC_GENEXP) < 0) {
+ return JS_FALSE;
+ }
+ EMIT_INDEX_OP(PN_OP(pn), index);
+ break;
+ }
+
+ /*
+ * For a script we emit the code as we parse. Thus the bytecode for
+ * top-level functions should go in the prolog to predefine their
+ * names in the variable object before the already-generated main code
+ * is executed. This extra work for top-level scripts is not necessary
+ * when we emit the code for a function. It is fully parsed prior to
+ * invocation of the emitter and calls to js_EmitTree for function
+ * definitions can be scheduled before generating the rest of code.
+ */
+ if (!(cg->treeContext.flags & TCF_IN_FUNCTION)) {
+ JS_ASSERT(!cg->treeContext.topStmt);
+ CG_SWITCH_TO_PROLOG(cg);
+ EMIT_INDEX_OP(JSOP_DEFFUN, index);
+ CG_SWITCH_TO_MAIN(cg);
+
+ /* Emit NOP for the decompiler. */
+ if (!EmitFunctionDefNop(cx, cg, index))
+ return JS_FALSE;
+ } else {
+#ifdef DEBUG
+ JSLocalKind localKind =
+#endif
+ js_LookupLocal(cx, cg->treeContext.u.fun, fun->atom, &slot);
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+ JS_ASSERT(pn->pn_index == (uint32) -1);
+ pn->pn_index = index;
+ if (!EmitSlotIndexOp(cx, JSOP_DEFLOCALFUN, slot, index, cg))
+ return JS_FALSE;
+ }
+ break;
+ }
+
+
+ case TOK_IF:
+ /* Initialize so we can detect else-if chains and avoid recursion. */
+ stmtInfo.type = STMT_IF;
+ beq = jmp = -1;
+ noteIndex = -1;
+
+ if_again:
+ /* Emit code for the condition before pushing stmtInfo. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid1))
+ return JS_FALSE;
+ top = CG_OFFSET(cg);
+ if (stmtInfo.type == STMT_IF) {
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_IF, top);
+ } else {
+ /*
+ * We came here from the goto further below that detects else-if
+ * chains, so we must mutate stmtInfo back into a STMT_IF record.
+ * Also (see below for why) we need a note offset for SRC_IF_ELSE
+ * to help the decompiler. Actually, we need two offsets, one for
+ * decompiling any else clause and the second for decompiling an
+ * else-if chain without bracing, overindenting, or incorrectly
+ * scoping let declarations.
+ */
+ JS_ASSERT(stmtInfo.type == STMT_ELSE);
+ stmtInfo.type = STMT_IF;
+ stmtInfo.update = top;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 1, top - jmp))
+ return JS_FALSE;
+ }
+
+ /* Emit an annotated branch-if-false around the then part. */
+ pn3 = pn->pn_kid3;
+ noteIndex = js_NewSrcNote(cx, cg, pn3 ? SRC_IF_ELSE : SRC_IF);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFEQ, 0);
+ if (beq < 0)
+ return JS_FALSE;
+
+ /* Emit code for the then and optional else parts. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid2))
+ return JS_FALSE;
+ if (pn3) {
+ /* Modify stmtInfo so we know we're in the else part. */
+ stmtInfo.type = STMT_ELSE;
+
+ /*
+ * Emit a JSOP_BACKPATCH op to jump from the end of our then part
+ * around the else part. The js_PopStatementCG call at the bottom
+ * of this switch case will fix up the backpatch chain linked from
+ * stmtInfo.breaks.
+ */
+ jmp = EmitGoto(cx, cg, &stmtInfo, &stmtInfo.breaks, NULL, SRC_NULL);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ /* Ensure the branch-if-false comes here, then emit the else. */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);
+ if (pn3->pn_type == TOK_IF) {
+ pn = pn3;
+ goto if_again;
+ }
+
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+
+ /*
+ * Annotate SRC_IF_ELSE with the offset from branch to jump, for
+ * the decompiler's benefit. We can't just "back up" from the pc
+ * of the else clause, because we don't know whether an extended
+ * jump was required to leap from the end of the then clause over
+ * the else clause.
+ */
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))
+ return JS_FALSE;
+ } else {
+ /* No else part, fixup the branch-if-false to come here. */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);
+ }
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_SWITCH:
+ /* Out of line to avoid bloating js_EmitTree's stack frame size. */
+ ok = EmitSwitch(cx, cg, pn, &stmtInfo);
+ break;
+
+ case TOK_WHILE:
+ /*
+ * Minimize bytecodes issued for one or more iterations by jumping to
+ * the condition below the body and closing the loop if the condition
+ * is true with a backward branch. For iteration count i:
+ *
+ * i test at the top test at the bottom
+ * = =============== ==================
+ * 0 ifeq-pass goto; ifne-fail
+ * 1 ifeq-fail; goto; ifne-pass goto; ifne-pass; ifne-fail
+ * 2 2*(ifeq-fail; goto); ifeq-pass goto; 2*ifne-pass; ifne-fail
+ * . . .
+ * N N*(ifeq-fail; goto); ifeq-pass goto; N*ifne-pass; ifne-fail
+ *
+ * SpiderMonkey, pre-mozilla.org, emitted while parsing and so used
+ * test at the top. When JSParseNode trees were added during the ES3
+ * work (1998-9), the code generation scheme was not optimized, and
+ * the decompiler continued to take advantage of the branch and jump
+ * that bracketed the body. But given the SRC_WHILE note, it is easy
+ * to support the more efficient scheme.
+ */
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WHILE_LOOP, top);
+ noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, beq - jmp))
+ return JS_FALSE;
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_DO:
+ /* Emit an annotated nop so we know to decompile a 'do' keyword. */
+ noteIndex = js_NewSrcNote(cx, cg, SRC_WHILE);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0)
+ return JS_FALSE;
+
+ /* Compile the loop body. */
+ top = CG_OFFSET(cg);
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_DO_LOOP, top);
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+
+ /* Set loop and enclosing label update offsets, for continue. */
+ stmt = &stmtInfo;
+ do {
+ stmt->update = CG_OFFSET(cg);
+ } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+ /* Compile the loop condition, now that continues know where to go. */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /*
+ * Since we use JSOP_IFNE for other purposes as well as for do-while
+ * loops, we must store 1 + (beq - top) in the SRC_WHILE note offset,
+ * and the decompiler must get that delta and decompile recursively.
+ */
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, 1 + (beq - top)))
+ return JS_FALSE;
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_FOR:
+ beq = 0; /* suppress gcc warnings */
+ jmp = -1;
+ pn2 = pn->pn_left;
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_FOR_LOOP, top);
+
+ if (pn2->pn_type == TOK_IN) {
+ /* Set stmtInfo type for later testing. */
+ stmtInfo.type = STMT_FOR_IN_LOOP;
+
+ /*
+ * If the left part is 'var x', emit code to define x if necessary
+ * using a prolog opcode, but do not emit a pop. If the left part
+ * is 'var x = i', emit prolog code to define x if necessary; then
+ * emit code to evaluate i, assign the result to x, and pop the
+ * result off the stack.
+ *
+ * All the logic to do this is implemented in the outer switch's
+ * TOK_VAR case, conditioned on pn_extra flags set by the parser.
+ *
+ * In the 'for (var x = i in o) ...' case, the js_EmitTree(...pn3)
+ * called here will generate the proper note for the assignment
+ * op that sets x = i, hoisting the initialized var declaration
+ * out of the loop: 'var x = i; for (x in o) ...'.
+ *
+ * In the 'for (var x in o) ...' case, nothing but the prolog op
+ * (if needed) should be generated here, we must emit the note
+ * just before the JSOP_FOR* opcode in the switch on pn3->pn_type
+ * a bit below, so nothing is hoisted: 'for (var x in o) ...'.
+ *
+ * A 'for (let x = i in o)' loop must not be hoisted, since in
+ * this form the let variable is scoped by the loop body (but not
+ * the head). The initializer expression i must be evaluated for
+ * any side effects. So we hoist only i in the let case.
+ */
+ pn3 = pn2->pn_left;
+ type = PN_TYPE(pn3);
+ cg->treeContext.flags |= TCF_IN_FOR_INIT;
+ if (TOKEN_TYPE_IS_DECL(type) && !js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+
+ /* Compile the object expression to the right of 'in'. */
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+
+ /*
+ * Emit a bytecode to convert top of stack value to the iterator
+ * object depending on the loop variant (for-in, for-each-in, or
+ * destructuring for-in).
+ */
+ JS_ASSERT(pn->pn_op == JSOP_ITER);
+ if (js_Emit2(cx, cg, JSOP_ITER, (uint8) pn->pn_iflags) < 0)
+ return JS_FALSE;
+
+ /* Annotate so the decompiler can find the loop-closing jump. */
+ noteIndex = js_NewSrcNote(cx, cg, SRC_FOR_IN);
+ if (noteIndex < 0)
+ return JS_FALSE;
+
+ /*
+ * Jump down to the loop condition to minimize overhead assuming at
+ * least one iteration, as the other loop forms do.
+ */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ top = CG_OFFSET(cg);
+ SET_STATEMENT_TOP(&stmtInfo, top);
+
+#ifdef DEBUG
+ intN loopDepth = cg->stackDepth;
+#endif
+
+ /*
+ * Compile a JSOP_FOR* bytecode based on the left hand side.
+ *
+ * Initialize op to JSOP_SETNAME in case of |for ([a, b] in o)...|
+ * or similar, to signify assignment, rather than declaration, to
+ * the decompiler. EmitDestructuringOps takes a prolog bytecode
+ * parameter and emits the appropriate source note, defaulting to
+ * assignment, so JSOP_SETNAME is not critical here; many similar
+ * ops could be used -- just not JSOP_NOP (which means 'let').
+ */
+ op = JSOP_SETNAME;
+ switch (type) {
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+#endif
+ case TOK_VAR:
+ JS_ASSERT(pn3->pn_arity == PN_LIST && pn3->pn_count == 1);
+ pn3 = pn3->pn_head;
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_ASSIGN) {
+ pn3 = pn3->pn_left;
+ JS_ASSERT(pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC);
+ }
+ if (pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC) {
+ op = PN_OP(pn2->pn_left);
+ goto destructuring_for;
+ }
+#else
+ JS_ASSERT(pn3->pn_type == TOK_NAME);
+#endif
+ /* FALL THROUGH */
+
+ case TOK_NAME:
+ /*
+ * Always annotate JSOP_FORLOCAL if given input of the form
+ * 'for (let x in * o)' -- the decompiler must not hoist the
+ * 'let x' out of the loop head, or x will be bound in the
+ * wrong scope. Likewise, but in this case only for the sake
+ * of higher decompilation fidelity only, do not hoist 'var x'
+ * when given 'for (var x in o)'.
+ */
+ if ((
+#if JS_HAS_BLOCK_SCOPE
+ type == TOK_LET ||
+#endif
+ (type == TOK_VAR && !pn3->pn_expr)) &&
+ js_NewSrcNote2(cx, cg, SRC_DECL,
+ (type == TOK_VAR)
+ ? SRC_DECL_VAR
+ : SRC_DECL_LET) < 0) {
+ return JS_FALSE;
+ }
+ if (pn3->pn_slot >= 0) {
+ op = PN_OP(pn3);
+ switch (op) {
+ case JSOP_GETARG: /* FALL THROUGH */
+ case JSOP_SETARG: op = JSOP_FORARG; break;
+ case JSOP_GETGVAR: /* FALL THROUGH */
+ case JSOP_SETGVAR: op = JSOP_FORNAME; break;
+ case JSOP_GETLOCAL: /* FALL THROUGH */
+ case JSOP_SETLOCAL: op = JSOP_FORLOCAL; break;
+ default: JS_ASSERT(0);
+ }
+ } else {
+ pn3->pn_op = JSOP_FORNAME;
+ if (!BindNameToSlot(cx, cg, pn3))
+ return JS_FALSE;
+ op = PN_OP(pn3);
+ }
+ if (pn3->pn_slot >= 0) {
+ if (pn3->pn_const) {
+ JS_ASSERT(op == JSOP_FORLOCAL);
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), pn3, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_LEFTSIDE);
+ return JS_FALSE;
+ }
+ atomIndex = (jsatomid) pn3->pn_slot;
+ EMIT_UINT16_IMM_OP(op, atomIndex);
+ } else {
+ if (!EmitAtomOp(cx, pn3, op, cg))
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_DOT:
+ /*
+ * 'for (o.p in q)' can use JSOP_FORPROP only if evaluating 'o'
+ * has no side effects.
+ */
+ useful = JS_FALSE;
+ if (!CheckSideEffects(cx, cg, pn3->pn_expr, &useful))
+ return JS_FALSE;
+ if (!useful) {
+ if (!EmitPropOp(cx, pn3, JSOP_FORPROP, cg, JS_FALSE))
+ return JS_FALSE;
+ break;
+ }
+ /* FALL THROUGH */
+
+#if JS_HAS_DESTRUCTURING
+ destructuring_for:
+#endif
+ default:
+ if (js_Emit1(cx, cg, JSOP_FORELEM) < 0)
+ return JS_FALSE;
+ JS_ASSERT(cg->stackDepth >= 3);
+
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_RB || pn3->pn_type == TOK_RC) {
+ if (!EmitDestructuringOps(cx, cg, op, pn3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ } else
+#endif
+#if JS_HAS_LVALUE_RETURN
+ if (pn3->pn_type == TOK_LP) {
+ JS_ASSERT(pn3->pn_op == JSOP_SETCALL);
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0)
+ return JS_FALSE;
+ } else
+#endif
+#if JS_HAS_XML_SUPPORT
+ if (pn3->pn_type == TOK_UNARYOP) {
+ JS_ASSERT(pn3->pn_op == JSOP_BINDXMLNAME);
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ENUMELEM) < 0)
+ return JS_FALSE;
+ } else
+#endif
+ if (!EmitElemOp(cx, pn3, JSOP_ENUMELEM, cg))
+ return JS_FALSE;
+ break;
+ }
+
+ /* The stack should be balanced around the JSOP_FOR* opcode sequence. */
+ JS_ASSERT(cg->stackDepth == loopDepth);
+
+ /* Set the first srcnote offset so we can find the start of the loop body. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, CG_OFFSET(cg) - jmp))
+ return JS_FALSE;
+
+ /* Emit code for the loop body. */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /* Set loop and enclosing "update" offsets, for continue. */
+ stmt = &stmtInfo;
+ do {
+ stmt->update = CG_OFFSET(cg);
+ } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+ /*
+ * Fixup the goto that starts the loop to jump down to JSOP_NEXTITER.
+ */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (js_Emit1(cx, cg, JSOP_NEXTITER) < 0)
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+
+ /* Set the second srcnote offset so we can find the closing jump. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1, beq - jmp))
+ return JS_FALSE;
+ } else {
+ /* C-style for (init; cond; update) ... loop. */
+ op = JSOP_POP;
+ pn3 = pn2->pn_kid1;
+ if (!pn3) {
+ /* No initializer: emit an annotated nop for the decompiler. */
+ op = JSOP_NOP;
+ } else {
+ cg->treeContext.flags |= TCF_IN_FOR_INIT;
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_ASSIGN &&
+ !MaybeEmitGroupAssignment(cx, cg, op, pn3, &op)) {
+ return JS_FALSE;
+ }
+#endif
+ if (op == JSOP_POP) {
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ if (TOKEN_TYPE_IS_DECL(pn3->pn_type)) {
+ /*
+ * Check whether a destructuring-initialized var decl
+ * was optimized to a group assignment. If so, we do
+ * not need to emit a pop below, so switch to a nop,
+ * just for the decompiler.
+ */
+ JS_ASSERT(pn3->pn_arity == PN_LIST);
+ if (pn3->pn_extra & PNX_GROUPINIT)
+ op = JSOP_NOP;
+ }
+ }
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ }
+
+ /*
+ * NB: the SRC_FOR note has offsetBias 1 (JSOP_{NOP,POP}_LENGTH).
+ * Use tmp to hold the biased srcnote "top" offset, which differs
+ * from the top local variable by the length of the JSOP_GOTO{,X}
+ * emitted in between tmp and top if this loop has a condition.
+ */
+ noteIndex = js_NewSrcNote(cx, cg, SRC_FOR);
+ if (noteIndex < 0 || js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ tmp = CG_OFFSET(cg);
+
+ if (pn2->pn_kid2) {
+ /* Goto the loop condition, which branches back to iterate. */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ }
+
+ top = CG_OFFSET(cg);
+ SET_STATEMENT_TOP(&stmtInfo, top);
+
+ /* Emit code for the loop body. */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /* Set the second note offset so we can find the update part. */
+ JS_ASSERT(noteIndex != -1);
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 1,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ /* Set loop and enclosing "update" offsets, for continue. */
+ stmt = &stmtInfo;
+ do {
+ stmt->update = CG_OFFSET(cg);
+ } while ((stmt = stmt->down) != NULL && stmt->type == STMT_LABEL);
+
+ /* Check for update code to do before the condition (if any). */
+ pn3 = pn2->pn_kid3;
+ if (pn3) {
+ op = JSOP_POP;
+#if JS_HAS_DESTRUCTURING
+ if (pn3->pn_type == TOK_ASSIGN &&
+ !MaybeEmitGroupAssignment(cx, cg, op, pn3, &op)) {
+ return JS_FALSE;
+ }
+#endif
+ if (op == JSOP_POP && !js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+
+ /* Always emit the POP or NOP, to help the decompiler. */
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+
+ /* Restore the absolute line number for source note readers. */
+ off = (ptrdiff_t) pn->pn_pos.end.lineno;
+ if (CG_CURRENT_LINE(cg) != (uintN) off) {
+ if (js_NewSrcNote2(cx, cg, SRC_SETLINE, off) < 0)
+ return JS_FALSE;
+ CG_CURRENT_LINE(cg) = (uintN) off;
+ }
+ }
+
+ /* Set the first note offset so we can find the loop condition. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ if (pn2->pn_kid2) {
+ /* Fix up the goto from top to target the loop condition. */
+ JS_ASSERT(jmp >= 0);
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+
+ if (!js_EmitTree(cx, cg, pn2->pn_kid2))
+ return JS_FALSE;
+ }
+
+ /* The third note offset helps us find the loop-closing jump. */
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 2,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ if (pn2->pn_kid2) {
+ beq = EmitJump(cx, cg, JSOP_IFNE, top - CG_OFFSET(cg));
+ if (beq < 0)
+ return JS_FALSE;
+ } else {
+ /* No loop condition -- emit the loop-closing jump. */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, top - CG_OFFSET(cg));
+ if (jmp < 0)
+ return JS_FALSE;
+ }
+ }
+
+ /* Now fixup all breaks and continues (before for/in's JSOP_ENDITER). */
+ if (!js_PopStatementCG(cx, cg))
+ return JS_FALSE;
+
+ if (pn2->pn_type == TOK_IN) {
+ /*
+ * JSOP_ENDITER must have a slot to save an exception thrown from
+ * the body of for-in loop when closing the iterator object, and
+ * fortunately it does: the slot that was set by JSOP_NEXTITER to
+ * the return value of iterator.next().
+ */
+ JS_ASSERT(js_CodeSpec[JSOP_ENDITER].nuses == 2);
+ if (!NewTryNote(cx, cg, JSTRY_ITER, cg->stackDepth, top, CG_OFFSET(cg)) ||
+ js_Emit1(cx, cg, JSOP_ENDITER) < 0) {
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_BREAK:
+ stmt = cg->treeContext.topStmt;
+ atom = pn->pn_atom;
+ if (atom) {
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ while (stmt->type != STMT_LABEL || stmt->u.label != atom)
+ stmt = stmt->down;
+ noteType = SRC_BREAK2LABEL;
+ } else {
+ ale = NULL;
+ while (!STMT_IS_LOOP(stmt) && stmt->type != STMT_SWITCH)
+ stmt = stmt->down;
+ noteType = (stmt->type == STMT_SWITCH) ? SRC_NULL : SRC_BREAK;
+ }
+
+ if (EmitGoto(cx, cg, stmt, &stmt->breaks, ale, noteType) < 0)
+ return JS_FALSE;
+ break;
+
+ case TOK_CONTINUE:
+ stmt = cg->treeContext.topStmt;
+ atom = pn->pn_atom;
+ if (atom) {
+ /* Find the loop statement enclosed by the matching label. */
+ JSStmtInfo *loop = NULL;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ while (stmt->type != STMT_LABEL || stmt->u.label != atom) {
+ if (STMT_IS_LOOP(stmt))
+ loop = stmt;
+ stmt = stmt->down;
+ }
+ stmt = loop;
+ noteType = SRC_CONT2LABEL;
+ } else {
+ ale = NULL;
+ while (!STMT_IS_LOOP(stmt))
+ stmt = stmt->down;
+ noteType = SRC_CONTINUE;
+ }
+
+ if (EmitGoto(cx, cg, stmt, &stmt->continues, ale, noteType) < 0)
+ return JS_FALSE;
+ break;
+
+ case TOK_WITH:
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_WITH, CG_OFFSET(cg));
+ if (js_Emit1(cx, cg, JSOP_ENTERWITH) < 0)
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_LEAVEWITH) < 0)
+ return JS_FALSE;
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_TRY:
+ {
+ ptrdiff_t tryStart, tryEnd, catchJump, finallyStart;
+ intN depth;
+ JSParseNode *lastCatch;
+
+ catchJump = -1;
+
+ /*
+ * Push stmtInfo to track jumps-over-catches and gosubs-to-finally
+ * for later fixup.
+ *
+ * When a finally block is 'active' (STMT_FINALLY on the treeContext),
+ * non-local jumps (including jumps-over-catches) result in a GOSUB
+ * being written into the bytecode stream and fixed-up later (c.f.
+ * EmitBackPatchOp and BackPatch).
+ */
+ js_PushStatement(&cg->treeContext, &stmtInfo,
+ pn->pn_kid3 ? STMT_FINALLY : STMT_TRY,
+ CG_OFFSET(cg));
+
+ /*
+ * Since an exception can be thrown at any place inside the try block,
+ * we need to restore the stack and the scope chain before we transfer
+ * the control to the exception handler.
+ *
+ * For that we store in a try note associated with the catch or
+ * finally block the stack depth upon the try entry. The interpreter
+ * uses this depth to properly unwind the stack and the scope chain.
+ */
+ depth = cg->stackDepth;
+
+ /* Mark try location for decompilation, then emit try block. */
+ if (js_Emit1(cx, cg, JSOP_TRY) < 0)
+ return JS_FALSE;
+ tryStart = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn->pn_kid1))
+ return JS_FALSE;
+ JS_ASSERT(depth == cg->stackDepth);
+
+ /* GOSUB to finally, if present. */
+ if (pn->pn_kid3) {
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &GOSUBS(stmtInfo));
+ if (jmp < 0)
+ return JS_FALSE;
+ }
+
+ /* Emit (hidden) jump over catch and/or finally. */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &catchJump);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ tryEnd = CG_OFFSET(cg);
+
+ /* If this try has a catch block, emit it. */
+ pn2 = pn->pn_kid2;
+ lastCatch = NULL;
+ if (pn2) {
+ jsint count = 0; /* previous catch block's population */
+
+ /*
+ * The emitted code for a catch block looks like:
+ *
+ * [throwing] only if 2nd+ catch block
+ * [leaveblock] only if 2nd+ catch block
+ * enterblock with SRC_CATCH
+ * exception
+ * [dup] only if catchguard
+ * setlocalpop <slot> or destructuring code
+ * [< catchguard code >] if there's a catchguard
+ * [ifeq <offset to next catch block>] " "
+ * [pop] only if catchguard
+ * < catch block contents >
+ * leaveblock
+ * goto <end of catch blocks> non-local; finally applies
+ *
+ * If there's no catch block without a catchguard, the last
+ * <offset to next catch block> points to rethrow code. This
+ * code will [gosub] to the finally code if appropriate, and is
+ * also used for the catch-all trynote for capturing exceptions
+ * thrown from catch{} blocks.
+ */
+ for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
+ ptrdiff_t guardJump, catchNote;
+
+ JS_ASSERT(cg->stackDepth == depth);
+ guardJump = GUARDJUMP(stmtInfo);
+ if (guardJump != -1) {
+ /* Fix up and clean up previous catch block. */
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, guardJump);
+
+ /*
+ * Account for JSOP_ENTERBLOCK (whose block object count
+ * is saved below) and pushed exception object that we
+ * still have after the jumping from the previous guard.
+ */
+ cg->stackDepth = depth + count + 1;
+
+ /*
+ * Move exception back to cx->exception to prepare for
+ * the next catch. We hide [throwing] from the decompiler
+ * since it compensates for the hidden JSOP_DUP at the
+ * start of the previous guarded catch.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
+ js_Emit1(cx, cg, JSOP_THROWING) < 0) {
+ return JS_FALSE;
+ }
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_LEAVEBLOCK, count);
+ JS_ASSERT(cg->stackDepth == depth);
+ }
+
+ /*
+ * Annotate the JSOP_ENTERBLOCK that's about to be generated
+ * by the call to js_EmitTree immediately below. Save this
+ * source note's index in stmtInfo for use by the TOK_CATCH:
+ * case, where the length of the catch guard is set as the
+ * note's offset.
+ */
+ catchNote = js_NewSrcNote2(cx, cg, SRC_CATCH, 0);
+ if (catchNote < 0)
+ return JS_FALSE;
+ CATCHNOTE(stmtInfo) = catchNote;
+
+ /*
+ * Emit the lexical scope and catch body. Save the catch's
+ * block object population via count, for use when targeting
+ * guardJump at the next catch (the guard mismatch case).
+ */
+ JS_ASSERT(pn3->pn_type == TOK_LEXICALSCOPE);
+ count = OBJ_BLOCK_COUNT(cx, pn3->pn_pob->object);
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+
+ /* gosub <finally>, if required */
+ if (pn->pn_kid3) {
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH,
+ &GOSUBS(stmtInfo));
+ if (jmp < 0)
+ return JS_FALSE;
+ JS_ASSERT(cg->stackDepth == depth);
+ }
+
+ /*
+ * Jump over the remaining catch blocks. This will get fixed
+ * up to jump to after catch/finally.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ jmp = EmitBackPatchOp(cx, cg, JSOP_BACKPATCH, &catchJump);
+ if (jmp < 0)
+ return JS_FALSE;
+
+ /*
+ * Save a pointer to the last catch node to handle try-finally
+ * and try-catch(guard)-finally special cases.
+ */
+ lastCatch = pn3->pn_expr;
+ }
+ }
+
+ /*
+ * Last catch guard jumps to the rethrow code sequence if none of the
+ * guards match. Target guardJump at the beginning of the rethrow
+ * sequence, just in case a guard expression throws and leaves the
+ * stack unbalanced.
+ */
+ if (lastCatch && lastCatch->pn_kid2) {
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, GUARDJUMP(stmtInfo));
+
+ /* Sync the stack to take into account pushed exception. */
+ JS_ASSERT(cg->stackDepth == depth);
+ cg->stackDepth = depth + 1;
+
+ /*
+ * Rethrow the exception, delegating executing of finally if any
+ * to the exception handler.
+ */
+ if (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 ||
+ js_Emit1(cx, cg, JSOP_THROW) < 0) {
+ return JS_FALSE;
+ }
+ }
+
+ JS_ASSERT(cg->stackDepth == depth);
+
+ /* Emit finally handler if any. */
+ finallyStart = 0; /* to quell GCC uninitialized warnings */
+ if (pn->pn_kid3) {
+ /*
+ * Fix up the gosubs that might have been emitted before non-local
+ * jumps to the finally code.
+ */
+ if (!BackPatch(cx, cg, GOSUBS(stmtInfo), CG_NEXT(cg), JSOP_GOSUB))
+ return JS_FALSE;
+
+ finallyStart = CG_OFFSET(cg);
+
+ /* Indicate that we're emitting a subroutine body. */
+ stmtInfo.type = STMT_SUBROUTINE;
+ if (!UpdateLineNumberNotes(cx, cg, pn->pn_kid3))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_FINALLY) < 0 ||
+ !js_EmitTree(cx, cg, pn->pn_kid3) ||
+ js_Emit1(cx, cg, JSOP_RETSUB) < 0) {
+ return JS_FALSE;
+ }
+ JS_ASSERT(cg->stackDepth == depth);
+ }
+ if (!js_PopStatementCG(cx, cg))
+ return JS_FALSE;
+
+ if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||
+ js_Emit1(cx, cg, JSOP_NOP) < 0) {
+ return JS_FALSE;
+ }
+
+ /* Fix up the end-of-try/catch jumps to come here. */
+ if (!BackPatch(cx, cg, catchJump, CG_NEXT(cg), JSOP_GOTO))
+ return JS_FALSE;
+
+ /*
+ * Add the try note last, to let post-order give us the right ordering
+ * (first to last for a given nesting level, inner to outer by level).
+ */
+ if (pn->pn_kid2 &&
+ !NewTryNote(cx, cg, JSTRY_CATCH, depth, tryStart, tryEnd)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * If we've got a finally, mark try+catch region with additional
+ * trynote to catch exceptions (re)thrown from a catch block or
+ * for the try{}finally{} case.
+ */
+ if (pn->pn_kid3 &&
+ !NewTryNote(cx, cg, JSTRY_FINALLY, depth, tryStart, finallyStart)) {
+ return JS_FALSE;
+ }
+ break;
+ }
+
+ case TOK_CATCH:
+ {
+ ptrdiff_t catchStart, guardJump;
+ JSObject *blockObj;
+
+ /*
+ * Morph STMT_BLOCK to STMT_CATCH, note the block entry code offset,
+ * and save the block object atom.
+ */
+ stmt = cg->treeContext.topStmt;
+ JS_ASSERT(stmt->type == STMT_BLOCK && (stmt->flags & SIF_SCOPE));
+ stmt->type = STMT_CATCH;
+ catchStart = stmt->update;
+ blockObj = stmt->u.blockObj;
+
+ /* Go up one statement info record to the TRY or FINALLY record. */
+ stmt = stmt->down;
+ JS_ASSERT(stmt->type == STMT_TRY || stmt->type == STMT_FINALLY);
+
+ /* Pick up the pending exception and bind it to the catch variable. */
+ if (js_Emit1(cx, cg, JSOP_EXCEPTION) < 0)
+ return JS_FALSE;
+
+ /*
+ * Dup the exception object if there is a guard for rethrowing to use
+ * it later when rethrowing or in other catches.
+ */
+ if (pn->pn_kid2 && js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+
+ pn2 = pn->pn_kid1;
+ switch (pn2->pn_type) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ if (!EmitDestructuringOps(cx, cg, JSOP_NOP, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ break;
+#endif
+
+ case TOK_NAME:
+ /* Inline BindNameToSlot for pn2. */
+ JS_ASSERT(pn2->pn_slot == -1);
+ pn2->pn_slot = AdjustBlockSlot(cx, cg,
+ OBJ_BLOCK_DEPTH(cx, blockObj));
+ if (pn2->pn_slot < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_SETLOCALPOP, pn2->pn_slot);
+ break;
+
+ default:
+ JS_ASSERT(0);
+ }
+
+ /* Emit the guard expression, if there is one. */
+ if (pn->pn_kid2) {
+ if (!js_EmitTree(cx, cg, pn->pn_kid2))
+ return JS_FALSE;
+ if (!js_SetSrcNoteOffset(cx, cg, CATCHNOTE(*stmt), 0,
+ CG_OFFSET(cg) - catchStart)) {
+ return JS_FALSE;
+ }
+ /* ifeq <next block> */
+ guardJump = EmitJump(cx, cg, JSOP_IFEQ, 0);
+ if (guardJump < 0)
+ return JS_FALSE;
+ GUARDJUMP(*stmt) = guardJump;
+
+ /* Pop duplicated exception object as we no longer need it. */
+ if (js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ }
+
+ /* Emit the catch body. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid3))
+ return JS_FALSE;
+
+ /*
+ * Annotate the JSOP_LEAVEBLOCK that will be emitted as we unwind via
+ * our TOK_LEXICALSCOPE parent, so the decompiler knows to pop.
+ */
+ off = cg->stackDepth;
+ if (js_NewSrcNote2(cx, cg, SRC_CATCH, off) < 0)
+ return JS_FALSE;
+ break;
+ }
+
+ case TOK_VAR:
+ if (!EmitVariables(cx, cg, pn, JS_FALSE, &noteIndex))
+ return JS_FALSE;
+ break;
+
+ case TOK_RETURN:
+ /* Push a return value */
+ pn2 = pn->pn_kid;
+ if (pn2) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ } else {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ }
+
+ /*
+ * EmitNonLocalJumpFixup may add fixup bytecode to close open try
+ * blocks having finally clauses and to exit intermingled let blocks.
+ * We can't simply transfer control flow to our caller in that case,
+ * because we must gosub to those finally clauses from inner to outer,
+ * with the correct stack pointer (i.e., after popping any with,
+ * for/in, etc., slots nested inside the finally's try).
+ *
+ * In this case we mutate JSOP_RETURN into JSOP_SETRVAL and add an
+ * extra JSOP_RETRVAL after the fixups.
+ */
+ top = CG_OFFSET(cg);
+ if (js_Emit1(cx, cg, JSOP_RETURN) < 0)
+ return JS_FALSE;
+ if (!EmitNonLocalJumpFixup(cx, cg, NULL))
+ return JS_FALSE;
+ if (top + JSOP_RETURN_LENGTH != CG_OFFSET(cg)) {
+ CG_BASE(cg)[top] = JSOP_SETRVAL;
+ if (js_Emit1(cx, cg, JSOP_RETRVAL) < 0)
+ return JS_FALSE;
+ }
+ break;
+
+#if JS_HAS_GENERATORS
+ case TOK_YIELD:
+ if (!(cg->treeContext.flags & TCF_IN_FUNCTION)) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), pn, JSREPORT_ERROR,
+ JSMSG_BAD_RETURN_OR_YIELD,
+ js_yield_str);
+ return JS_FALSE;
+ }
+ if (pn->pn_kid) {
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ } else {
+ if (js_Emit1(cx, cg, JSOP_PUSH) < 0)
+ return JS_FALSE;
+ }
+ if (pn->pn_hidden && js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_YIELD) < 0)
+ return JS_FALSE;
+ break;
+#endif
+
+ case TOK_LC:
+#if JS_HAS_XML_SUPPORT
+ if (pn->pn_arity == PN_UNARY) {
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif
+
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+
+ noteIndex = -1;
+ tmp = CG_OFFSET(cg);
+ if (pn->pn_extra & PNX_NEEDBRACES) {
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_BRACE, 0);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_NOP) < 0)
+ return JS_FALSE;
+ }
+
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_BLOCK, top);
+ if (pn->pn_extra & PNX_FUNCDEFS) {
+ /*
+ * This block contains top-level function definitions. To ensure
+ * that we emit the bytecode defining them prior the rest of code
+ * in the block we use a separate pass over functions. During the
+ * main pass later the emitter will add JSOP_NOP with source notes
+ * for the function to preserve the original functions position
+ * when decompiling.
+ *
+ * Currently this is used only for functions, as compile-as-we go
+ * mode for scripts does not allow separate emitter passes.
+ */
+ JS_ASSERT(cg->treeContext.flags & TCF_IN_FUNCTION);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_FUNCTION) {
+ if (pn2->pn_op == JSOP_NOP) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ } else {
+ /*
+ * JSOP_DEFFUN in a top-level block with function
+ * definitions appears, for example, when "if (true)"
+ * is optimized away from "if (true) function x() {}".
+ * See bug 428424.
+ */
+ JS_ASSERT(pn2->pn_op == JSOP_DEFFUN);
+ }
+ }
+ }
+ }
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+
+ if (noteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_SEQ:
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_SEQ, top);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+ ok = js_PopStatementCG(cx, cg);
+ break;
+
+ case TOK_SEMI:
+ pn2 = pn->pn_kid;
+ if (pn2) {
+ /*
+ * Top-level or called-from-a-native JS_Execute/EvaluateScript,
+ * debugger, and eval frames may need the value of the ultimate
+ * expression statement as the script's result, despite the fact
+ * that it appears useless to the compiler.
+ *
+ * API users may also set the JSOPTION_NO_SCRIPT_RVAL option when
+ * calling JS_Compile* to suppress JSOP_POPV.
+ */
+ useful = wantval =
+ !(cg->treeContext.flags & (TCF_IN_FUNCTION | TCF_NO_SCRIPT_RVAL));
+ if (!useful) {
+ if (!CheckSideEffects(cx, cg, pn2, &useful))
+ return JS_FALSE;
+ }
+
+ /*
+ * Don't eliminate apparently useless expressions if they are
+ * labeled expression statements. The tc->topStmt->update test
+ * catches the case where we are nesting in js_EmitTree for a
+ * labeled compound statement.
+ */
+ if (!useful &&
+ (!cg->treeContext.topStmt ||
+ cg->treeContext.topStmt->type != STMT_LABEL ||
+ cg->treeContext.topStmt->update < CG_OFFSET(cg))) {
+ CG_CURRENT_LINE(cg) = pn2->pn_pos.begin.lineno;
+ if (!js_ReportCompileErrorNumber(cx, CG_TS(cg), pn2,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_USELESS_EXPR)) {
+ return JS_FALSE;
+ }
+ } else {
+ op = wantval ? JSOP_POPV : JSOP_POP;
+#if JS_HAS_DESTRUCTURING
+ if (!wantval &&
+ pn2->pn_type == TOK_ASSIGN &&
+ !MaybeEmitGroupAssignment(cx, cg, op, pn2, &op)) {
+ return JS_FALSE;
+ }
+#endif
+ if (op != JSOP_NOP) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+ }
+ }
+ break;
+
+ case TOK_COLON:
+ /* Emit an annotated nop so we know to decompile a label. */
+ atom = pn->pn_atom;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ pn2 = pn->pn_expr;
+ noteType = (pn2->pn_type == TOK_LC ||
+ (pn2->pn_type == TOK_LEXICALSCOPE &&
+ pn2->pn_expr->pn_type == TOK_LC))
+ ? SRC_LABELBRACE
+ : SRC_LABEL;
+ noteIndex = js_NewSrcNote2(cx, cg, noteType,
+ (ptrdiff_t) ALE_INDEX(ale));
+ if (noteIndex < 0 ||
+ js_Emit1(cx, cg, JSOP_NOP) < 0) {
+ return JS_FALSE;
+ }
+
+ /* Emit code for the labeled statement. */
+ js_PushStatement(&cg->treeContext, &stmtInfo, STMT_LABEL,
+ CG_OFFSET(cg));
+ stmtInfo.u.label = atom;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (!js_PopStatementCG(cx, cg))
+ return JS_FALSE;
+
+ /* If the statement was compound, emit a note for the end brace. */
+ if (noteType == SRC_LABELBRACE) {
+ if (js_NewSrcNote(cx, cg, SRC_ENDBRACE) < 0 ||
+ js_Emit1(cx, cg, JSOP_NOP) < 0) {
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_COMMA:
+ /*
+ * Emit SRC_PCDELTA notes on each JSOP_POP between comma operands.
+ * These notes help the decompiler bracket the bytecodes generated
+ * from each sub-expression that follows a comma.
+ */
+ off = noteIndex = -1;
+ for (pn2 = pn->pn_head; ; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ tmp = CG_OFFSET(cg);
+ if (noteIndex >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
+ return JS_FALSE;
+ }
+ if (!pn2->pn_next)
+ break;
+ off = tmp;
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (noteIndex < 0 ||
+ js_Emit1(cx, cg, JSOP_POP) < 0) {
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_ASSIGN:
+ /*
+ * Check left operand type and generate specialized code for it.
+ * Specialize to avoid ECMA "reference type" values on the operand
+ * stack, which impose pervasive runtime "GetValue" costs.
+ */
+ pn2 = pn->pn_left;
+ JS_ASSERT(pn2->pn_type != TOK_RP);
+ atomIndex = (jsatomid) -1; /* quell GCC overwarning */
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn2->pn_slot >= 0) {
+ atomIndex = (jsatomid) pn2->pn_slot;
+ } else {
+ ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ EMIT_INDEX_OP(JSOP_BINDNAME, atomIndex);
+ }
+ break;
+ case TOK_DOT:
+ if (!js_EmitTree(cx, cg, pn2->pn_expr))
+ return JS_FALSE;
+ ale = js_IndexAtom(cx, pn2->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ atomIndex = ALE_INDEX(ale);
+ break;
+ case TOK_LB:
+ JS_ASSERT(pn2->pn_arity == PN_BINARY);
+ if (!js_EmitTree(cx, cg, pn2->pn_left))
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+ break;
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ break;
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ JS_ASSERT(pn2->pn_op == JSOP_SETXMLNAME);
+ if (!js_EmitTree(cx, cg, pn2->pn_kid))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ default:
+ JS_ASSERT(0);
+ }
+
+ op = PN_OP(pn);
+#if JS_HAS_GETTER_SETTER
+ if (op == JSOP_GETTER || op == JSOP_SETTER) {
+ if (pn2->pn_type == TOK_NAME && PN_OP(pn2) != JSOP_SETNAME) {
+ /*
+ * x getter = y where x is a local or let variable is not
+ * supported.
+ */
+ js_ReportCompileErrorNumber(cx,
+ TS(cg->treeContext.parseContext),
+ pn2, JSREPORT_ERROR,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ (op == JSOP_GETTER)
+ ? js_getter_str
+ : js_setter_str);
+ return JS_FALSE;
+ }
+
+ /* We'll emit these prefix bytecodes after emitting the r.h.s. */
+ } else
+#endif
+ /* If += or similar, dup the left operand and get its value. */
+ if (op != JSOP_NOP) {
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (pn2->pn_op != JSOP_SETNAME) {
+ EMIT_UINT16_IMM_OP((pn2->pn_op == JSOP_SETGVAR)
+ ? JSOP_GETGVAR
+ : (pn2->pn_op == JSOP_SETARG)
+ ? JSOP_GETARG
+ : JSOP_GETLOCAL,
+ atomIndex);
+ break;
+ }
+ if (js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_GETXPROP, atomIndex);
+ break;
+ case TOK_DOT:
+ if (js_Emit1(cx, cg, JSOP_DUP) < 0)
+ return JS_FALSE;
+ if (pn2->pn_atom == cx->runtime->atomState.lengthAtom) {
+ if (js_Emit1(cx, cg, JSOP_LENGTH) < 0)
+ return JS_FALSE;
+ } else {
+ EMIT_INDEX_OP(JSOP_GETPROP, atomIndex);
+ }
+ break;
+ case TOK_LB:
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+#endif
+ if (js_Emit1(cx, cg, JSOP_DUP2) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_GETELEM) < 0)
+ return JS_FALSE;
+ break;
+ default:;
+ }
+ }
+
+ /* Now emit the right operand (it may affect the namespace). */
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+
+ /* If += etc., emit the binary operator with a decompiler note. */
+ if (op != JSOP_NOP) {
+ /*
+ * Take care to avoid SRC_ASSIGNOP if the left-hand side is a
+ * const declared in a function (i.e., with non-negative pn_slot
+ * and when pn_const is true), as in this case (just a bit further
+ * below) we will avoid emitting the assignment op.
+ */
+ if (pn2->pn_type != TOK_NAME ||
+ pn2->pn_slot < 0 ||
+ !pn2->pn_const) {
+ if (js_NewSrcNote(cx, cg, SRC_ASSIGNOP) < 0)
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+
+ /* Left parts such as a.b.c and a[b].c need a decompiler note. */
+ if (pn2->pn_type != TOK_NAME &&
+#if JS_HAS_DESTRUCTURING
+ pn2->pn_type != TOK_RB &&
+ pn2->pn_type != TOK_RC &&
+#endif
+ js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0) {
+ return JS_FALSE;
+ }
+
+ /* Finally, emit the specialized assignment bytecode. */
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (pn2->pn_slot >= 0) {
+ if (!pn2->pn_const)
+ EMIT_UINT16_IMM_OP(PN_OP(pn2), atomIndex);
+ break;
+ }
+ /* FALL THROUGH */
+ case TOK_DOT:
+ EMIT_INDEX_OP(PN_OP(pn2), atomIndex);
+ break;
+ case TOK_LB:
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+#endif
+ if (js_Emit1(cx, cg, JSOP_SETELEM) < 0)
+ return JS_FALSE;
+ break;
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ if (!EmitDestructuringOps(cx, cg, JSOP_SETNAME, pn2))
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (js_Emit1(cx, cg, JSOP_SETXMLNAME) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ default:
+ JS_ASSERT(0);
+ }
+ break;
+
+ case TOK_HOOK:
+ /* Emit the condition, then branch if false to the else part. */
+ if (!js_EmitTree(cx, cg, pn->pn_kid1))
+ return JS_FALSE;
+ noteIndex = js_NewSrcNote(cx, cg, SRC_COND);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ beq = EmitJump(cx, cg, JSOP_IFEQ, 0);
+ if (beq < 0 || !js_EmitTree(cx, cg, pn->pn_kid2))
+ return JS_FALSE;
+
+ /* Jump around else, fixup the branch, emit else, fixup jump. */
+ jmp = EmitJump(cx, cg, JSOP_GOTO, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, beq);
+
+ /*
+ * Because each branch pushes a single value, but our stack budgeting
+ * analysis ignores branches, we now have to adjust cg->stackDepth to
+ * ignore the value pushed by the first branch. Execution will follow
+ * only one path, so we must decrement cg->stackDepth.
+ *
+ * Failing to do this will foil code, such as the try/catch/finally
+ * exception handling code generator, that samples cg->stackDepth for
+ * use at runtime (JSOP_SETSP), or in let expression and block code
+ * generation, which must use the stack depth to compute local stack
+ * indexes correctly.
+ */
+ JS_ASSERT(cg->stackDepth > 0);
+ cg->stackDepth--;
+ if (!js_EmitTree(cx, cg, pn->pn_kid3))
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (!js_SetSrcNoteOffset(cx, cg, noteIndex, 0, jmp - beq))
+ return JS_FALSE;
+ break;
+
+ case TOK_OR:
+ case TOK_AND:
+ /*
+ * JSOP_OR converts the operand on the stack to boolean, and if true,
+ * leaves the original operand value on the stack and jumps; otherwise
+ * it pops and falls into the next bytecode, which evaluates the right
+ * operand. The jump goes around the right operand evaluation.
+ *
+ * JSOP_AND converts the operand on the stack to boolean, and if false,
+ * leaves the original operand value on the stack and jumps; otherwise
+ * it pops and falls into the right operand's bytecode.
+ */
+ if (pn->pn_arity == PN_BINARY) {
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0);
+ if (top < 0)
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ off = CG_OFFSET(cg);
+ pc = CG_CODE(cg, top);
+ CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, off - top);
+ *pc = pn->pn_op;
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ JS_ASSERT(pn->pn_head->pn_next->pn_next);
+
+ /* Left-associative operator chain: avoid too much recursion. */
+ pn2 = pn->pn_head;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ top = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0);
+ if (top < 0)
+ return JS_FALSE;
+
+ /* Emit nodes between the head and the tail. */
+ jmp = top;
+ while ((pn2 = pn2->pn_next)->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ off = EmitJump(cx, cg, JSOP_BACKPATCH_POP, 0);
+ if (off < 0)
+ return JS_FALSE;
+ if (!SetBackPatchDelta(cx, cg, CG_CODE(cg, jmp), off - jmp))
+ return JS_FALSE;
+ jmp = off;
+
+ }
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+
+ pn2 = pn->pn_head;
+ off = CG_OFFSET(cg);
+ do {
+ pc = CG_CODE(cg, top);
+ tmp = GetJumpOffset(cg, pc);
+ CHECK_AND_SET_JUMP_OFFSET(cx, cg, pc, off - top);
+ *pc = pn->pn_op;
+ top += tmp;
+ } while ((pn2 = pn2->pn_next)->pn_next);
+ }
+ break;
+
+ case TOK_BITOR:
+ case TOK_BITXOR:
+ case TOK_BITAND:
+ case TOK_EQOP:
+ case TOK_RELOP:
+ case TOK_IN:
+ case TOK_INSTANCEOF:
+ case TOK_SHOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ case TOK_STAR:
+ case TOK_DIVOP:
+ if (pn->pn_arity == PN_LIST) {
+ /* Left-associative operator chain: avoid too much recursion. */
+ pn2 = pn->pn_head;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ op = PN_OP(pn);
+ while ((pn2 = pn2->pn_next) != NULL) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+ } else {
+#if JS_HAS_XML_SUPPORT
+ uintN oldflags;
+
+ case TOK_DBLCOLON:
+ if (pn->pn_arity == PN_NAME) {
+ if (!js_EmitTree(cx, cg, pn->pn_expr))
+ return JS_FALSE;
+ if (!EmitAtomOp(cx, pn, PN_OP(pn), cg))
+ return JS_FALSE;
+ break;
+ }
+
+ /*
+ * Binary :: has a right operand that brackets arbitrary code,
+ * possibly including a let (a = b) ... expression. We must clear
+ * TCF_IN_FOR_INIT to avoid mis-compiling such beasts.
+ */
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+#endif
+
+ /* Binary operators that evaluate both operands unconditionally. */
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+#if JS_HAS_XML_SUPPORT
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+#endif
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_THROW:
+#if JS_HAS_XML_SUPPORT
+ case TOK_AT:
+ case TOK_DEFAULT:
+ JS_ASSERT(pn->pn_arity == PN_UNARY);
+ /* FALL THROUGH */
+#endif
+ case TOK_UNARYOP:
+ {
+ uintN oldflags;
+
+ /* Unary op, including unary +/-. */
+ op = PN_OP(pn);
+#if JS_HAS_XML_SUPPORT
+ if (op == JSOP_XMLNAME) {
+ if (!EmitXMLName(cx, pn, op, cg))
+ return JS_FALSE;
+ break;
+ }
+#endif
+ pn2 = pn->pn_kid;
+ if (op == JSOP_TYPEOF) {
+ for (pn3 = pn2; pn3->pn_type == TOK_RP; pn3 = pn3->pn_kid)
+ continue;
+ if (pn3->pn_type != TOK_NAME)
+ op = JSOP_TYPEOFEXPR;
+ }
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ break;
+ }
+
+ case TOK_INC:
+ case TOK_DEC:
+ /* Emit lvalue-specialized code for ++/-- operators. */
+ pn2 = pn->pn_kid;
+ JS_ASSERT(pn2->pn_type != TOK_RP);
+ op = PN_OP(pn);
+ switch (pn2->pn_type) {
+ default:
+ JS_ASSERT(pn2->pn_type == TOK_NAME);
+ pn2->pn_op = op;
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ op = PN_OP(pn2);
+ if (pn2->pn_slot >= 0) {
+ if (pn2->pn_const) {
+ /* Incrementing a declared const: just get its value. */
+ op = (JOF_OPTYPE(op) == JOF_ATOM)
+ ? JSOP_GETGVAR
+ : JSOP_GETLOCAL;
+ }
+ atomIndex = (jsatomid) pn2->pn_slot;
+ EMIT_UINT16_IMM_OP(op, atomIndex);
+ } else {
+ if (!EmitAtomOp(cx, pn2, op, cg))
+ return JS_FALSE;
+ }
+ break;
+ case TOK_DOT:
+ if (!EmitPropOp(cx, pn2, op, cg, JS_FALSE))
+ return JS_FALSE;
+ break;
+ case TOK_LB:
+ if (!EmitElemOp(cx, pn2, op, cg))
+ return JS_FALSE;
+ break;
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE,
+ CG_OFFSET(cg) - pn2->pn_offset) < 0) {
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ JS_ASSERT(pn2->pn_op == JSOP_SETXMLNAME);
+ if (!js_EmitTree(cx, cg, pn2->pn_kid))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_BINDXMLNAME) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ }
+ break;
+
+ case TOK_DELETE:
+ /*
+ * Under ECMA 3, deleting a non-reference returns true -- but alas we
+ * must evaluate the operand if it appears it might have side effects.
+ */
+ pn2 = pn->pn_kid;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ pn2->pn_op = JSOP_DELNAME;
+ if (!BindNameToSlot(cx, cg, pn2))
+ return JS_FALSE;
+ op = PN_OP(pn2);
+ if (op == JSOP_FALSE) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ } else {
+ if (!EmitAtomOp(cx, pn2, op, cg))
+ return JS_FALSE;
+ }
+ break;
+ case TOK_DOT:
+ if (!EmitPropOp(cx, pn2, JSOP_DELPROP, cg, JS_FALSE))
+ return JS_FALSE;
+ break;
+#if JS_HAS_XML_SUPPORT
+ case TOK_DBLDOT:
+ if (!EmitElemOp(cx, pn2, JSOP_DELDESC, cg))
+ return JS_FALSE;
+ break;
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_DELELEM) < 0)
+ return JS_FALSE;
+ break;
+#endif
+ case TOK_LB:
+ if (!EmitElemOp(cx, pn2, JSOP_DELELEM, cg))
+ return JS_FALSE;
+ break;
+ default:
+ /*
+ * If useless, just emit JSOP_TRUE; otherwise convert delete foo()
+ * to foo(), true (a comma expression, requiring SRC_PCDELTA).
+ */
+ useful = JS_FALSE;
+ if (!CheckSideEffects(cx, cg, pn2, &useful))
+ return JS_FALSE;
+ if (!useful) {
+ off = noteIndex = -1;
+ } else {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ off = CG_OFFSET(cg);
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_PCDELTA, 0);
+ if (noteIndex < 0 || js_Emit1(cx, cg, JSOP_POP) < 0)
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg, JSOP_TRUE) < 0)
+ return JS_FALSE;
+ if (noteIndex >= 0) {
+ tmp = CG_OFFSET(cg);
+ if (!js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0, tmp-off))
+ return JS_FALSE;
+ }
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_FILTER:
+ if (!js_EmitTree(cx, cg, pn->pn_left))
+ return JS_FALSE;
+ jmp = js_Emit3(cx, cg, JSOP_FILTER, 0, 0);
+ if (jmp < 0)
+ return JS_FALSE;
+ top = CG_OFFSET(cg);
+ if (!js_EmitTree(cx, cg, pn->pn_right))
+ return JS_FALSE;
+ CHECK_AND_SET_JUMP_OFFSET_AT(cx, cg, jmp);
+ if (EmitJump(cx, cg, JSOP_ENDFILTER, top - CG_OFFSET(cg)) < 0)
+ return JS_FALSE;
+ break;
+#endif
+
+ case TOK_DOT:
+ /*
+ * Pop a stack operand, convert it to object, get a property named by
+ * this bytecode's immediate-indexed atom operand, and push its value
+ * (not a reference to it).
+ */
+ ok = EmitPropOp(cx, pn, PN_OP(pn), cg, JS_FALSE);
+ break;
+
+ case TOK_LB:
+#if JS_HAS_XML_SUPPORT
+ case TOK_DBLDOT:
+#endif
+ /*
+ * Pop two operands, convert the left one to object and the right one
+ * to property name (atom or tagged int), get the named property, and
+ * push its value. Set the "obj" register to the result of ToObject
+ * on the left operand.
+ */
+ ok = EmitElemOp(cx, pn, PN_OP(pn), cg);
+ break;
+
+ case TOK_NEW:
+ case TOK_LP:
+ {
+ uintN oldflags;
+
+ /*
+ * Emit function call or operator new (constructor call) code.
+ * First, emit code for the left operand to evaluate the callable or
+ * constructable object expression.
+ */
+ pn2 = pn->pn_head;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ if (!EmitNameOp(cx, cg, pn2, JS_TRUE))
+ return JS_FALSE;
+ break;
+ case TOK_DOT:
+ if (!EmitPropOp(cx, pn2, PN_OP(pn2), cg, JS_TRUE))
+ return JS_FALSE;
+ break;
+ case TOK_LB:
+ JS_ASSERT(pn2->pn_op == JSOP_GETELEM);
+ if (!EmitElemOp(cx, pn2, JSOP_CALLELEM, cg))
+ return JS_FALSE;
+ break;
+ case TOK_UNARYOP:
+#if JS_HAS_XML_SUPPORT
+ if (pn2->pn_op == JSOP_XMLNAME) {
+ if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, cg))
+ return JS_FALSE;
+ break;
+ }
+#endif
+ /* FALL THROUGH */
+ default:
+ /*
+ * Push null as a placeholder for the global object, per ECMA-262
+ * 11.2.3 step 6. We use JSOP_NULLTHIS to distinguish this opcode
+ * from JSOP_NULL (see jstracer.cpp for one use-case).
+ */
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_NULLTHIS) < 0)
+ return JS_FALSE;
+ }
+
+ /* Remember start of callable-object bytecode for decompilation hint. */
+ off = top;
+
+ /*
+ * Emit code for each argument in order, then emit the JSOP_*CALL or
+ * JSOP_NEW bytecode with a two-byte immediate telling how many args
+ * were pushed on the operand stack.
+ */
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ for (pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
+ if (!js_EmitTree(cx, cg, pn3))
+ return JS_FALSE;
+ }
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - off) < 0)
+ return JS_FALSE;
+
+ argc = pn->pn_count - 1;
+ if (js_Emit3(cx, cg, PN_OP(pn), ARGC_HI(argc), ARGC_LO(argc)) < 0)
+ return JS_FALSE;
+ if (PN_OP(pn) == JSOP_EVAL)
+ EMIT_UINT16_IMM_OP(JSOP_LINENO, pn->pn_pos.begin.lineno);
+ break;
+ }
+
+ case TOK_LEXICALSCOPE:
+ {
+ JSParsedObjectBox *pob;
+ uintN count;
+
+ pob = pn->pn_pob;
+ js_PushBlockScope(&cg->treeContext, &stmtInfo, pob->object,
+ CG_OFFSET(cg));
+
+ /*
+ * If this lexical scope is not for a catch block, let block or let
+ * expression, or any kind of for loop (where the scope starts in the
+ * head after the first part if for (;;), else in the body if for-in);
+ * and if our container is top-level but not a function body, or else
+ * a block statement; then emit a SRC_BRACE note. All other container
+ * statements get braces by default from the decompiler.
+ */
+ noteIndex = -1;
+ type = PN_TYPE(pn->pn_expr);
+ if (type != TOK_CATCH && type != TOK_LET && type != TOK_FOR &&
+ (!(stmt = stmtInfo.down)
+ ? !(cg->treeContext.flags & TCF_IN_FUNCTION)
+ : stmt->type == STMT_BLOCK)) {
+#if defined DEBUG_brendanXXX || defined DEBUG_mrbkap
+ /* There must be no source note already output for the next op. */
+ JS_ASSERT(CG_NOTE_COUNT(cg) == 0 ||
+ CG_LAST_NOTE_OFFSET(cg) != CG_OFFSET(cg) ||
+ !GettableNoteForNextOp(cg));
+#endif
+ noteIndex = js_NewSrcNote2(cx, cg, SRC_BRACE, 0);
+ if (noteIndex < 0)
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(CG_OFFSET(cg) == top);
+ if (!EmitObjectOp(cx, pob, JSOP_ENTERBLOCK, cg))
+ return JS_FALSE;
+
+ if (!js_EmitTree(cx, cg, pn->pn_expr))
+ return JS_FALSE;
+
+ op = PN_OP(pn);
+ if (op == JSOP_LEAVEBLOCKEXPR) {
+ if (js_NewSrcNote2(cx, cg, SRC_PCBASE, CG_OFFSET(cg) - top) < 0)
+ return JS_FALSE;
+ } else {
+ if (noteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - top)) {
+ return JS_FALSE;
+ }
+ }
+
+ /* Emit the JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR opcode. */
+ count = OBJ_BLOCK_COUNT(cx, pob->object);
+ EMIT_UINT16_IMM_OP(op, count);
+
+ ok = js_PopStatementCG(cx, cg);
+ break;
+ }
+
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+ /* Let statements have their variable declarations on the left. */
+ if (pn->pn_arity == PN_BINARY) {
+ pn2 = pn->pn_right;
+ pn = pn->pn_left;
+ } else {
+ pn2 = NULL;
+ }
+
+ /* Non-null pn2 means that pn is the variable list from a let head. */
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ if (!EmitVariables(cx, cg, pn, pn2 != NULL, &noteIndex))
+ return JS_FALSE;
+
+ /* Thus non-null pn2 is the body of the let block or expression. */
+ tmp = CG_OFFSET(cg);
+ if (pn2 && !js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+
+ if (noteIndex >= 0 &&
+ !js_SetSrcNoteOffset(cx, cg, (uintN)noteIndex, 0,
+ CG_OFFSET(cg) - tmp)) {
+ return JS_FALSE;
+ }
+ break;
+#endif /* JS_HAS_BLOCK_SCOPE */
+
+#if JS_HAS_GENERATORS
+ case TOK_ARRAYPUSH: {
+ jsint slot;
+
+ /*
+ * The array object's stack index is in cg->arrayCompDepth. See below
+ * under the array initialiser code generator for array comprehension
+ * special casing.
+ */
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ slot = cg->arrayCompDepth;
+ slot = AdjustBlockSlot(cx, cg, slot);
+ if (slot < 0)
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(PN_OP(pn), slot);
+ break;
+ }
+#endif
+
+ case TOK_RB:
+#if JS_HAS_GENERATORS
+ case TOK_ARRAYCOMP:
+#endif
+ /*
+ * Emit code for [a, b, c] of the form:
+ *
+ * t = new Array; t[0] = a; t[1] = b; t[2] = c; t;
+ *
+ * but use a stack slot for t and avoid dup'ing and popping it using
+ * the JSOP_NEWINIT and JSOP_INITELEM bytecodes.
+ *
+ * If no sharp variable is defined and the initialiser is not for an
+ * array comprehension, use JSOP_NEWARRAY.
+ */
+ pn2 = pn->pn_head;
+ op = JSOP_NEWINIT; // FIXME: 260106 patch disabled for now
+
+#if JS_HAS_SHARP_VARS
+ if (pn2 && pn2->pn_type == TOK_DEFSHARP)
+ op = JSOP_NEWINIT;
+#endif
+#if JS_HAS_GENERATORS
+ if (pn->pn_type == TOK_ARRAYCOMP)
+ op = JSOP_NEWINIT;
+#endif
+
+ if (op == JSOP_NEWINIT &&
+ js_Emit2(cx, cg, op, (jsbytecode) JSProto_Array) < 0) {
+ return JS_FALSE;
+ }
+
+#if JS_HAS_SHARP_VARS
+ if (pn2 && pn2->pn_type == TOK_DEFSHARP) {
+ EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
+ pn2 = pn2->pn_next;
+ }
+#endif
+
+#if JS_HAS_GENERATORS
+ if (pn->pn_type == TOK_ARRAYCOMP) {
+ uintN saveDepth;
+
+ /*
+ * Pass the new array's stack index to the TOK_ARRAYPUSH case by
+ * storing it in pn->pn_extra, then simply traverse the TOK_FOR
+ * node and its kids under pn2 to generate this comprehension.
+ */
+ JS_ASSERT(cg->stackDepth > 0);
+ saveDepth = cg->arrayCompDepth;
+ cg->arrayCompDepth = (uint32) (cg->stackDepth - 1);
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ cg->arrayCompDepth = saveDepth;
+
+ /* Emit the usual op needed for decompilation. */
+ if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)
+ return JS_FALSE;
+ break;
+ }
+#endif /* JS_HAS_GENERATORS */
+
+ for (atomIndex = 0; pn2; atomIndex++, pn2 = pn2->pn_next) {
+ if (op == JSOP_NEWINIT && !EmitNumberOp(cx, atomIndex, cg))
+ return JS_FALSE;
+
+ if (pn2->pn_type == TOK_COMMA) {
+ if (js_Emit1(cx, cg, JSOP_HOLE) < 0)
+ return JS_FALSE;
+ } else {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ }
+
+ if (op == JSOP_NEWINIT && js_Emit1(cx, cg, JSOP_INITELEM) < 0)
+ return JS_FALSE;
+ }
+
+ if (pn->pn_extra & PNX_ENDCOMMA) {
+ /* Emit a source note so we know to decompile an extra comma. */
+ if (js_NewSrcNote(cx, cg, SRC_CONTINUE) < 0)
+ return JS_FALSE;
+ }
+
+ if (op == JSOP_NEWARRAY) {
+ JS_ASSERT(atomIndex == pn->pn_count);
+ off = js_EmitN(cx, cg, op, 3);
+ if (off < 0)
+ return JS_FALSE;
+ pc = CG_CODE(cg, off);
+ SET_UINT24(pc, atomIndex);
+ UpdateDepth(cx, cg, off);
+ } else {
+ /* Emit an op for sharp array cleanup and decompilation. */
+ if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_RC:
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (pn->pn_extra & PNX_SHORTHAND) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), pn, JSREPORT_ERROR,
+ JSMSG_BAD_OBJECT_INIT);
+ return JS_FALSE;
+ }
+#endif
+ /*
+ * Emit code for {p:a, '%q':b, 2:c} of the form:
+ *
+ * t = new Object; t.p = a; t['%q'] = b; t[2] = c; t;
+ *
+ * but use a stack slot for t and avoid dup'ing and popping it via
+ * the JSOP_NEWINIT and JSOP_INITELEM/JSOP_INITPROP bytecodes.
+ */
+ if (js_Emit2(cx, cg, JSOP_NEWINIT, (jsbytecode) JSProto_Object) < 0)
+ return JS_FALSE;
+
+ pn2 = pn->pn_head;
+#if JS_HAS_SHARP_VARS
+ if (pn2 && pn2->pn_type == TOK_DEFSHARP) {
+ EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid)pn2->pn_num);
+ pn2 = pn2->pn_next;
+ }
+#endif
+
+ for (; pn2; pn2 = pn2->pn_next) {
+ /* Emit an index for t[2], else map an atom for t.p or t['%q']. */
+ pn3 = pn2->pn_left;
+ if (pn3->pn_type == TOK_NUMBER) {
+#ifdef __GNUC__
+ ale = NULL; /* quell GCC overwarning */
+#endif
+ if (!EmitNumberOp(cx, pn3->pn_dval, cg))
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(pn3->pn_type == TOK_NAME ||
+ pn3->pn_type == TOK_STRING);
+ ale = js_IndexAtom(cx, pn3->pn_atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ }
+
+ /* Emit code for the property initializer. */
+ if (!js_EmitTree(cx, cg, pn2->pn_right))
+ return JS_FALSE;
+
+#if JS_HAS_GETTER_SETTER
+ op = PN_OP(pn2);
+ if (op == JSOP_GETTER || op == JSOP_SETTER) {
+ if (js_Emit1(cx, cg, op) < 0)
+ return JS_FALSE;
+ }
+#endif
+ /* Annotate JSOP_INITELEM so we decompile 2:c and not just c. */
+ if (pn3->pn_type == TOK_NUMBER) {
+ if (js_NewSrcNote(cx, cg, SRC_INITPROP) < 0)
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_INITELEM) < 0)
+ return JS_FALSE;
+ } else {
+ EMIT_INDEX_OP(JSOP_INITPROP, ALE_INDEX(ale));
+ }
+ }
+
+ /* Emit an op for sharpArray cleanup and decompilation. */
+ if (js_Emit1(cx, cg, JSOP_ENDINIT) < 0)
+ return JS_FALSE;
+ break;
+
+#if JS_HAS_SHARP_VARS
+ case TOK_DEFSHARP:
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ EMIT_UINT16_IMM_OP(JSOP_DEFSHARP, (jsatomid) pn->pn_num);
+ break;
+
+ case TOK_USESHARP:
+ EMIT_UINT16_IMM_OP(JSOP_USESHARP, (jsatomid) pn->pn_num);
+ break;
+#endif /* JS_HAS_SHARP_VARS */
+
+ case TOK_RP:
+ {
+ uintN oldflags;
+
+ /*
+ * The node for (e) has e as its kid, enabling users who want to nest
+ * assignment expressions in conditions to avoid the error correction
+ * done by Condition (from x = y to x == y) by double-parenthesizing.
+ */
+ oldflags = cg->treeContext.flags;
+ cg->treeContext.flags &= ~TCF_IN_FOR_INIT;
+ if (!js_EmitTree(cx, cg, pn->pn_kid))
+ return JS_FALSE;
+ cg->treeContext.flags |= oldflags & TCF_IN_FOR_INIT;
+ break;
+ }
+
+ case TOK_NAME:
+ if (!EmitNameOp(cx, cg, pn, JS_FALSE))
+ return JS_FALSE;
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLATTR:
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_XMLCDATA:
+ case TOK_XMLCOMMENT:
+#endif
+ case TOK_STRING:
+ ok = EmitAtomOp(cx, pn, PN_OP(pn), cg);
+ break;
+
+ case TOK_NUMBER:
+ ok = EmitNumberOp(cx, pn->pn_dval, cg);
+ break;
+
+ case TOK_REGEXP:
+ /*
+ * If the regexp's script is one-shot, we can avoid the extra
+ * fork-on-exec costs of JSOP_REGEXP by selecting JSOP_OBJECT.
+ * Otherwise, to avoid incorrect proto, parent, and lastIndex
+ * sharing among threads and sequentially across re-execution,
+ * select JSOP_REGEXP.
+ */
+ JS_ASSERT(pn->pn_op == JSOP_REGEXP);
+ if (cg->treeContext.flags & TCF_COMPILE_N_GO) {
+ ok = EmitObjectOp(cx, pn->pn_pob, JSOP_OBJECT, cg);
+ } else {
+ ok = EmitIndexOp(cx, JSOP_REGEXP,
+ IndexParsedObject(pn->pn_pob, &cg->regexpList),
+ cg);
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_ANYNAME:
+#endif
+ case TOK_PRIMARY:
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ break;
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ case TOK_DEBUGGER:
+ if (js_Emit1(cx, cg, JSOP_DEBUGGER) < 0)
+ return JS_FALSE;
+ break;
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLELEM:
+ case TOK_XMLLIST:
+ if (pn->pn_op == JSOP_XMLOBJECT) {
+ ok = EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg);
+ break;
+ }
+
+ JS_ASSERT(pn->pn_type == TOK_XMLLIST || pn->pn_count != 0);
+ switch (pn->pn_head ? pn->pn_head->pn_type : TOK_XMLLIST) {
+ case TOK_XMLETAGO:
+ JS_ASSERT(0);
+ /* FALL THROUGH */
+ case TOK_XMLPTAGC:
+ case TOK_XMLSTAGO:
+ break;
+ default:
+ if (js_Emit1(cx, cg, JSOP_STARTXML) < 0)
+ return JS_FALSE;
+ }
+
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_LC &&
+ js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) {
+ return JS_FALSE;
+ }
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+ }
+
+ if (pn->pn_extra & PNX_XMLROOT) {
+ if (pn->pn_count == 0) {
+ JS_ASSERT(pn->pn_type == TOK_XMLLIST);
+ atom = cx->runtime->atomState.emptyAtom;
+ ale = js_IndexAtom(cx, atom, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_STRING, ALE_INDEX(ale));
+ }
+ if (js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ }
+#ifdef DEBUG
+ else
+ JS_ASSERT(pn->pn_count != 0);
+#endif
+ break;
+
+ case TOK_XMLPTAGC:
+ if (pn->pn_op == JSOP_XMLOBJECT) {
+ ok = EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg);
+ break;
+ }
+ /* FALL THROUGH */
+
+ case TOK_XMLSTAGO:
+ case TOK_XMLETAGO:
+ {
+ uint32 i;
+
+ if (js_Emit1(cx, cg, JSOP_STARTXML) < 0)
+ return JS_FALSE;
+
+ ale = js_IndexAtom(cx,
+ (pn->pn_type == TOK_XMLETAGO)
+ ? cx->runtime->atomState.etagoAtom
+ : cx->runtime->atomState.stagoAtom,
+ &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_STRING, ALE_INDEX(ale));
+
+ JS_ASSERT(pn->pn_count != 0);
+ pn2 = pn->pn_head;
+ if (pn2->pn_type == TOK_LC && js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0)
+ return JS_FALSE;
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+
+ for (pn2 = pn2->pn_next, i = 0; pn2; pn2 = pn2->pn_next, i++) {
+ if (pn2->pn_type == TOK_LC &&
+ js_Emit1(cx, cg, JSOP_STARTXMLEXPR) < 0) {
+ return JS_FALSE;
+ }
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if ((i & 1) && pn2->pn_type == TOK_LC) {
+ if (js_Emit1(cx, cg, JSOP_TOATTRVAL) < 0)
+ return JS_FALSE;
+ }
+ if (js_Emit1(cx, cg,
+ (i & 1) ? JSOP_ADDATTRVAL : JSOP_ADDATTRNAME) < 0) {
+ return JS_FALSE;
+ }
+ }
+
+ ale = js_IndexAtom(cx,
+ (pn->pn_type == TOK_XMLPTAGC)
+ ? cx->runtime->atomState.ptagcAtom
+ : cx->runtime->atomState.tagcAtom,
+ &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ EMIT_INDEX_OP(JSOP_STRING, ALE_INDEX(ale));
+ if (js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+
+ if ((pn->pn_extra & PNX_XMLROOT) && js_Emit1(cx, cg, PN_OP(pn)) < 0)
+ return JS_FALSE;
+ break;
+ }
+
+ case TOK_XMLNAME:
+ if (pn->pn_arity == PN_LIST) {
+ JS_ASSERT(pn->pn_count != 0);
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_EmitTree(cx, cg, pn2))
+ return JS_FALSE;
+ if (pn2 != pn->pn_head && js_Emit1(cx, cg, JSOP_ADD) < 0)
+ return JS_FALSE;
+ }
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_NULLARY);
+ ok = (pn->pn_op == JSOP_OBJECT)
+ ? EmitObjectOp(cx, pn->pn_pob, PN_OP(pn), cg)
+ : EmitAtomOp(cx, pn, PN_OP(pn), cg);
+ }
+ break;
+
+ case TOK_XMLPI:
+ ale = js_IndexAtom(cx, pn->pn_atom2, &cg->atomList);
+ if (!ale)
+ return JS_FALSE;
+ if (!EmitIndexOp(cx, JSOP_QNAMEPART, ALE_INDEX(ale), cg))
+ return JS_FALSE;
+ if (!EmitAtomOp(cx, pn, JSOP_XMLPI, cg))
+ return JS_FALSE;
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ default:
+ JS_ASSERT(0);
+ }
+
+ if (ok && --cg->emitLevel == 0 && cg->spanDeps)
+ ok = OptimizeSpanDeps(cx, cg);
+
+ return ok;
+}
+
+/*
+ * We should try to get rid of offsetBias (always 0 or 1, where 1 is
+ * JSOP_{NOP,POP}_LENGTH), which is used only by SRC_FOR and SRC_DECL.
+ */
+JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[] = {
+ {"null", 0, 0, 0},
+ {"if", 0, 0, 0},
+ {"if-else", 2, 0, 1},
+ {"for", 3, 1, 1},
+ {"while", 1, 0, 1},
+ {"continue", 0, 0, 0},
+ {"decl", 1, 1, 1},
+ {"pcdelta", 1, 0, 1},
+ {"assignop", 0, 0, 0},
+ {"cond", 1, 0, 1},
+ {"brace", 1, 0, 1},
+ {"hidden", 0, 0, 0},
+ {"pcbase", 1, 0, -1},
+ {"label", 1, 0, 0},
+ {"labelbrace", 1, 0, 0},
+ {"endbrace", 0, 0, 0},
+ {"break2label", 1, 0, 0},
+ {"cont2label", 1, 0, 0},
+ {"switch", 2, 0, 1},
+ {"funcdef", 1, 0, 0},
+ {"catch", 1, 0, 1},
+ {"extended", -1, 0, 0},
+ {"newline", 0, 0, 0},
+ {"setline", 1, 0, 0},
+ {"xdelta", 0, 0, 0},
+};
+
+static intN
+AllocSrcNote(JSContext *cx, JSCodeGenerator *cg)
+{
+ intN index;
+ JSArenaPool *pool;
+ size_t size;
+
+ index = CG_NOTE_COUNT(cg);
+ if (((uintN)index & CG_NOTE_MASK(cg)) == 0) {
+ pool = cg->notePool;
+ size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
+ if (!CG_NOTES(cg)) {
+ /* Allocate the first note array lazily; leave noteMask alone. */
+ JS_ARENA_ALLOCATE_CAST(CG_NOTES(cg), jssrcnote *, pool, size);
+ } else {
+ /* Grow by doubling note array size; update noteMask on success. */
+ JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
+ if (CG_NOTES(cg))
+ CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
+ }
+ if (!CG_NOTES(cg)) {
+ js_ReportOutOfScriptQuota(cx);
+ return -1;
+ }
+ }
+
+ CG_NOTE_COUNT(cg) = index + 1;
+ return index;
+}
+
+intN
+js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type)
+{
+ intN index, n;
+ jssrcnote *sn;
+ ptrdiff_t offset, delta, xdelta;
+
+ /*
+ * Claim a note slot in CG_NOTES(cg) by growing it if necessary and then
+ * incrementing CG_NOTE_COUNT(cg).
+ */
+ index = AllocSrcNote(cx, cg);
+ if (index < 0)
+ return -1;
+ sn = &CG_NOTES(cg)[index];
+
+ /*
+ * Compute delta from the last annotated bytecode's offset. If it's too
+ * big to fit in sn, allocate one or more xdelta notes and reset sn.
+ */
+ offset = CG_OFFSET(cg);
+ delta = offset - CG_LAST_NOTE_OFFSET(cg);
+ CG_LAST_NOTE_OFFSET(cg) = offset;
+ if (delta >= SN_DELTA_LIMIT) {
+ do {
+ xdelta = JS_MIN(delta, SN_XDELTA_MASK);
+ SN_MAKE_XDELTA(sn, xdelta);
+ delta -= xdelta;
+ index = AllocSrcNote(cx, cg);
+ if (index < 0)
+ return -1;
+ sn = &CG_NOTES(cg)[index];
+ } while (delta >= SN_DELTA_LIMIT);
+ }
+
+ /*
+ * Initialize type and delta, then allocate the minimum number of notes
+ * needed for type's arity. Usually, we won't need more, but if an offset
+ * does take two bytes, js_SetSrcNoteOffset will grow CG_NOTES(cg).
+ */
+ SN_MAKE_NOTE(sn, type, delta);
+ for (n = (intN)js_SrcNoteSpec[type].arity; n > 0; n--) {
+ if (js_NewSrcNote(cx, cg, SRC_NULL) < 0)
+ return -1;
+ }
+ return index;
+}
+
+intN
+js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset)
+{
+ intN index;
+
+ index = js_NewSrcNote(cx, cg, type);
+ if (index >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset))
+ return -1;
+ }
+ return index;
+}
+
+intN
+js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset1, ptrdiff_t offset2)
+{
+ intN index;
+
+ index = js_NewSrcNote(cx, cg, type);
+ if (index >= 0) {
+ if (!js_SetSrcNoteOffset(cx, cg, index, 0, offset1))
+ return -1;
+ if (!js_SetSrcNoteOffset(cx, cg, index, 1, offset2))
+ return -1;
+ }
+ return index;
+}
+
+static JSBool
+GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg)
+{
+ JSArenaPool *pool;
+ size_t size;
+
+ /* Grow by doubling note array size; update noteMask on success. */
+ pool = cg->notePool;
+ size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1);
+ JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size);
+ if (!CG_NOTES(cg)) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1;
+ return JS_TRUE;
+}
+
+jssrcnote *
+js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
+ ptrdiff_t delta)
+{
+ ptrdiff_t base, limit, newdelta, diff;
+ intN index;
+
+ /*
+ * Called only from OptimizeSpanDeps and js_FinishTakingSrcNotes to add to
+ * main script note deltas, and only by a small positive amount.
+ */
+ JS_ASSERT(cg->current == &cg->main);
+ JS_ASSERT((unsigned) delta < (unsigned) SN_XDELTA_LIMIT);
+
+ base = SN_DELTA(sn);
+ limit = SN_IS_XDELTA(sn) ? SN_XDELTA_LIMIT : SN_DELTA_LIMIT;
+ newdelta = base + delta;
+ if (newdelta < limit) {
+ SN_SET_DELTA(sn, newdelta);
+ } else {
+ index = sn - cg->main.notes;
+ if ((cg->main.noteCount & cg->main.noteMask) == 0) {
+ if (!GrowSrcNotes(cx, cg))
+ return NULL;
+ sn = cg->main.notes + index;
+ }
+ diff = cg->main.noteCount - index;
+ cg->main.noteCount++;
+ memmove(sn + 1, sn, SRCNOTE_SIZE(diff));
+ SN_MAKE_XDELTA(sn, delta);
+ sn++;
+ }
+ return sn;
+}
+
+JS_FRIEND_API(uintN)
+js_SrcNoteLength(jssrcnote *sn)
+{
+ uintN arity;
+ jssrcnote *base;
+
+ arity = (intN)js_SrcNoteSpec[SN_TYPE(sn)].arity;
+ for (base = sn++; arity; sn++, arity--) {
+ if (*sn & SN_3BYTE_OFFSET_FLAG)
+ sn += 2;
+ }
+ return sn - base;
+}
+
+JS_FRIEND_API(ptrdiff_t)
+js_GetSrcNoteOffset(jssrcnote *sn, uintN which)
+{
+ /* Find the offset numbered which (i.e., skip exactly which offsets). */
+ JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
+ JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
+ for (sn++; which; sn++, which--) {
+ if (*sn & SN_3BYTE_OFFSET_FLAG)
+ sn += 2;
+ }
+ if (*sn & SN_3BYTE_OFFSET_FLAG) {
+ return (ptrdiff_t)(((uint32)(sn[0] & SN_3BYTE_OFFSET_MASK) << 16)
+ | (sn[1] << 8)
+ | sn[2]);
+ }
+ return (ptrdiff_t)*sn;
+}
+
+JSBool
+js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
+ uintN which, ptrdiff_t offset)
+{
+ jssrcnote *sn;
+ ptrdiff_t diff;
+
+ if ((jsuword)offset >= (jsuword)((ptrdiff_t)SN_3BYTE_OFFSET_FLAG << 16)) {
+ ReportStatementTooLarge(cx, cg);
+ return JS_FALSE;
+ }
+
+ /* Find the offset numbered which (i.e., skip exactly which offsets). */
+ sn = &CG_NOTES(cg)[index];
+ JS_ASSERT(SN_TYPE(sn) != SRC_XDELTA);
+ JS_ASSERT((intN) which < js_SrcNoteSpec[SN_TYPE(sn)].arity);
+ for (sn++; which; sn++, which--) {
+ if (*sn & SN_3BYTE_OFFSET_FLAG)
+ sn += 2;
+ }
+
+ /* See if the new offset requires three bytes. */
+ if (offset > (ptrdiff_t)SN_3BYTE_OFFSET_MASK) {
+ /* Maybe this offset was already set to a three-byte value. */
+ if (!(*sn & SN_3BYTE_OFFSET_FLAG)) {
+ /* Losing, need to insert another two bytes for this offset. */
+ index = PTRDIFF(sn, CG_NOTES(cg), jssrcnote);
+
+ /*
+ * Simultaneously test to see if the source note array must grow to
+ * accomodate either the first or second byte of additional storage
+ * required by this 3-byte offset.
+ */
+ if (((CG_NOTE_COUNT(cg) + 1) & CG_NOTE_MASK(cg)) <= 1) {
+ if (!GrowSrcNotes(cx, cg))
+ return JS_FALSE;
+ sn = CG_NOTES(cg) + index;
+ }
+ CG_NOTE_COUNT(cg) += 2;
+
+ diff = CG_NOTE_COUNT(cg) - (index + 3);
+ JS_ASSERT(diff >= 0);
+ if (diff > 0)
+ memmove(sn + 3, sn + 1, SRCNOTE_SIZE(diff));
+ }
+ *sn++ = (jssrcnote)(SN_3BYTE_OFFSET_FLAG | (offset >> 16));
+ *sn++ = (jssrcnote)(offset >> 8);
+ }
+ *sn = (jssrcnote)offset;
+ return JS_TRUE;
+}
+
+#ifdef DEBUG_notme
+#define DEBUG_srcnotesize
+#endif
+
+#ifdef DEBUG_srcnotesize
+#define NBINS 10
+static uint32 hist[NBINS];
+
+void DumpSrcNoteSizeHist()
+{
+ static FILE *fp;
+ int i, n;
+
+ if (!fp) {
+ fp = fopen("/tmp/srcnotes.hist", "w");
+ if (!fp)
+ return;
+ setvbuf(fp, NULL, _IONBF, 0);
+ }
+ fprintf(fp, "SrcNote size histogram:\n");
+ for (i = 0; i < NBINS; i++) {
+ fprintf(fp, "%4u %4u ", JS_BIT(i), hist[i]);
+ for (n = (int) JS_HOWMANY(hist[i], 10); n > 0; --n)
+ fputc('*', fp);
+ fputc('\n', fp);
+ }
+ fputc('\n', fp);
+}
+#endif
+
+/*
+ * Fill in the storage at notes with prolog and main srcnotes; the space at
+ * notes was allocated using the CG_COUNT_FINAL_SRCNOTES macro from jsemit.h.
+ * SO DON'T CHANGE THIS FUNCTION WITHOUT AT LEAST CHECKING WHETHER jsemit.h's
+ * CG_COUNT_FINAL_SRCNOTES MACRO NEEDS CORRESPONDING CHANGES!
+ */
+JSBool
+js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes)
+{
+ uintN prologCount, mainCount, totalCount;
+ ptrdiff_t offset, delta;
+ jssrcnote *sn;
+
+ JS_ASSERT(cg->current == &cg->main);
+
+ prologCount = cg->prolog.noteCount;
+ if (prologCount && cg->prolog.currentLine != cg->firstLine) {
+ CG_SWITCH_TO_PROLOG(cg);
+ if (js_NewSrcNote2(cx, cg, SRC_SETLINE, (ptrdiff_t)cg->firstLine) < 0)
+ return JS_FALSE;
+ prologCount = cg->prolog.noteCount;
+ CG_SWITCH_TO_MAIN(cg);
+ } else {
+ /*
+ * Either no prolog srcnotes, or no line number change over prolog.
+ * We don't need a SRC_SETLINE, but we may need to adjust the offset
+ * of the first main note, by adding to its delta and possibly even
+ * prepending SRC_XDELTA notes to it to account for prolog bytecodes
+ * that came at and after the last annotated bytecode.
+ */
+ offset = CG_PROLOG_OFFSET(cg) - cg->prolog.lastNoteOffset;
+ JS_ASSERT(offset >= 0);
+ if (offset > 0 && cg->main.noteCount != 0) {
+ /* NB: Use as much of the first main note's delta as we can. */
+ sn = cg->main.notes;
+ delta = SN_IS_XDELTA(sn)
+ ? SN_XDELTA_MASK - (*sn & SN_XDELTA_MASK)
+ : SN_DELTA_MASK - (*sn & SN_DELTA_MASK);
+ if (offset < delta)
+ delta = offset;
+ for (;;) {
+ if (!js_AddToSrcNoteDelta(cx, cg, sn, delta))
+ return JS_FALSE;
+ offset -= delta;
+ if (offset == 0)
+ break;
+ delta = JS_MIN(offset, SN_XDELTA_MASK);
+ sn = cg->main.notes;
+ }
+ }
+ }
+
+ mainCount = cg->main.noteCount;
+ totalCount = prologCount + mainCount;
+ if (prologCount)
+ memcpy(notes, cg->prolog.notes, SRCNOTE_SIZE(prologCount));
+ memcpy(notes + prologCount, cg->main.notes, SRCNOTE_SIZE(mainCount));
+ SN_MAKE_TERMINATOR(&notes[totalCount]);
+
+#ifdef DEBUG_notme
+ { int bin = JS_CeilingLog2(totalCount);
+ if (bin >= NBINS)
+ bin = NBINS - 1;
+ ++hist[bin];
+ }
+#endif
+ return JS_TRUE;
+}
+
+static JSBool
+NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
+ uintN stackDepth, size_t start, size_t end)
+{
+ JSTryNode *tryNode;
+
+ JS_ASSERT((uintN)(uint16)stackDepth == stackDepth);
+ JS_ASSERT(start <= end);
+ JS_ASSERT((size_t)(uint32)start == start);
+ JS_ASSERT((size_t)(uint32)end == end);
+
+ JS_ARENA_ALLOCATE_TYPE(tryNode, JSTryNode, &cx->tempPool);
+ if (!tryNode) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+
+ tryNode->note.kind = kind;
+ tryNode->note.stackDepth = (uint16)stackDepth;
+ tryNode->note.start = (uint32)start;
+ tryNode->note.length = (uint32)(end - start);
+ tryNode->prev = cg->lastTryNode;
+ cg->lastTryNode = tryNode;
+ cg->ntrynotes++;
+ return JS_TRUE;
+}
+
+void
+js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array)
+{
+ JSTryNode *tryNode;
+ JSTryNote *tn;
+
+ JS_ASSERT(array->length > 0 && array->length == cg->ntrynotes);
+ tn = array->vector + array->length;
+ tryNode = cg->lastTryNode;
+ do {
+ *--tn = tryNode->note;
+ } while ((tryNode = tryNode->prev) != NULL);
+ JS_ASSERT(tn == array->vector);
+}
+
+/*
+ * Find the index of the given object for code generator.
+ *
+ * Since the emitter refers to each parsed object only once, for the index we
+ * use the number of already indexes objects. We also add the object to a list
+ * to convert the list to a fixed-size array when we complete code generation,
+ * see FinishParsedObjects bellow.
+ *
+ * Most of the objects go to JSCodeGenerator.objectList but for regexp we use
+ * a separated JSCodeGenerator.regexpList. In this way the emitted index can
+ * be directly used to store and fetch a reference to a cloned RegExp object
+ * that shares the same JSRegExp private data created for the object literal
+ * in pob. We need clones to hold lastIndex and other direct properties that
+ * should not be shared among threads sharing a precompiled function or
+ * script.
+ *
+ * If the code being compiled is function code, allocate a reserved slot in
+ * the cloned function object that shares its precompiled script with other
+ * cloned function objects and with the compiler-created clone-parent. There
+ * are nregexps = JS_SCRIPT_REGEXPS(script)->length such reserved slots in each
+ * function object cloned from fun->object. NB: during compilation, a funobj
+ * slots element must never be allocated, because js_AllocSlot could hand out
+ * one of the slots that should be given to a regexp clone.
+ *
+ * If the code being compiled is global code, the cloned regexp are stored in
+ * fp->vars slot after cg->treeContext.ngvars and to protect regexp slots from
+ * GC we set fp->nvars to ngvars + nregexps.
+ *
+ * The slots initially contain undefined or null. We populate them lazily when
+ * JSOP_REGEXP is executed for the first time.
+ *
+ * Why clone regexp objects? ECMA specifies that when a regular expression
+ * literal is scanned, a RegExp object is created. In the spec, compilation
+ * and execution happen indivisibly, but in this implementation and many of
+ * its embeddings, code is precompiled early and re-executed in multiple
+ * threads, or using multiple global objects, or both, for efficiency.
+ *
+ * In such cases, naively following ECMA leads to wrongful sharing of RegExp
+ * objects, which makes for collisions on the lastIndex property (especially
+ * for global regexps) and on any ad-hoc properties. Also, __proto__ and
+ * __parent__ refer to the pre-compilation prototype and global objects, a
+ * pigeon-hole problem for instanceof tests.
+ */
+static uintN
+IndexParsedObject(JSParsedObjectBox *pob, JSEmittedObjectList *list)
+{
+ JS_ASSERT(!pob->emitLink);
+ pob->emitLink = list->lastPob;
+ list->lastPob = pob;
+ return list->length++;
+}
+
+void
+FinishParsedObjects(JSEmittedObjectList *emittedList, JSObjectArray *array)
+{
+ JSObject **cursor;
+ JSParsedObjectBox *pob;
+
+ JS_ASSERT(emittedList->length <= INDEX_LIMIT);
+ JS_ASSERT(emittedList->length == array->length);
+
+ cursor = array->vector + array->length;
+ pob = emittedList->lastPob;
+ do {
+ --cursor;
+ JS_ASSERT(!*cursor);
+ *cursor = pob->object;
+ } while ((pob = pob->emitLink) != NULL);
+ JS_ASSERT(cursor == array->vector);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsemit.h b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.h
new file mode 100644
index 0000000..4e39f6c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsemit.h
@@ -0,0 +1,777 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsemit_h___
+#define jsemit_h___
+/*
+ * JS bytecode generation.
+ */
+
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jsatom.h"
+#include "jsopcode.h"
+#include "jsscript.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * NB: If you add enumerators for scope statements, add them between STMT_WITH
+ * and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
+ * non-looping statement enumerators, add them before STMT_DO_LOOP or you will
+ * break the STMT_TYPE_IS_LOOP macro.
+ *
+ * Also remember to keep the statementName array in jsemit.c in sync.
+ */
+typedef enum JSStmtType {
+ STMT_LABEL, /* labeled statement: L: s */
+ STMT_IF, /* if (then) statement */
+ STMT_ELSE, /* else clause of if statement */
+ STMT_SEQ, /* synthetic sequence of statements */
+ STMT_BLOCK, /* compound statement: { s1[;... sN] } */
+ STMT_SWITCH, /* switch statement */
+ STMT_WITH, /* with statement */
+ STMT_CATCH, /* catch block */
+ STMT_TRY, /* try block */
+ STMT_FINALLY, /* finally block */
+ STMT_SUBROUTINE, /* gosub-target subroutine body */
+ STMT_DO_LOOP, /* do/while loop statement */
+ STMT_FOR_LOOP, /* for loop statement */
+ STMT_FOR_IN_LOOP, /* for/in loop statement */
+ STMT_WHILE_LOOP, /* while loop statement */
+ STMT_LIMIT
+} JSStmtType;
+
+#define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))
+
+/*
+ * A comment on the encoding of the JSStmtType enum and type-testing macros:
+ *
+ * STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may
+ * become, a lexical scope. It therefore includes block and switch (the two
+ * low-numbered "maybe" scope types) and excludes with (with has dynamic scope
+ * pending the "reformed with" in ES4/JS2). It includes all try-catch-finally
+ * types, which are high-numbered maybe-scope types.
+ *
+ * STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
+ * links to other scoping statement info records. It excludes the two early
+ * "maybe" types, block and switch, as well as the try and both finally types,
+ * since try and the other trailing maybe-scope types don't need block scope
+ * unless they contain let declarations.
+ *
+ * We treat WITH as a static scope because it prevents lexical binding from
+ * continuing further up the static scope chain. With the lost "reformed with"
+ * proposal for ES4, we would be able to model it statically, too.
+ */
+#define STMT_TYPE_MAYBE_SCOPE(type) \
+ (type != STMT_WITH && \
+ STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))
+
+#define STMT_TYPE_LINKS_SCOPE(type) \
+ STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)
+
+#define STMT_TYPE_IS_TRYING(type) \
+ STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)
+
+#define STMT_TYPE_IS_LOOP(type) ((type) >= STMT_DO_LOOP)
+
+#define STMT_MAYBE_SCOPE(stmt) STMT_TYPE_MAYBE_SCOPE((stmt)->type)
+#define STMT_LINKS_SCOPE(stmt) (STMT_TYPE_LINKS_SCOPE((stmt)->type) || \
+ ((stmt)->flags & SIF_SCOPE))
+#define STMT_IS_TRYING(stmt) STMT_TYPE_IS_TRYING((stmt)->type)
+#define STMT_IS_LOOP(stmt) STMT_TYPE_IS_LOOP((stmt)->type)
+
+typedef struct JSStmtInfo JSStmtInfo;
+
+struct JSStmtInfo {
+ uint16 type; /* statement type */
+ uint16 flags; /* flags, see below */
+ ptrdiff_t update; /* loop update offset (top if none) */
+ ptrdiff_t breaks; /* offset of last break in loop */
+ ptrdiff_t continues; /* offset of last continue in loop */
+ union {
+ JSAtom *label; /* name of LABEL */
+ JSObject *blockObj; /* block scope object */
+ } u;
+ JSStmtInfo *down; /* info for enclosing statement */
+ JSStmtInfo *downScope; /* next enclosing lexical scope */
+};
+
+#define SIF_SCOPE 0x0001 /* statement has its own lexical scope */
+#define SIF_BODY_BLOCK 0x0002 /* STMT_BLOCK type is a function body */
+#define SIF_FOR_BLOCK 0x0004 /* for (let ...) induced block scope */
+
+/*
+ * To reuse space in JSStmtInfo, rename breaks and continues for use during
+ * try/catch/finally code generation and backpatching. To match most common
+ * use cases, the macro argument is a struct, not a struct pointer. Only a
+ * loop, switch, or label statement info record can have breaks and continues,
+ * and only a for loop has an update backpatch chain, so it's safe to overlay
+ * these for the "trying" JSStmtTypes.
+ */
+#define CATCHNOTE(stmt) ((stmt).update)
+#define GOSUBS(stmt) ((stmt).breaks)
+#define GUARDJUMP(stmt) ((stmt).continues)
+
+#define AT_TOP_LEVEL(tc) \
+ (!(tc)->topStmt || ((tc)->topStmt->flags & SIF_BODY_BLOCK))
+
+#define SET_STATEMENT_TOP(stmt, top) \
+ ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
+
+struct JSTreeContext { /* tree context for semantic checks */
+ uint16 flags; /* statement state flags, see below */
+ uint16 ngvars; /* max. no. of global variables/regexps */
+ JSStmtInfo *topStmt; /* top of statement info stack */
+ JSStmtInfo *topScopeStmt; /* top lexical scope statement */
+ JSObject *blockChain; /* compile time block scope chain (NB: one
+ deeper than the topScopeStmt/downScope
+ chain when in head of let block/expr) */
+ JSParseNode *blockNode; /* parse node for a lexical scope.
+ XXX combine with blockChain? */
+ JSAtomList decls; /* function, const, and var declarations */
+ JSParseContext *parseContext;
+
+ union {
+
+ JSFunction *fun; /* function to store argument and variable
+ names when flags & TCF_IN_FUNCTION */
+ JSObject *scopeChain; /* scope chain object for the script */
+ } u;
+
+#ifdef JS_SCOPE_DEPTH_METER
+ uint16 scopeDepth; /* current lexical scope chain depth */
+ uint16 maxScopeDepth; /* maximum lexical scope chain depth */
+#endif
+};
+
+#define TCF_IN_FUNCTION 0x01 /* parsing inside function body */
+#define TCF_RETURN_EXPR 0x02 /* function has 'return expr;' */
+#define TCF_RETURN_VOID 0x04 /* function has 'return;' */
+#define TCF_IN_FOR_INIT 0x08 /* parsing init expr of for; exclude 'in' */
+#define TCF_FUN_CLOSURE_VS_VAR 0x10 /* function and var with same name */
+#define TCF_FUN_USES_NONLOCALS 0x20 /* function refers to non-local names */
+#define TCF_FUN_HEAVYWEIGHT 0x40 /* function needs Call object per call */
+#define TCF_FUN_IS_GENERATOR 0x80 /* parsed yield statement in function */
+#define TCF_HAS_DEFXMLNS 0x100 /* default xml namespace = ...; parsed */
+#define TCF_HAS_FUNCTION_STMT 0x200 /* block contains a function statement */
+#define TCF_GENEXP_LAMBDA 0x400 /* flag lambda from generator expression */
+#define TCF_COMPILE_N_GO 0x800 /* compiler-and-go mode of script, can
+ optimize name references based on scope
+ chain */
+#define TCF_NO_SCRIPT_RVAL 0x1000 /* API caller does not want result value
+ from global script */
+/*
+ * Flags to propagate out of the blocks.
+ */
+#define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID)
+
+/*
+ * Flags to propagate from FunctionBody.
+ */
+#define TCF_FUN_FLAGS (TCF_FUN_IS_GENERATOR | \
+ TCF_FUN_HEAVYWEIGHT | \
+ TCF_FUN_USES_NONLOCALS | \
+ TCF_FUN_CLOSURE_VS_VAR)
+
+/*
+ * Flags field, not stored in JSTreeContext.flags, for passing staticDepth
+ * into js_CompileScript.
+ */
+#define TCF_STATIC_DEPTH_MASK 0xffff0000
+#define TCF_GET_STATIC_DEPTH(f) ((uint32)(f) >> 16)
+#define TCF_PUT_STATIC_DEPTH(d) ((uint16)(d) << 16)
+
+#ifdef JS_SCOPE_DEPTH_METER
+# define JS_SCOPE_DEPTH_METERING(code) ((void) (code))
+#else
+# define JS_SCOPE_DEPTH_METERING(code) ((void) 0)
+#endif
+
+#define TREE_CONTEXT_INIT(tc, pc) \
+ ((tc)->flags = (tc)->ngvars = 0, \
+ (tc)->topStmt = (tc)->topScopeStmt = NULL, \
+ (tc)->blockChain = NULL, \
+ ATOM_LIST_INIT(&(tc)->decls), \
+ (tc)->blockNode = NULL, \
+ (tc)->parseContext = (pc), \
+ (tc)->u.scopeChain = NULL, \
+ JS_SCOPE_DEPTH_METERING((tc)->scopeDepth = (tc)->maxScopeDepth = 0))
+
+/*
+ * For functions TREE_CONTEXT_FINISH is called the second time to finish the
+ * extra tc created during code generation. We skip stats update in such
+ * cases.
+ */
+#define TREE_CONTEXT_FINISH(cx, tc) \
+ JS_SCOPE_DEPTH_METERING( \
+ (tc)->maxScopeDepth == (uintN) -1 || \
+ JS_BASIC_STATS_ACCUM(&(cx)->runtime->lexicalScopeDepthStats, \
+ (tc)->maxScopeDepth))
+
+/*
+ * Span-dependent instructions are jumps whose span (from the jump bytecode to
+ * the jump target) may require 2 or 4 bytes of immediate operand.
+ */
+typedef struct JSSpanDep JSSpanDep;
+typedef struct JSJumpTarget JSJumpTarget;
+
+struct JSSpanDep {
+ ptrdiff_t top; /* offset of first bytecode in an opcode */
+ ptrdiff_t offset; /* offset - 1 within opcode of jump operand */
+ ptrdiff_t before; /* original offset - 1 of jump operand */
+ JSJumpTarget *target; /* tagged target pointer or backpatch delta */
+};
+
+/*
+ * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets
+ * sorted by offset from left to right, so that targets after a span-dependent
+ * instruction whose jump offset operand must be extended can be found quickly
+ * and adjusted upward (toward higher offsets).
+ */
+struct JSJumpTarget {
+ ptrdiff_t offset; /* offset of span-dependent jump target */
+ int balance; /* AVL tree balance number */
+ JSJumpTarget *kids[2]; /* left and right AVL tree child pointers */
+};
+
+#define JT_LEFT 0
+#define JT_RIGHT 1
+#define JT_OTHER_DIR(dir) (1 - (dir))
+#define JT_IMBALANCE(dir) (((dir) << 1) - 1)
+#define JT_DIR(imbalance) (((imbalance) + 1) >> 1)
+
+/*
+ * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear,
+ * so we can maintain backpatch chains when using span dependency records to
+ * hold jump offsets that overflow 16 bits.
+ */
+#define JT_TAG_BIT ((jsword) 1)
+#define JT_UNTAG_SHIFT 1
+#define JT_SET_TAG(jt) ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT))
+#define JT_CLR_TAG(jt) ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))
+#define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT)
+
+#define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)
+#define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)
+#define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)
+#define BPDELTA_TO_JT(bp) ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT))
+#define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))
+
+#define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt))
+#define SD_GET_TARGET(sd) (JS_ASSERT(JT_HAS_TAG((sd)->target)), \
+ JT_CLR_TAG((sd)->target))
+#define SD_SET_BPDELTA(sd,bp) ((sd)->target = BPDELTA_TO_JT(bp))
+#define SD_GET_BPDELTA(sd) (JS_ASSERT(!JT_HAS_TAG((sd)->target)), \
+ JT_TO_BPDELTA((sd)->target))
+
+/* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */
+#define SD_SPAN(sd,pivot) (SD_GET_TARGET(sd) \
+ ? JT_CLR_TAG((sd)->target)->offset - (pivot) \
+ : 0)
+
+typedef struct JSTryNode JSTryNode;
+
+struct JSTryNode {
+ JSTryNote note;
+ JSTryNode *prev;
+};
+
+typedef struct JSEmittedObjectList {
+ uint32 length; /* number of emitted so far objects */
+ JSParsedObjectBox *lastPob; /* last emitted object */
+} JSEmittedObjectList;
+
+extern void
+FinishParsedObjects(JSEmittedObjectList *emittedList, JSObjectArray *objectMap);
+
+struct JSCodeGenerator {
+ JSTreeContext treeContext; /* base state: statement info stack, etc. */
+
+ JSArenaPool *codePool; /* pointer to thread code arena pool */
+ JSArenaPool *notePool; /* pointer to thread srcnote arena pool */
+ void *codeMark; /* low watermark in cg->codePool */
+ void *noteMark; /* low watermark in cg->notePool */
+
+ struct {
+ jsbytecode *base; /* base of JS bytecode vector */
+ jsbytecode *limit; /* one byte beyond end of bytecode */
+ jsbytecode *next; /* pointer to next free bytecode */
+ jssrcnote *notes; /* source notes, see below */
+ uintN noteCount; /* number of source notes so far */
+ uintN noteMask; /* growth increment for notes */
+ ptrdiff_t lastNoteOffset; /* code offset for last source note */
+ uintN currentLine; /* line number for tree-based srcnote gen */
+ } prolog, main, *current;
+
+ JSAtomList atomList; /* literals indexed for mapping */
+ uintN firstLine; /* first line, for js_NewScriptFromCG */
+
+ intN stackDepth; /* current stack depth in script frame */
+ uintN maxStackDepth; /* maximum stack depth so far */
+
+ uintN ntrynotes; /* number of allocated so far try notes */
+ JSTryNode *lastTryNode; /* the last allocated try node */
+
+ JSSpanDep *spanDeps; /* span dependent instruction records */
+ JSJumpTarget *jumpTargets; /* AVL tree of jump target offsets */
+ JSJumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */
+ uintN numSpanDeps; /* number of span dependencies */
+ uintN numJumpTargets; /* number of jump targets */
+ ptrdiff_t spanDepTodo; /* offset from main.base of potentially
+ unoptimized spandeps */
+
+ uintN arrayCompDepth; /* stack depth of array in comprehension */
+
+ uintN emitLevel; /* js_EmitTree recursion level */
+ JSAtomList constList; /* compile time constants */
+
+ JSEmittedObjectList objectList; /* list of emitted so far objects */
+ JSEmittedObjectList regexpList; /* list of emitted so far regexp
+ that will be cloned during execution */
+
+ uintN staticDepth; /* static frame chain depth */
+ JSAtomList upvarList; /* map of atoms to upvar indexes */
+ JSUpvarArray upvarMap; /* indexed upvar pairs (JS_realloc'ed) */
+ JSCodeGenerator *parent; /* enclosing function or global context */
+};
+
+#define CG_TS(cg) TS((cg)->treeContext.parseContext)
+
+#define CG_BASE(cg) ((cg)->current->base)
+#define CG_LIMIT(cg) ((cg)->current->limit)
+#define CG_NEXT(cg) ((cg)->current->next)
+#define CG_CODE(cg,offset) (CG_BASE(cg) + (offset))
+#define CG_OFFSET(cg) PTRDIFF(CG_NEXT(cg), CG_BASE(cg), jsbytecode)
+
+#define CG_NOTES(cg) ((cg)->current->notes)
+#define CG_NOTE_COUNT(cg) ((cg)->current->noteCount)
+#define CG_NOTE_MASK(cg) ((cg)->current->noteMask)
+#define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
+#define CG_CURRENT_LINE(cg) ((cg)->current->currentLine)
+
+#define CG_PROLOG_BASE(cg) ((cg)->prolog.base)
+#define CG_PROLOG_LIMIT(cg) ((cg)->prolog.limit)
+#define CG_PROLOG_NEXT(cg) ((cg)->prolog.next)
+#define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
+#define CG_PROLOG_OFFSET(cg) PTRDIFF(CG_PROLOG_NEXT(cg), CG_PROLOG_BASE(cg),\
+ jsbytecode)
+
+#define CG_SWITCH_TO_MAIN(cg) ((cg)->current = &(cg)->main)
+#define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)
+
+/*
+ * Initialize cg to allocate bytecode space from codePool, source note space
+ * from notePool, and all other arena-allocated temporaries from cx->tempPool.
+ */
+extern JS_FRIEND_API(void)
+js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,
+ JSArenaPool *codePool, JSArenaPool *notePool,
+ uintN lineno);
+
+/*
+ * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by
+ * js_InitCodeGenerator. Note that cgs are magic: they own the arena pool
+ * "tops-of-stack" space above their codeMark, noteMark, and tempMark points.
+ * This means you cannot alloc from tempPool and save the pointer beyond the
+ * next JS_FinishCodeGenerator.
+ */
+extern JS_FRIEND_API(void)
+js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg);
+
+/*
+ * Emit one bytecode.
+ */
+extern ptrdiff_t
+js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
+
+/*
+ * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
+ */
+extern ptrdiff_t
+js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
+
+/*
+ * Emit three bytecodes, an opcode with two bytes of immediate operands.
+ */
+extern ptrdiff_t
+js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
+ jsbytecode op2);
+
+/*
+ * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
+ */
+extern ptrdiff_t
+js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
+
+/*
+ * Unsafe macro to call js_SetJumpOffset and return false if it does.
+ */
+#define CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,BAD_EXIT) \
+ JS_BEGIN_MACRO \
+ if (!js_SetJumpOffset(cx, cg, pc, off)) { \
+ BAD_EXIT; \
+ } \
+ JS_END_MACRO
+
+#define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off) \
+ CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,return JS_FALSE)
+
+#define CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx,cg,off,BAD_EXIT) \
+ CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx, cg, CG_CODE(cg,off), \
+ CG_OFFSET(cg) - (off), BAD_EXIT)
+
+#define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \
+ CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, off, return JS_FALSE)
+
+extern JSBool
+js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
+ ptrdiff_t off);
+
+/* Test whether we're in a statement of given type. */
+extern JSBool
+js_InStatement(JSTreeContext *tc, JSStmtType type);
+
+/* Test whether we're in a with statement. */
+#define js_InWithStatement(tc) js_InStatement(tc, STMT_WITH)
+
+/*
+ * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
+ */
+extern void
+js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
+ ptrdiff_t top);
+
+/*
+ * Push a block scope statement and link blockObj into tc->blockChain. To pop
+ * this statement info record, use js_PopStatement as usual, or if appropriate
+ * (if generating code), js_PopStatementCG.
+ */
+extern void
+js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
+ ptrdiff_t top);
+
+/*
+ * Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
+ * is up to the caller to free it.
+ */
+extern void
+js_PopStatement(JSTreeContext *tc);
+
+/*
+ * Like js_PopStatement(&cg->treeContext), also patch breaks and continues
+ * unless the top statement info record represents a try-catch-finally suite.
+ * May fail if a jump offset overflows.
+ */
+extern JSBool
+js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
+
+/*
+ * Define and lookup a primitive jsval associated with the const named by atom.
+ * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
+ * and saves the const's value in cg->constList, if it can be used at compile
+ * time. It returns true unless an error occurred.
+ *
+ * If the initializer's value could not be saved, js_DefineCompileTimeConstant
+ * calls will return the undefined value. js_DefineCompileTimeConstant tries
+ * to find a const value memorized for atom, returning true with *vp set to a
+ * value other than undefined if the constant was found, true with *vp set to
+ * JSVAL_VOID if not found, and false on error.
+ */
+extern JSBool
+js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
+ JSParseNode *pn);
+
+/*
+ * Find a lexically scoped variable (one declared by let, catch, or an array
+ * comprehension) named by atom, looking in tc's compile-time scopes.
+ *
+ * If a WITH statement is reached along the scope stack, return its statement
+ * info record, so callers can tell that atom is ambiguous. If slotp is not
+ * null, then if atom is found, set *slotp to its stack slot, otherwise to -1.
+ * This means that if slotp is not null, all the block objects on the lexical
+ * scope chain must have had their depth slots computed by the code generator,
+ * so the caller must be under js_EmitTree.
+ *
+ * In any event, directly return the statement info record in which atom was
+ * found. Otherwise return null.
+ */
+extern JSStmtInfo *
+js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp);
+
+/*
+ * Emit code into cg for the tree rooted at pn.
+ */
+extern JSBool
+js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
+
+/*
+ * Emit function code using cg for the tree rooted at body.
+ */
+extern JSBool
+js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
+
+/*
+ * Source notes generated along with bytecode for decompiling and debugging.
+ * A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
+ * the previous note. If 3 bits of offset aren't enough, extended delta notes
+ * (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
+ * are emitted before the next note. Some notes have operand offsets encoded
+ * immediately after them, in note bytes or byte-triples.
+ *
+ * Source Note Extended Delta
+ * +7-6-5-4-3+2-1-0+ +7-6-5+4-3-2-1-0+
+ * |note-type|delta| |1 1| ext-delta |
+ * +---------+-----+ +---+-----------+
+ *
+ * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
+ * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
+ *
+ * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
+ * initializers need to match the order here.
+ *
+ * Note on adding new source notes: every pair of bytecodes (A, B) where A and
+ * B have disjoint sets of source notes that could apply to each bytecode may
+ * reuse the same note type value for two notes (snA, snB) that have the same
+ * arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is
+ * why SRC_IF and SRC_INITPROP have the same value below. For bad historical
+ * reasons, some bytecodes below that could be overlayed have not been, but
+ * before using SRC_EXTENDED, consider compressing the existing note types.
+ *
+ * Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
+ * incompatible source note or other bytecode changes.
+ */
+typedef enum JSSrcNoteType {
+ SRC_NULL = 0, /* terminates a note vector */
+ SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */
+ SRC_BREAK = 1, /* JSOP_GOTO is a break */
+ SRC_INITPROP = 1, /* disjoint meaning applied to JSOP_INITELEM or
+ to an index label in a regular (structuring)
+ or a destructuring object initialiser */
+ SRC_GENEXP = 1, /* JSOP_ANONFUNOBJ from generator expression */
+ SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */
+ SRC_FOR_IN = 2, /* JSOP_GOTO to for-in loop condition from
+ before loop (same arity as SRC_IF_ELSE) */
+ SRC_FOR = 3, /* JSOP_NOP or JSOP_POP in for(;;) loop head */
+ SRC_WHILE = 4, /* JSOP_GOTO to for or while loop condition
+ from before loop, else JSOP_NOP at top of
+ do-while loop */
+ SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break;
+ also used on JSOP_ENDINIT if extra comma
+ at end of array literal: [1,2,,] */
+ SRC_DECL = 6, /* type of a declaration (var, const, let*) */
+ SRC_DESTRUCT = 6, /* JSOP_DUP starting a destructuring assignment
+ operation, with SRC_DECL_* offset operand */
+ SRC_PCDELTA = 7, /* distance forward from comma-operator to
+ next POP, or from CONDSWITCH to first CASE
+ opcode, etc. -- always a forward delta */
+ SRC_GROUPASSIGN = 7, /* SRC_DESTRUCT variant for [a, b] = [c, d] */
+ SRC_ASSIGNOP = 8, /* += or another assign-op follows */
+ SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
+ SRC_BRACE = 10, /* mandatory brace, for scope or to avoid
+ dangling else */
+ SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
+ SRC_PCBASE = 12, /* distance back from annotated getprop or
+ setprop op to left-most obj.prop.subprop
+ bytecode -- always a backward delta */
+ SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
+ SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
+ SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
+ SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */
+ SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */
+ SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch,
+ 2nd off to first JSOP_CASE if condswitch */
+ SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
+ SRC_CATCH = 20, /* catch block has guard */
+ SRC_EXTENDED = 21, /* extended source note, 32-159, in next byte */
+ SRC_NEWLINE = 22, /* bytecode follows a source newline */
+ SRC_SETLINE = 23, /* a file-absolute source line number note */
+ SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
+} JSSrcNoteType;
+
+/*
+ * Constants for the SRC_DECL source note. Note that span-dependent bytecode
+ * selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
+ * to be adjusted, but these "offsets" are too small to span a span-dependent
+ * instruction, so can be used to denote distinct declaration syntaxes to the
+ * decompiler.
+ *
+ * NB: the var_prefix array in jsopcode.c depends on these dense indexes from
+ * SRC_DECL_VAR through SRC_DECL_LET.
+ */
+#define SRC_DECL_VAR 0
+#define SRC_DECL_CONST 1
+#define SRC_DECL_LET 2
+#define SRC_DECL_NONE 3
+
+#define SN_TYPE_BITS 5
+#define SN_DELTA_BITS 3
+#define SN_XDELTA_BITS 6
+#define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
+#define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
+#define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
+
+#define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \
+ (((t) << SN_DELTA_BITS) \
+ | ((d) & SN_DELTA_MASK)))
+#define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \
+ ((SRC_XDELTA << SN_DELTA_BITS) \
+ | ((d) & SN_XDELTA_MASK)))
+
+#define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
+#define SN_TYPE(sn) ((JSSrcNoteType)(SN_IS_XDELTA(sn) \
+ ? SRC_XDELTA \
+ : *(sn) >> SN_DELTA_BITS))
+#define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
+#define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE)
+
+#define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \
+ ? *(sn) & SN_XDELTA_MASK \
+ : *(sn) & SN_DELTA_MASK))
+#define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \
+ ? SN_MAKE_XDELTA(sn, delta) \
+ : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
+
+#define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
+#define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
+
+/*
+ * Offset fields follow certain notes and are frequency-encoded: an offset in
+ * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
+ * the high bit of the first byte is set.
+ */
+#define SN_3BYTE_OFFSET_FLAG 0x80
+#define SN_3BYTE_OFFSET_MASK 0x7f
+
+typedef struct JSSrcNoteSpec {
+ const char *name; /* name for disassembly/debugging output */
+ int8 arity; /* number of offset operands */
+ uint8 offsetBias; /* bias of offset(s) from annotated pc */
+ int8 isSpanDep; /* 1 or -1 if offsets could span extended ops,
+ 0 otherwise; sign tells span direction */
+} JSSrcNoteSpec;
+
+extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];
+extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn);
+
+#define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \
+ : js_SrcNoteLength(sn))
+#define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))
+
+/* A source note array is terminated by an all-zero element. */
+#define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL)
+#define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL)
+
+/*
+ * Append a new source note of the given type (and therefore size) to cg's
+ * notes dynamic array, updating cg->noteCount. Return the new note's index
+ * within the array pointed at by cg->current->notes. Return -1 if out of
+ * memory.
+ */
+extern intN
+js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
+
+extern intN
+js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset);
+
+extern intN
+js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
+ ptrdiff_t offset1, ptrdiff_t offset2);
+
+/*
+ * NB: this function can add at most one extra extended delta note.
+ */
+extern jssrcnote *
+js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
+ ptrdiff_t delta);
+
+/*
+ * Get and set the offset operand identified by which (0 for the first, etc.).
+ */
+extern JS_FRIEND_API(ptrdiff_t)
+js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
+
+extern JSBool
+js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
+ uintN which, ptrdiff_t offset);
+
+/*
+ * Finish taking source notes in cx's notePool, copying final notes to the new
+ * stable store allocated by the caller and passed in via notes. Return false
+ * on malloc failure, which means this function reported an error.
+ *
+ * To compute the number of jssrcnotes to allocate and pass in via notes, use
+ * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
+ * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
+ * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
+ */
+#define CG_COUNT_FINAL_SRCNOTES(cg, cnt) \
+ JS_BEGIN_MACRO \
+ ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \
+ cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1; \
+ if ((cg)->prolog.noteCount && \
+ (cg)->prolog.currentLine != (cg)->firstLine) { \
+ if (diff_ > SN_DELTA_MASK) \
+ cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK); \
+ cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1); \
+ } else if (diff_ > 0) { \
+ if (cg->main.noteCount) { \
+ jssrcnote *sn_ = (cg)->main.notes; \
+ diff_ -= SN_IS_XDELTA(sn_) \
+ ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK) \
+ : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK); \
+ } \
+ if (diff_ > 0) \
+ cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK); \
+ } \
+ JS_END_MACRO
+
+extern JSBool
+js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes);
+
+extern void
+js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array);
+
+JS_END_EXTERN_C
+
+#endif /* jsemit_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp
new file mode 100644
index 0000000..c61b724
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.cpp
@@ -0,0 +1,1376 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS standard exception implementation.
+ */
+
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstaticcheck.h"
+
+/* Forward declarations for js_ErrorClass's initializer. */
+static JSBool
+Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+static void
+exn_finalize(JSContext *cx, JSObject *obj);
+
+static void
+exn_trace(JSTracer *trc, JSObject *obj);
+
+static void
+exn_finalize(JSContext *cx, JSObject *obj);
+
+static JSBool
+exn_enumerate(JSContext *cx, JSObject *obj);
+
+static JSBool
+exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp);
+
+JSClass js_ErrorClass = {
+ js_Error_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_MARK_IS_TRACE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Error),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ exn_enumerate, (JSResolveOp)exn_resolve, JS_ConvertStub, exn_finalize,
+ NULL, NULL, NULL, Exception,
+ NULL, NULL, JS_CLASS_TRACE(exn_trace), NULL
+};
+
+typedef struct JSStackTraceElem {
+ JSString *funName;
+ size_t argc;
+ const char *filename;
+ uintN ulineno;
+} JSStackTraceElem;
+
+typedef struct JSExnPrivate {
+ /* A copy of the JSErrorReport originally generated. */
+ JSErrorReport *errorReport;
+ JSString *message;
+ JSString *filename;
+ uintN lineno;
+ size_t stackDepth;
+ JSStackTraceElem stackElems[1];
+} JSExnPrivate;
+
+static JSString *
+StackTraceToString(JSContext *cx, JSExnPrivate *priv);
+
+static JSErrorReport *
+CopyErrorReport(JSContext *cx, JSErrorReport *report)
+{
+ /*
+ * We use a single malloc block to make a deep copy of JSErrorReport with
+ * the following layout:
+ * JSErrorReport
+ * array of copies of report->messageArgs
+ * jschar array with characters for all messageArgs
+ * jschar array with characters for ucmessage
+ * jschar array with characters for uclinebuf and uctokenptr
+ * char array with characters for linebuf and tokenptr
+ * char array with characters for filename
+ * Such layout together with the properties enforced by the following
+ * asserts does not need any extra alignment padding.
+ */
+ JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char *) == 0);
+ JS_STATIC_ASSERT(sizeof(const char *) % sizeof(jschar) == 0);
+
+ size_t filenameSize;
+ size_t linebufSize;
+ size_t uclinebufSize;
+ size_t ucmessageSize;
+ size_t i, argsArraySize, argsCopySize, argSize;
+ size_t mallocSize;
+ JSErrorReport *copy;
+ uint8 *cursor;
+
+#define JS_CHARS_SIZE(jschars) ((js_strlen(jschars) + 1) * sizeof(jschar))
+
+ filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
+ linebufSize = report->linebuf ? strlen(report->linebuf) + 1 : 0;
+ uclinebufSize = report->uclinebuf ? JS_CHARS_SIZE(report->uclinebuf) : 0;
+ ucmessageSize = 0;
+ argsArraySize = 0;
+ argsCopySize = 0;
+ if (report->ucmessage) {
+ ucmessageSize = JS_CHARS_SIZE(report->ucmessage);
+ if (report->messageArgs) {
+ for (i = 0; report->messageArgs[i]; ++i)
+ argsCopySize += JS_CHARS_SIZE(report->messageArgs[i]);
+
+ /* Non-null messageArgs should have at least one non-null arg. */
+ JS_ASSERT(i != 0);
+ argsArraySize = (i + 1) * sizeof(const jschar *);
+ }
+ }
+
+ /*
+ * The mallocSize can not overflow since it represents the sum of the
+ * sizes of already allocated objects.
+ */
+ mallocSize = sizeof(JSErrorReport) + argsArraySize + argsCopySize +
+ ucmessageSize + uclinebufSize + linebufSize + filenameSize;
+ cursor = (uint8 *)JS_malloc(cx, mallocSize);
+ if (!cursor)
+ return NULL;
+
+ copy = (JSErrorReport *)cursor;
+ memset(cursor, 0, sizeof(JSErrorReport));
+ cursor += sizeof(JSErrorReport);
+
+ if (argsArraySize != 0) {
+ copy->messageArgs = (const jschar **)cursor;
+ cursor += argsArraySize;
+ for (i = 0; report->messageArgs[i]; ++i) {
+ copy->messageArgs[i] = (const jschar *)cursor;
+ argSize = JS_CHARS_SIZE(report->messageArgs[i]);
+ memcpy(cursor, report->messageArgs[i], argSize);
+ cursor += argSize;
+ }
+ copy->messageArgs[i] = NULL;
+ JS_ASSERT(cursor == (uint8 *)copy->messageArgs[0] + argsCopySize);
+ }
+
+ if (report->ucmessage) {
+ copy->ucmessage = (const jschar *)cursor;
+ memcpy(cursor, report->ucmessage, ucmessageSize);
+ cursor += ucmessageSize;
+ }
+
+ if (report->uclinebuf) {
+ copy->uclinebuf = (const jschar *)cursor;
+ memcpy(cursor, report->uclinebuf, uclinebufSize);
+ cursor += uclinebufSize;
+ if (report->uctokenptr) {
+ copy->uctokenptr = copy->uclinebuf + (report->uctokenptr -
+ report->uclinebuf);
+ }
+ }
+
+ if (report->linebuf) {
+ copy->linebuf = (const char *)cursor;
+ memcpy(cursor, report->linebuf, linebufSize);
+ cursor += linebufSize;
+ if (report->tokenptr) {
+ copy->tokenptr = copy->linebuf + (report->tokenptr -
+ report->linebuf);
+ }
+ }
+
+ if (report->filename) {
+ copy->filename = (const char *)cursor;
+ memcpy(cursor, report->filename, filenameSize);
+ }
+ JS_ASSERT(cursor + filenameSize == (uint8 *)copy + mallocSize);
+
+ /* Copy non-pointer members. */
+ copy->lineno = report->lineno;
+ copy->errorNumber = report->errorNumber;
+
+ /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
+ copy->flags = report->flags;
+
+#undef JS_CHARS_SIZE
+ return copy;
+}
+
+static jsval *
+GetStackTraceValueBuffer(JSExnPrivate *priv)
+{
+ /*
+ * We use extra memory after JSExnPrivateInfo.stackElems to store jsvals
+ * that helps to produce more informative stack traces. The following
+ * assert allows us to assume that no gap after stackElems is necessary to
+ * align the buffer properly.
+ */
+ JS_STATIC_ASSERT(sizeof(JSStackTraceElem) % sizeof(jsval) == 0);
+
+ return (jsval *)(priv->stackElems + priv->stackDepth);
+}
+
+static JSBool
+InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
+ JSString *filename, uintN lineno, JSErrorReport *report)
+{
+ JSSecurityCallbacks *callbacks;
+ JSCheckAccessOp checkAccess;
+ JSErrorReporter older;
+ JSExceptionState *state;
+ jsval callerid, v;
+ JSStackFrame *fp, *fpstop;
+ size_t stackDepth, valueCount, size;
+ JSBool overflow;
+ JSExnPrivate *priv;
+ JSStackTraceElem *elem;
+ jsval *values;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, exnObject) == &js_ErrorClass);
+
+ /*
+ * Prepare stack trace data.
+ *
+ * Set aside any error reporter for cx and save its exception state
+ * so we can suppress any checkAccess failures. Such failures should stop
+ * the backtrace procedure, not result in a failure of this constructor.
+ */
+ callbacks = JS_GetSecurityCallbacks(cx);
+ checkAccess = callbacks
+ ? callbacks->checkObjectAccess
+ : NULL;
+ older = JS_SetErrorReporter(cx, NULL);
+ state = JS_SaveExceptionState(cx);
+
+ callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);
+ stackDepth = 0;
+ valueCount = 0;
+ for (fp = cx->fp; fp; fp = fp->down) {
+ if (fp->fun && fp->argv) {
+ v = JSVAL_NULL;
+ if (checkAccess &&
+ !checkAccess(cx, fp->callee, callerid, JSACC_READ, &v)) {
+ break;
+ }
+ valueCount += fp->argc;
+ }
+ ++stackDepth;
+ }
+ JS_RestoreExceptionState(cx, state);
+ JS_SetErrorReporter(cx, older);
+ fpstop = fp;
+
+ size = offsetof(JSExnPrivate, stackElems);
+ overflow = (stackDepth > ((size_t)-1 - size) / sizeof(JSStackTraceElem));
+ size += stackDepth * sizeof(JSStackTraceElem);
+ overflow |= (valueCount > ((size_t)-1 - size) / sizeof(jsval));
+ size += valueCount * sizeof(jsval);
+ if (overflow) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+ priv = (JSExnPrivate *)JS_malloc(cx, size);
+ if (!priv)
+ return JS_FALSE;
+
+ /*
+ * We initialize errorReport with a copy of report after setting the
+ * private slot, to prevent GC accessing a junk value we clear the field
+ * here.
+ */
+ priv->errorReport = NULL;
+ priv->message = message;
+ priv->filename = filename;
+ priv->lineno = lineno;
+ priv->stackDepth = stackDepth;
+
+ values = GetStackTraceValueBuffer(priv);
+ elem = priv->stackElems;
+ for (fp = cx->fp; fp != fpstop; fp = fp->down) {
+ if (!fp->fun) {
+ elem->funName = NULL;
+ elem->argc = 0;
+ } else {
+ elem->funName = fp->fun->atom
+ ? ATOM_TO_STRING(fp->fun->atom)
+ : cx->runtime->emptyString;
+ elem->argc = fp->argc;
+ memcpy(values, fp->argv, fp->argc * sizeof(jsval));
+ values += fp->argc;
+ }
+ elem->ulineno = 0;
+ elem->filename = NULL;
+ if (fp->script) {
+ elem->filename = fp->script->filename;
+ if (fp->regs)
+ elem->ulineno = js_FramePCToLineNumber(cx, fp);
+ }
+ ++elem;
+ }
+ JS_ASSERT(priv->stackElems + stackDepth == elem);
+ JS_ASSERT(GetStackTraceValueBuffer(priv) + valueCount == values);
+
+ STOBJ_SET_SLOT(exnObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(priv));
+
+ if (report) {
+ /*
+ * Construct a new copy of the error report struct. We can't use the
+ * error report struct that was passed in, because it's allocated on
+ * the stack, and also because it may point to transient data in the
+ * JSTokenStream.
+ */
+ priv->errorReport = CopyErrorReport(cx, report);
+ if (!priv->errorReport) {
+ /* The finalizer realeases priv since it is in the private slot. */
+ return JS_FALSE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSExnPrivate *
+GetExnPrivate(JSContext *cx, JSObject *obj)
+{
+ jsval privateValue;
+ JSExnPrivate *priv;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ErrorClass);
+ privateValue = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ if (JSVAL_IS_VOID(privateValue))
+ return NULL;
+ priv = (JSExnPrivate *)JSVAL_TO_PRIVATE(privateValue);
+ JS_ASSERT(priv);
+ return priv;
+}
+
+static void
+exn_trace(JSTracer *trc, JSObject *obj)
+{
+ JSExnPrivate *priv;
+ JSStackTraceElem *elem;
+ size_t vcount, i;
+ jsval *vp, v;
+
+ priv = GetExnPrivate(trc->context, obj);
+ if (priv) {
+ if (priv->message)
+ JS_CALL_STRING_TRACER(trc, priv->message, "exception message");
+ if (priv->filename)
+ JS_CALL_STRING_TRACER(trc, priv->filename, "exception filename");
+
+ elem = priv->stackElems;
+ for (vcount = i = 0; i != priv->stackDepth; ++i, ++elem) {
+ if (elem->funName) {
+ JS_CALL_STRING_TRACER(trc, elem->funName,
+ "stack trace function name");
+ }
+ if (IS_GC_MARKING_TRACER(trc) && elem->filename)
+ js_MarkScriptFilename(elem->filename);
+ vcount += elem->argc;
+ }
+ vp = GetStackTraceValueBuffer(priv);
+ for (i = 0; i != vcount; ++i, ++vp) {
+ v = *vp;
+ JS_CALL_VALUE_TRACER(trc, v, "stack trace argument");
+ }
+ }
+}
+
+static void
+exn_finalize(JSContext *cx, JSObject *obj)
+{
+ JSExnPrivate *priv;
+
+ priv = GetExnPrivate(cx, obj);
+ if (priv) {
+ if (priv->errorReport)
+ JS_free(cx, priv->errorReport);
+ JS_free(cx, priv);
+ }
+}
+
+static JSBool
+exn_enumerate(JSContext *cx, JSObject *obj)
+{
+ JSAtomState *atomState;
+ uintN i;
+ JSAtom *atom;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ JS_STATIC_ASSERT(sizeof(JSAtomState) <= (size_t)(uint16)-1);
+ static const uint16 offsets[] = {
+ (uint16)offsetof(JSAtomState, messageAtom),
+ (uint16)offsetof(JSAtomState, fileNameAtom),
+ (uint16)offsetof(JSAtomState, lineNumberAtom),
+ (uint16)offsetof(JSAtomState, stackAtom),
+ };
+
+ atomState = &cx->runtime->atomState;
+ for (i = 0; i != JS_ARRAY_LENGTH(offsets); ++i) {
+ atom = *(JSAtom **)((uint8 *)atomState + offsets[i]);
+ if (!js_LookupProperty(cx, obj, ATOM_TO_JSID(atom), &pobj, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+exn_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSExnPrivate *priv;
+ JSString *str;
+ JSAtom *atom;
+ JSString *stack;
+ const char *prop;
+ jsval v;
+
+ *objp = NULL;
+ priv = GetExnPrivate(cx, obj);
+ if (priv && JSVAL_IS_STRING(id)) {
+ str = JSVAL_TO_STRING(id);
+
+ atom = cx->runtime->atomState.messageAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ prop = js_message_str;
+ v = STRING_TO_JSVAL(priv->message);
+ goto define;
+ }
+
+ atom = cx->runtime->atomState.fileNameAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ prop = js_fileName_str;
+ v = STRING_TO_JSVAL(priv->filename);
+ goto define;
+ }
+
+ atom = cx->runtime->atomState.lineNumberAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ prop = js_lineNumber_str;
+ v = INT_TO_JSVAL(priv->lineno);
+ goto define;
+ }
+
+ atom = cx->runtime->atomState.stackAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ stack = StackTraceToString(cx, priv);
+ if (!stack)
+ return JS_FALSE;
+
+ /* Allow to GC all things that were used to build stack trace. */
+ priv->stackDepth = 0;
+ prop = js_stack_str;
+ v = STRING_TO_JSVAL(stack);
+ goto define;
+ }
+ }
+ return JS_TRUE;
+
+ define:
+ if (!JS_DefineProperty(cx, obj, prop, v, NULL, NULL, JSPROP_ENUMERATE))
+ return JS_FALSE;
+ *objp = obj;
+ return JS_TRUE;
+}
+
+JSErrorReport *
+js_ErrorFromException(JSContext *cx, jsval exn)
+{
+ JSObject *obj;
+ JSExnPrivate *priv;
+
+ if (JSVAL_IS_PRIMITIVE(exn))
+ return NULL;
+ obj = JSVAL_TO_OBJECT(exn);
+ if (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass)
+ return NULL;
+ priv = GetExnPrivate(cx, obj);
+ if (!priv)
+ return NULL;
+ return priv->errorReport;
+}
+
+struct JSExnSpec {
+ int protoIndex;
+ const char *name;
+ JSProtoKey key;
+ JSNative native;
+};
+
+/*
+ * All *Error constructors share the same JSClass, js_ErrorClass. But each
+ * constructor function for an *Error class must have a distinct native 'call'
+ * function pointer, in order for instanceof to work properly across multiple
+ * standard class sets. See jsfun.c:fun_hasInstance.
+ */
+#define MAKE_EXCEPTION_CTOR(name) \
+static JSBool \
+name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) \
+{ \
+ return Exception(cx, obj, argc, argv, rval); \
+}
+
+MAKE_EXCEPTION_CTOR(Error)
+MAKE_EXCEPTION_CTOR(InternalError)
+MAKE_EXCEPTION_CTOR(EvalError)
+MAKE_EXCEPTION_CTOR(RangeError)
+MAKE_EXCEPTION_CTOR(ReferenceError)
+MAKE_EXCEPTION_CTOR(SyntaxError)
+MAKE_EXCEPTION_CTOR(TypeError)
+MAKE_EXCEPTION_CTOR(URIError)
+
+#undef MAKE_EXCEPTION_CTOR
+
+static struct JSExnSpec exceptions[] = {
+ {JSEXN_NONE, js_Error_str, JSProto_Error, Error},
+ {JSEXN_ERR, js_InternalError_str, JSProto_InternalError, InternalError},
+ {JSEXN_ERR, js_EvalError_str, JSProto_EvalError, EvalError},
+ {JSEXN_ERR, js_RangeError_str, JSProto_RangeError, RangeError},
+ {JSEXN_ERR, js_ReferenceError_str, JSProto_ReferenceError, ReferenceError},
+ {JSEXN_ERR, js_SyntaxError_str, JSProto_SyntaxError, SyntaxError},
+ {JSEXN_ERR, js_TypeError_str, JSProto_TypeError, TypeError},
+ {JSEXN_ERR, js_URIError_str, JSProto_URIError, URIError},
+ {0, NULL, JSProto_Null, NULL}
+};
+
+static JSString *
+ValueToShortSource(JSContext *cx, jsval v)
+{
+ JSString *str;
+
+ /* Avoid toSource bloat and fallibility for object types. */
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ str = js_ValueToSource(cx, v);
+ } else if (VALUE_IS_FUNCTION(cx, v)) {
+ /*
+ * XXX Avoid function decompilation bloat for now.
+ */
+ str = JS_GetFunctionId(JS_ValueToFunction(cx, v));
+ if (!str && !(str = js_ValueToSource(cx, v))) {
+ /*
+ * Continue to soldier on if the function couldn't be
+ * converted into a string.
+ */
+ JS_ClearPendingException(cx);
+ str = JS_NewStringCopyZ(cx, "[unknown function]");
+ }
+ } else {
+ /*
+ * XXX Avoid toString on objects, it takes too long and uses too much
+ * memory, for too many classes (see Mozilla bug 166743).
+ */
+ char buf[100];
+ JS_snprintf(buf, sizeof buf, "[object %s]",
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v))->name);
+ str = JS_NewStringCopyZ(cx, buf);
+ }
+ return str;
+}
+
+static JSString *
+StackTraceToString(JSContext *cx, JSExnPrivate *priv)
+{
+ jschar *stackbuf;
+ size_t stacklen, stackmax;
+ JSStackTraceElem *elem, *endElem;
+ jsval *values;
+ size_t i;
+ JSString *str;
+ const char *cp;
+ char ulnbuf[11];
+
+ /* After this point, failing control flow must goto bad. */
+ stackbuf = NULL;
+ stacklen = stackmax = 0;
+
+/* Limit the stackbuf length to a reasonable value to avoid overflow checks. */
+#define STACK_LENGTH_LIMIT JS_BIT(20)
+
+#define APPEND_CHAR_TO_STACK(c) \
+ JS_BEGIN_MACRO \
+ if (stacklen == stackmax) { \
+ void *ptr_; \
+ if (stackmax >= STACK_LENGTH_LIMIT) \
+ goto done; \
+ stackmax = stackmax ? 2 * stackmax : 64; \
+ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \
+ if (!ptr_) \
+ goto bad; \
+ stackbuf = (jschar *) ptr_; \
+ } \
+ stackbuf[stacklen++] = (c); \
+ JS_END_MACRO
+
+#define APPEND_STRING_TO_STACK(str) \
+ JS_BEGIN_MACRO \
+ JSString *str_ = str; \
+ jschar *chars_; \
+ size_t length_; \
+ \
+ JSSTRING_CHARS_AND_LENGTH(str_, chars_, length_); \
+ if (length_ > stackmax - stacklen) { \
+ void *ptr_; \
+ if (stackmax >= STACK_LENGTH_LIMIT || \
+ length_ >= STACK_LENGTH_LIMIT - stacklen) { \
+ goto done; \
+ } \
+ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \
+ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \
+ if (!ptr_) \
+ goto bad; \
+ stackbuf = (jschar *) ptr_; \
+ } \
+ js_strncpy(stackbuf + stacklen, chars_, length_); \
+ stacklen += length_; \
+ JS_END_MACRO
+
+ values = GetStackTraceValueBuffer(priv);
+ elem = priv->stackElems;
+ for (endElem = elem + priv->stackDepth; elem != endElem; elem++) {
+ if (elem->funName) {
+ APPEND_STRING_TO_STACK(elem->funName);
+ APPEND_CHAR_TO_STACK('(');
+ for (i = 0; i != elem->argc; i++, values++) {
+ if (i > 0)
+ APPEND_CHAR_TO_STACK(',');
+ str = ValueToShortSource(cx, *values);
+ if (!str)
+ goto bad;
+ APPEND_STRING_TO_STACK(str);
+ }
+ APPEND_CHAR_TO_STACK(')');
+ }
+ APPEND_CHAR_TO_STACK('@');
+ if (elem->filename) {
+ for (cp = elem->filename; *cp; cp++)
+ APPEND_CHAR_TO_STACK(*cp);
+ }
+ APPEND_CHAR_TO_STACK(':');
+ JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", elem->ulineno);
+ for (cp = ulnbuf; *cp; cp++)
+ APPEND_CHAR_TO_STACK(*cp);
+ APPEND_CHAR_TO_STACK('\n');
+ }
+#undef APPEND_CHAR_TO_STACK
+#undef APPEND_STRING_TO_STACK
+#undef STACK_LENGTH_LIMIT
+
+ done:
+ if (stacklen == 0) {
+ JS_ASSERT(!stackbuf);
+ return cx->runtime->emptyString;
+ }
+ if (stacklen < stackmax) {
+ /*
+ * Realloc can fail when shrinking on some FreeBSD versions, so
+ * don't use JS_realloc here; simply let the oversized allocation
+ * be owned by the string in that rare case.
+ */
+ void *shrunk = JS_realloc(cx, stackbuf, (stacklen+1) * sizeof(jschar));
+ if (shrunk)
+ stackbuf = (jschar *) shrunk;
+ }
+
+ stackbuf[stacklen] = 0;
+ str = js_NewString(cx, stackbuf, stacklen);
+ if (str)
+ return str;
+
+ bad:
+ if (stackbuf)
+ JS_free(cx, stackbuf);
+ return NULL;
+}
+
+/* XXXbe Consolidate the ugly truth that we don't treat filename as UTF-8
+ with these two functions. */
+static JSString *
+FilenameToString(JSContext *cx, const char *filename)
+{
+ return JS_NewStringCopyZ(cx, filename);
+}
+
+static const char *
+StringToFilename(JSContext *cx, JSString *str)
+{
+ return js_GetStringBytes(cx, str);
+}
+
+static JSBool
+Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ uint32 lineno;
+ JSString *message, *filename;
+ JSStackFrame *fp;
+
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ /*
+ * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
+ * called as functions, without operator new. But as we do not give
+ * each constructor a distinct JSClass, whose .name member is used by
+ * js_NewObject to find the class prototype, we must get the class
+ * prototype ourselves.
+ */
+ if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(argv[-2]),
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ rval))
+ return JS_FALSE;
+ obj = js_NewObject(cx, &js_ErrorClass, JSVAL_TO_OBJECT(*rval), NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ /*
+ * If it's a new object of class Exception, then null out the private
+ * data so that the finalizer doesn't attempt to free it.
+ */
+ if (OBJ_GET_CLASS(cx, obj) == &js_ErrorClass)
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, JSVAL_VOID);
+
+ /* Set the 'message' property. */
+ if (argc != 0) {
+ message = js_ValueToString(cx, argv[0]);
+ if (!message)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(message);
+ } else {
+ message = cx->runtime->emptyString;
+ }
+
+ /* Set the 'fileName' property. */
+ if (argc > 1) {
+ filename = js_ValueToString(cx, argv[1]);
+ if (!filename)
+ return JS_FALSE;
+ argv[1] = STRING_TO_JSVAL(filename);
+ fp = NULL;
+ } else {
+ fp = JS_GetScriptedCaller(cx, NULL);
+ if (fp) {
+ filename = FilenameToString(cx, fp->script->filename);
+ if (!filename)
+ return JS_FALSE;
+ } else {
+ filename = cx->runtime->emptyString;
+ }
+ }
+
+ /* Set the 'lineNumber' property. */
+ if (argc > 2) {
+ lineno = js_ValueToECMAUint32(cx, &argv[2]);
+ if (JSVAL_IS_NULL(argv[2]))
+ return JS_FALSE;
+ } else {
+ if (!fp)
+ fp = JS_GetScriptedCaller(cx, NULL);
+ lineno = (fp && fp->regs) ? js_FramePCToLineNumber(cx, fp) : 0;
+ }
+
+ return (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass) ||
+ InitExnPrivate(cx, obj, message, filename, lineno, NULL);
+}
+
+/*
+ * Convert to string.
+ *
+ * This method only uses JavaScript-modifiable properties name, message. It
+ * is left to the host to check for private data and report filename and line
+ * number information along with this message.
+ */
+static JSBool
+exn_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval v;
+ JSString *name, *message, *result;
+ jschar *chars, *cp;
+ size_t name_length, message_length, length;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj ||
+ !OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
+ &v)) {
+ return JS_FALSE;
+ }
+ name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
+ *vp = STRING_TO_JSVAL(name);
+
+ if (!JS_GetProperty(cx, obj, js_message_str, &v))
+ return JS_FALSE;
+ message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v)
+ : cx->runtime->emptyString;
+
+ if (JSSTRING_LENGTH(message) != 0) {
+ name_length = JSSTRING_LENGTH(name);
+ message_length = JSSTRING_LENGTH(message);
+ length = (name_length ? name_length + 2 : 0) + message_length;
+ cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+
+ if (name_length) {
+ js_strncpy(cp, JSSTRING_CHARS(name), name_length);
+ cp += name_length;
+ *cp++ = ':'; *cp++ = ' ';
+ }
+ js_strncpy(cp, JSSTRING_CHARS(message), message_length);
+ cp += message_length;
+ *cp = 0;
+
+ result = js_NewString(cx, chars, length);
+ if (!result) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ } else {
+ result = name;
+ }
+
+ *vp = STRING_TO_JSVAL(result);
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+/*
+ * Return a string that may eval to something similar to the original object.
+ */
+static JSBool
+exn_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSString *name, *message, *filename, *lineno_as_str, *result;
+ jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
+ JSTempValueRooter tvr;
+ JSBool ok;
+ uint32 lineno;
+ size_t lineno_length, name_length, message_length, filename_length, length;
+ jschar *chars, *cp;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj ||
+ !OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.nameAtom),
+ vp)) {
+ return JS_FALSE;
+ }
+ name = js_ValueToString(cx, *vp);
+ if (!name)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(name);
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT(cx, 3, localroots, &tvr);
+
+#ifdef __GNUC__
+ message = filename = NULL;
+#endif
+ ok = JS_GetProperty(cx, obj, js_message_str, &localroots[0]) &&
+ (message = js_ValueToSource(cx, localroots[0]));
+ if (!ok)
+ goto out;
+ localroots[0] = STRING_TO_JSVAL(message);
+
+ ok = JS_GetProperty(cx, obj, js_fileName_str, &localroots[1]) &&
+ (filename = js_ValueToSource(cx, localroots[1]));
+ if (!ok)
+ goto out;
+ localroots[1] = STRING_TO_JSVAL(filename);
+
+ ok = JS_GetProperty(cx, obj, js_lineNumber_str, &localroots[2]);
+ if (!ok)
+ goto out;
+ lineno = js_ValueToECMAUint32 (cx, &localroots[2]);
+ ok = !JSVAL_IS_NULL(localroots[2]);
+ if (!ok)
+ goto out;
+
+ if (lineno != 0) {
+ lineno_as_str = js_ValueToString(cx, localroots[2]);
+ if (!lineno_as_str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ lineno_length = JSSTRING_LENGTH(lineno_as_str);
+ } else {
+ lineno_as_str = NULL;
+ lineno_length = 0;
+ }
+
+ /* Magic 8, for the characters in ``(new ())''. */
+ name_length = JSSTRING_LENGTH(name);
+ message_length = JSSTRING_LENGTH(message);
+ length = 8 + name_length + message_length;
+
+ filename_length = JSSTRING_LENGTH(filename);
+ if (filename_length != 0) {
+ /* append filename as ``, {filename}'' */
+ length += 2 + filename_length;
+ if (lineno_as_str) {
+ /* append lineno as ``, {lineno_as_str}'' */
+ length += 2 + lineno_length;
+ }
+ } else {
+ if (lineno_as_str) {
+ /*
+ * no filename, but have line number,
+ * need to append ``, "", {lineno_as_str}''
+ */
+ length += 6 + lineno_length;
+ }
+ }
+
+ cp = chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' ';
+ js_strncpy(cp, JSSTRING_CHARS(name), name_length);
+ cp += name_length;
+ *cp++ = '(';
+ if (message_length != 0) {
+ js_strncpy(cp, JSSTRING_CHARS(message), message_length);
+ cp += message_length;
+ }
+
+ if (filename_length != 0) {
+ /* append filename as ``, {filename}'' */
+ *cp++ = ','; *cp++ = ' ';
+ js_strncpy(cp, JSSTRING_CHARS(filename), filename_length);
+ cp += filename_length;
+ } else {
+ if (lineno_as_str) {
+ /*
+ * no filename, but have line number,
+ * need to append ``, "", {lineno_as_str}''
+ */
+ *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"';
+ }
+ }
+ if (lineno_as_str) {
+ /* append lineno as ``, {lineno_as_str}'' */
+ *cp++ = ','; *cp++ = ' ';
+ js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length);
+ cp += lineno_length;
+ }
+
+ *cp++ = ')'; *cp++ = ')'; *cp = 0;
+
+ result = js_NewString(cx, chars, length);
+ if (!result) {
+ JS_free(cx, chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ *vp = STRING_TO_JSVAL(result);
+ ok = JS_TRUE;
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+#endif
+
+static JSFunctionSpec exception_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, exn_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, exn_toString, 0,0),
+ JS_FS_END
+};
+
+JSObject *
+js_InitExceptionClasses(JSContext *cx, JSObject *obj)
+{
+ JSObject *obj_proto, *protos[JSEXN_LIMIT];
+ int i;
+
+ /*
+ * If lazy class initialization occurs for any Error subclass, then all
+ * classes are initialized, starting with Error. To avoid reentry and
+ * redundant initialization, we must not pass a null proto parameter to
+ * js_NewObject below, when called for the Error superclass. We need to
+ * ensure that Object.prototype is the proto of Error.prototype.
+ *
+ * See the equivalent code to ensure that parent_proto is non-null when
+ * JS_InitClass calls js_NewObject, in jsapi.c.
+ */
+ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object),
+ &obj_proto)) {
+ return NULL;
+ }
+
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+
+ /* Initialize the prototypes first. */
+ for (i = 0; exceptions[i].name != 0; i++) {
+ JSAtom *atom;
+ JSFunction *fun;
+ JSString *nameString;
+ int protoIndex = exceptions[i].protoIndex;
+
+ /* Make the prototype for the current constructor name. */
+ protos[i] = js_NewObject(cx, &js_ErrorClass,
+ (protoIndex != JSEXN_NONE)
+ ? protos[protoIndex]
+ : obj_proto,
+ obj, 0);
+ if (!protos[i])
+ break;
+
+ /* So exn_finalize knows whether to destroy private data. */
+ STOBJ_SET_SLOT(protos[i], JSSLOT_PRIVATE, JSVAL_VOID);
+
+ /* Make a constructor function for the current name. */
+ atom = cx->runtime->atomState.classAtoms[exceptions[i].key];
+ fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0);
+ if (!fun)
+ break;
+
+ /* Make this constructor make objects of class Exception. */
+ FUN_CLASP(fun) = &js_ErrorClass;
+
+ /* Make the prototype and constructor links. */
+ if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), protos[i],
+ JSPROP_READONLY | JSPROP_PERMANENT)) {
+ break;
+ }
+
+ /* proto bootstrap bit from JS_InitClass omitted. */
+ nameString = JS_NewStringCopyZ(cx, exceptions[i].name);
+ if (!nameString)
+ break;
+
+ /* Add the name property to the prototype. */
+ if (!JS_DefineProperty(cx, protos[i], js_name_str,
+ STRING_TO_JSVAL(nameString),
+ NULL, NULL,
+ JSPROP_ENUMERATE)) {
+ break;
+ }
+
+ /* Finally, stash the constructor for later uses. */
+ if (!js_SetClassObject(cx, obj, exceptions[i].key, FUN_OBJECT(fun)))
+ break;
+ }
+
+ js_LeaveLocalRootScope(cx);
+ if (exceptions[i].name)
+ return NULL;
+
+ /*
+ * Add an empty message property. (To Exception.prototype only,
+ * because this property will be the same for all the exception
+ * protos.)
+ */
+ if (!JS_DefineProperty(cx, protos[0], js_message_str,
+ STRING_TO_JSVAL(cx->runtime->emptyString),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return NULL;
+ }
+ if (!JS_DefineProperty(cx, protos[0], js_fileName_str,
+ STRING_TO_JSVAL(cx->runtime->emptyString),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return NULL;
+ }
+ if (!JS_DefineProperty(cx, protos[0], js_lineNumber_str,
+ INT_TO_JSVAL(0),
+ NULL, NULL, JSPROP_ENUMERATE)) {
+ return NULL;
+ }
+
+ /*
+ * Add methods only to Exception.prototype, because ostensibly all
+ * exception types delegate to that.
+ */
+ if (!JS_DefineFunctions(cx, protos[0], exception_methods))
+ return NULL;
+
+ return protos[0];
+}
+
+const JSErrorFormatString*
+js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
+ const uintN errorNumber)
+{
+ const JSErrorFormatString *errorString = NULL;
+
+ if (cx->localeCallbacks && cx->localeCallbacks->localeGetErrorMessage) {
+ errorString = cx->localeCallbacks
+ ->localeGetErrorMessage(userRef, locale, errorNumber);
+ }
+ if (!errorString)
+ errorString = js_GetErrorMessage(userRef, locale, errorNumber);
+ return errorString;
+}
+
+#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES )
+/* For use below... get character strings for error name and exception name */
+static struct exnname { char *name; char *exception; } errortoexnname[] = {
+#define MSG_DEF(name, number, count, exception, format) \
+ {#name, #exception},
+#include "js.msg"
+#undef MSG_DEF
+};
+#endif /* DEBUG */
+
+JSBool
+js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
+{
+ JSErrNum errorNumber;
+ const JSErrorFormatString *errorString;
+ JSExnType exn;
+ jsval tv[4];
+ JSTempValueRooter tvr;
+ JSBool ok;
+ JSObject *errProto, *errObject;
+ JSString *messageStr, *filenameStr;
+
+ /*
+ * Tell our caller to report immediately if this report is just a warning.
+ */
+ JS_ASSERT(reportp);
+ if (JSREPORT_IS_WARNING(reportp->flags))
+ return JS_FALSE;
+
+ /* Find the exception index associated with this error. */
+ errorNumber = (JSErrNum) reportp->errorNumber;
+ errorString = js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
+ exn = errorString ? (JSExnType) errorString->exnType : JSEXN_NONE;
+ JS_ASSERT(exn < JSEXN_LIMIT);
+
+#if defined( DEBUG_mccabe ) && defined ( PRINTNAMES )
+ /* Print the error name and the associated exception name to stderr */
+ fprintf(stderr, "%s\t%s\n",
+ errortoexnname[errorNumber].name,
+ errortoexnname[errorNumber].exception);
+#endif
+
+ /*
+ * Return false (no exception raised) if no exception is associated
+ * with the given error number.
+ */
+ if (exn == JSEXN_NONE)
+ return JS_FALSE;
+
+ /*
+ * Prevent runaway recursion, via cx->generatingError. If an out-of-memory
+ * error occurs, no exception object will be created, but we don't assume
+ * that OOM is the only kind of error that subroutines of this function
+ * called below might raise.
+ */
+ if (cx->generatingError)
+ return JS_FALSE;
+
+ MUST_FLOW_THROUGH("out");
+ cx->generatingError = JS_TRUE;
+
+ /* Protect the newly-created strings below from nesting GCs. */
+ memset(tv, 0, sizeof tv);
+ JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(tv), tv, &tvr);
+
+ /*
+ * Try to get an appropriate prototype by looking up the corresponding
+ * exception constructor name in the scope chain of the current context's
+ * top stack frame, or in the global object if no frame is active.
+ */
+ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(exceptions[exn].key),
+ &errProto);
+ if (!ok)
+ goto out;
+ tv[0] = OBJECT_TO_JSVAL(errProto);
+
+ errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL, 0);
+ if (!errObject) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ tv[1] = OBJECT_TO_JSVAL(errObject);
+
+ messageStr = JS_NewStringCopyZ(cx, message);
+ if (!messageStr) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ tv[2] = STRING_TO_JSVAL(messageStr);
+
+ filenameStr = JS_NewStringCopyZ(cx, reportp->filename);
+ if (!filenameStr) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ tv[3] = STRING_TO_JSVAL(filenameStr);
+
+ ok = InitExnPrivate(cx, errObject, messageStr, filenameStr,
+ reportp->lineno, reportp);
+ if (!ok)
+ goto out;
+
+ JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
+
+ /* Flag the error report passed in to indicate an exception was raised. */
+ reportp->flags |= JSREPORT_EXCEPTION;
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ cx->generatingError = JS_FALSE;
+ return ok;
+}
+
+JSBool
+js_ReportUncaughtException(JSContext *cx)
+{
+ jsval exn;
+ JSObject *exnObject;
+ jsval roots[5];
+ JSTempValueRooter tvr;
+ JSErrorReport *reportp, report;
+ JSString *str;
+ const char *bytes;
+ JSBool ok;
+
+ if (!JS_IsExceptionPending(cx))
+ return JS_TRUE;
+
+ if (!JS_GetPendingException(cx, &exn))
+ return JS_FALSE;
+
+ memset(roots, 0, sizeof roots);
+ JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(roots), roots, &tvr);
+
+ /*
+ * Because js_ValueToString below could error and an exception object
+ * could become unrooted, we must root exnObject. Later, if exnObject is
+ * non-null, we need to root other intermediates, so allocate an operand
+ * stack segment to protect all of these values.
+ */
+ if (JSVAL_IS_PRIMITIVE(exn)) {
+ exnObject = NULL;
+ } else {
+ exnObject = JSVAL_TO_OBJECT(exn);
+ roots[0] = exn;
+ }
+
+ JS_ClearPendingException(cx);
+ reportp = js_ErrorFromException(cx, exn);
+
+ /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */
+ str = js_ValueToString(cx, exn);
+ if (!str) {
+ bytes = "unknown (can't convert to string)";
+ } else {
+ roots[1] = STRING_TO_JSVAL(str);
+ bytes = js_GetStringBytes(cx, str);
+ if (!bytes) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ ok = JS_TRUE;
+
+ if (!reportp &&
+ exnObject &&
+ OBJ_GET_CLASS(cx, exnObject) == &js_ErrorClass) {
+ const char *filename;
+ uint32 lineno;
+
+ ok = JS_GetProperty(cx, exnObject, js_message_str, &roots[2]);
+ if (!ok)
+ goto out;
+ if (JSVAL_IS_STRING(roots[2])) {
+ bytes = js_GetStringBytes(cx, JSVAL_TO_STRING(roots[2]));
+ if (!bytes) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+
+ ok = JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]);
+ if (!ok)
+ goto out;
+ str = js_ValueToString(cx, roots[3]);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ filename = StringToFilename(cx, str);
+ if (!filename) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ ok = JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]);
+ if (!ok)
+ goto out;
+ lineno = js_ValueToECMAUint32 (cx, &roots[4]);
+ ok = !JSVAL_IS_NULL(roots[4]);
+ if (!ok)
+ goto out;
+
+ reportp = &report;
+ memset(&report, 0, sizeof report);
+ report.filename = filename;
+ report.lineno = (uintN) lineno;
+ }
+
+ if (!reportp) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_UNCAUGHT_EXCEPTION, bytes);
+ } else {
+ /* Flag the error as an exception. */
+ reportp->flags |= JSREPORT_EXCEPTION;
+
+ /* Pass the exception object. */
+ JS_SetPendingException(cx, exn);
+ js_ReportErrorAgain(cx, bytes, reportp);
+ JS_ClearPendingException(cx);
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsexn.h b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.h
new file mode 100644
index 0000000..867586d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsexn.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS runtime exception classes.
+ */
+
+#ifndef jsexn_h___
+#define jsexn_h___
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_ErrorClass;
+
+/*
+ * Initialize the exception constructor/prototype hierarchy.
+ */
+extern JSObject *
+js_InitExceptionClasses(JSContext *cx, JSObject *obj);
+
+/*
+ * Given a JSErrorReport, check to see if there is an exception associated with
+ * the error number. If there is, then create an appropriate exception object,
+ * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the
+ * error report. Exception-aware host error reporters should probably ignore
+ * error reports so flagged. Returns JS_TRUE if an associated exception is
+ * found and set, JS_FALSE otherwise.
+ */
+extern JSBool
+js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp);
+
+/*
+ * Called if a JS API call to js_Execute or js_InternalCall fails; calls the
+ * error reporter with the error report associated with any uncaught exception
+ * that has been raised. Returns true if there was an exception pending, and
+ * the error reporter was actually called.
+ *
+ * The JSErrorReport * that the error reporter is called with is currently
+ * associated with a JavaScript object, and is not guaranteed to persist after
+ * the object is collected. Any persistent uses of the JSErrorReport contents
+ * should make their own copy.
+ *
+ * The flags field of the JSErrorReport will have the JSREPORT_EXCEPTION flag
+ * set; embeddings that want to silently propagate JavaScript exceptions to
+ * other contexts may want to use an error reporter that ignores errors with
+ * this flag.
+ */
+extern JSBool
+js_ReportUncaughtException(JSContext *cx);
+
+extern JSErrorReport *
+js_ErrorFromException(JSContext *cx, jsval exn);
+
+extern const JSErrorFormatString *
+js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale,
+ const uintN errorNumber);
+
+JS_END_EXTERN_C
+
+#endif /* jsexn_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp
new file mode 100644
index 0000000..c5f60ae
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.cpp
@@ -0,0 +1,2736 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS File object
+ */
+#if JS_HAS_FILE_OBJECT
+
+#include "jsstddef.h"
+#include "jsfile.h"
+
+/* ----------------- Platform-specific includes and defines ----------------- */
+#if defined(XP_WIN) || defined(XP_OS2)
+# include <direct.h>
+# include <io.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# define FILESEPARATOR '\\'
+# define FILESEPARATOR2 '/'
+# define CURRENT_DIR "c:\\"
+# define POPEN _popen
+# define PCLOSE _pclose
+#elif defined(XP_UNIX) || defined(XP_BEOS)
+# include <strings.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# define FILESEPARATOR '/'
+# define FILESEPARATOR2 '\0'
+# define CURRENT_DIR "/"
+# define POPEN popen
+# define PCLOSE pclose
+#endif
+
+/* --------------- Platform-independent includes and defines ---------------- */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsdate.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jslock.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include <string.h>
+
+/* NSPR dependencies */
+#include "prio.h"
+#include "prerror.h"
+
+#define SPECIAL_FILE_STRING "Special File"
+#define CURRENTDIR_PROPERTY "currentDir"
+#define SEPARATOR_PROPERTY "separator"
+#define FILE_CONSTRUCTOR "File"
+#define PIPE_SYMBOL '|'
+
+#define ASCII 0
+#define UTF8 1
+#define UCS2 2
+
+#define asciistring "text"
+#define utfstring "binary"
+#define unicodestring "unicode"
+
+#define MAX_PATH_LENGTH 1024
+#define MODE_SIZE 256
+#define NUMBER_SIZE 32
+#define MAX_LINE_LENGTH 256
+#define URL_PREFIX "file://"
+
+#define STDINPUT_NAME "Standard input stream"
+#define STDOUTPUT_NAME "Standard output stream"
+#define STDERROR_NAME "Standard error stream"
+
+#define RESOLVE_PATH js_canonicalPath /* js_absolutePath */
+
+/* Error handling */
+typedef enum JSFileErrNum {
+#define MSG_DEF(name, number, count, exception, format) \
+ name = number,
+#include "jsfile.msg"
+#undef MSG_DEF
+ JSFileErr_Limit
+#undef MSGDEF
+} JSFileErrNum;
+
+#define JSFILE_HAS_DFLT_MSG_STRINGS 1
+
+JSErrorFormatString JSFile_ErrorFormatString[JSFileErr_Limit] = {
+#if JSFILE_HAS_DFLT_MSG_STRINGS
+#define MSG_DEF(name, number, count, exception, format) \
+ { format, count },
+#else
+#define MSG_DEF(name, number, count, exception, format) \
+ { NULL, count },
+#endif
+#include "jsfile.msg"
+#undef MSG_DEF
+};
+
+const JSErrorFormatString *
+JSFile_GetErrorMessage(void *userRef, const char *locale,
+ const uintN errorNumber)
+{
+ if ((errorNumber > 0) && (errorNumber < JSFileErr_Limit))
+ return &JSFile_ErrorFormatString[errorNumber];
+ else
+ return NULL;
+}
+
+#define JSFILE_CHECK_NATIVE(op) \
+ if (file->isNative) { \
+ JS_ReportWarning(cx, "Cannot call or access \"%s\" on native file %s",\
+ op, file->path); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_WRITE \
+ if (!file->isOpen) { \
+ JS_ReportWarning(cx, \
+ "File %s is closed, will open it for writing, proceeding", \
+ file->path); \
+ js_FileOpen(cx, obj, file, "write,append,create"); \
+ } \
+ if (!js_canWrite(cx, file)) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_CANNOT_WRITE, file->path); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_READ \
+ if (!file->isOpen) { \
+ JS_ReportWarning(cx, \
+ "File %s is closed, will open it for reading, proceeding", \
+ file->path); \
+ js_FileOpen(cx, obj, file, "read"); \
+ } \
+ if (!js_canRead(cx, file)) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_CANNOT_READ, file->path); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_OPEN(op) \
+ if (!file->isOpen) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_FILE_MUST_BE_OPEN, op); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_CLOSED(op) \
+ if (file->isOpen) { \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_FILE_MUST_BE_CLOSED, op); \
+ goto out; \
+ }
+
+#define JSFILE_CHECK_ONE_ARG(op) \
+ if (argc != 1) { \
+ char str[NUMBER_SIZE]; \
+ sprintf(str, "%d", argc); \
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, \
+ JSFILEMSG_EXPECTS_ONE_ARG_ERROR, op, str); \
+ goto out; \
+ }
+
+
+/*
+ Security mechanism, should define a callback for this.
+ The parameters are as follows:
+ SECURITY_CHECK(JSContext *cx, JSPrincipals *ps, char *op_name, JSFile *file)
+ XXX Should this be a real function returning a JSBool result (and getting
+ some typesafety help from the compiler?).
+*/
+#define SECURITY_CHECK(cx, ps, op, file) \
+ /* Define a callback here... */
+
+
+/* Structure representing the file internally */
+typedef struct JSFile {
+ char *path; /* the path to the file. */
+ JSBool isOpen;
+ int32 mode; /* mode used to open the file: read, write, append, create, etc.. */
+ int32 type; /* Asciiz, utf, unicode */
+ char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */
+ jsint nbBytesInBuf; /* number of bytes stored in the buffer above */
+ jschar charBuffer; /* character read in advance by readln ( mac files only ) */
+ JSBool charBufferUsed; /* flag indicating if the buffer above is being used */
+ JSBool hasRandomAccess;/* can the file be randomly accessed? false for stdin, and
+ UTF-encoded files. */
+ JSBool hasAutoflush; /* should we force a flush for each line break? */
+ JSBool isNative; /* if the file is using OS-specific file FILE type */
+ /* We can actually put the following two in a union since they should never be used at the same time */
+ PRFileDesc *handle; /* the handle for the file, if open. */
+ FILE *nativehandle; /* native handle, for stuff NSPR doesn't do. */
+ JSBool isPipe; /* if the file is really an OS pipe */
+} JSFile;
+
+/* a few forward declarations... */
+JS_PUBLIC_API(JSObject*) js_NewFileObject(JSContext *cx, char *filename);
+static JSBool file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+static JSBool file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+/* New filename manipulation procesures */
+/* assumes we don't have leading/trailing spaces */
+static JSBool
+js_filenameHasAPipe(const char *filename)
+{
+ if (!filename)
+ return JS_FALSE;
+
+ return filename[0] == PIPE_SYMBOL ||
+ filename[strlen(filename) - 1] == PIPE_SYMBOL;
+}
+
+static JSBool
+js_isAbsolute(const char *name)
+{
+#if defined(XP_WIN) || defined(XP_OS2)
+ return *name && name[1] == ':';
+#else
+ return (name[0]
+# if defined(XP_UNIX) || defined(XP_BEOS)
+ ==
+# else
+ !=
+# endif
+ FILESEPARATOR);
+#endif
+}
+
+/*
+ * Concatenates base and name to produce a valid filename.
+ * Returned string must be freed.
+*/
+static char*
+js_combinePath(JSContext *cx, const char *base, const char *name)
+{
+ int len = strlen(base);
+ char* result = JS_malloc(cx, len + strlen(name) + 2);
+
+ if (!result)
+ return NULL;
+
+ strcpy(result, base);
+
+ if (base[len - 1] != FILESEPARATOR && base[len - 1] != FILESEPARATOR2) {
+ result[len] = FILESEPARATOR;
+ result[len + 1] = '\0';
+ }
+ strcat(result, name);
+ return result;
+}
+
+/* Extract the last component from a path name. Returned string must be freed */
+static char *
+js_fileBaseName(JSContext *cx, const char *pathname)
+{
+ jsint index, aux;
+ char *result;
+
+ index = strlen(pathname)-1;
+
+ /* Chop off trailing seperators. */
+ while (index > 0 && (pathname[index]==FILESEPARATOR ||
+ pathname[index]==FILESEPARATOR2)) {
+ --index;
+ }
+
+ aux = index;
+
+ /* Now find the next separator. */
+ while (index >= 0 && pathname[index] != FILESEPARATOR &&
+ pathname[index] != FILESEPARATOR2) {
+ --index;
+ }
+
+ /* Allocate and copy. */
+ result = JS_malloc(cx, aux - index + 1);
+ if (!result)
+ return NULL;
+ strncpy(result, pathname + index + 1, aux - index);
+ result[aux - index] = '\0';
+ return result;
+}
+
+/*
+ * Returns everything but the last component from a path name.
+ * Returned string must be freed.
+ */
+static char *
+js_fileDirectoryName(JSContext *cx, const char *pathname)
+{
+ char *result;
+ const char *cp, *end;
+ size_t pathsize;
+
+ end = pathname + strlen(pathname);
+ cp = end - 1;
+
+ /* If this is already a directory, chop off the trailing /s. */
+ while (cp >= pathname) {
+ if (*cp != FILESEPARATOR && *cp != FILESEPARATOR2)
+ break;
+ --cp;
+ }
+
+ if (cp < pathname && end != pathname) {
+ /* There were just /s, return the root. */
+ result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */
+ result[0] = FILESEPARATOR;
+ result[1] = '\0';
+ return result;
+ }
+
+ /* Now chop off the last portion. */
+ while (cp >= pathname) {
+ if (*cp == FILESEPARATOR || *cp == FILESEPARATOR2)
+ break;
+ --cp;
+ }
+
+ /* Check if this is a leaf. */
+ if (cp < pathname) {
+ /* It is, return "pathname/". */
+ if (end[-1] == FILESEPARATOR || end[-1] == FILESEPARATOR2) {
+ /* Already has its terminating /. */
+ return JS_strdup(cx, pathname);
+ }
+
+ pathsize = end - pathname + 1;
+ result = JS_malloc(cx, pathsize + 1);
+ if (!result)
+ return NULL;
+
+ strcpy(result, pathname);
+ result[pathsize - 1] = FILESEPARATOR;
+ result[pathsize] = '\0';
+
+ return result;
+ }
+
+ /* Return everything up to and including the seperator. */
+ pathsize = cp - pathname + 1;
+ result = JS_malloc(cx, pathsize + 1);
+ if (!result)
+ return NULL;
+
+ strncpy(result, pathname, pathsize);
+ result[pathsize] = '\0';
+
+ return result;
+}
+
+static char *
+js_absolutePath(JSContext *cx, const char * path)
+{
+ JSObject *obj;
+ JSString *str;
+ jsval prop;
+
+ if (js_isAbsolute(path)) {
+ return JS_strdup(cx, path);
+ } else {
+ obj = JS_GetGlobalObject(cx);
+ if (!JS_GetProperty(cx, obj, FILE_CONSTRUCTOR, &prop)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR);
+ return JS_strdup(cx, path);
+ }
+
+ obj = JSVAL_TO_OBJECT(prop);
+ if (!JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, &prop)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR);
+ return JS_strdup(cx, path);
+ }
+
+ str = JS_ValueToString(cx, prop);
+ if (!str)
+ return JS_strdup(cx, path);
+
+ /* should we have an array of curr dirs indexed by drive for windows? */
+ return js_combinePath(cx, JS_GetStringBytes(str), path);
+ }
+}
+
+/* Side effect: will remove spaces in the beginning/end of the filename */
+static char *
+js_canonicalPath(JSContext *cx, char *oldpath)
+{
+ char *tmp;
+ char *path = oldpath;
+ char *base, *dir, *current, *result;
+ jsint c;
+ jsint back = 0;
+ unsigned int i = 0, j = strlen(path)-1;
+
+ /* This is probably optional */
+ /* Remove possible spaces in the beginning and end */
+ while (i < j && path[i] == ' ')
+ i++;
+ while (j >= 0 && path[j] == ' ')
+ j--;
+
+ tmp = JS_malloc(cx, j-i+2);
+ if (!tmp)
+ return NULL;
+
+ strncpy(tmp, path + i, j - i + 1);
+ tmp[j - i + 1] = '\0';
+
+ path = tmp;
+
+ /* Pipe support. */
+ if (js_filenameHasAPipe(path))
+ return path;
+
+ /* file:// support. */
+ if (!strncmp(path, URL_PREFIX, strlen(URL_PREFIX))) {
+ tmp = js_canonicalPath(cx, path + strlen(URL_PREFIX));
+ JS_free(cx, path);
+ return tmp;
+ }
+
+ if (!js_isAbsolute(path)) {
+ tmp = js_absolutePath(cx, path);
+ if (!tmp)
+ return NULL;
+ JS_free(cx, path);
+ path = tmp;
+ }
+
+ result = JS_strdup(cx, "");
+
+ current = path;
+
+ base = js_fileBaseName(cx, current);
+ dir = js_fileDirectoryName(cx, current);
+
+ while (strcmp(dir, current)) {
+ if (!strcmp(base, "..")) {
+ back++;
+ } else {
+ if (back > 0) {
+ back--;
+ } else {
+ tmp = result;
+ result = JS_malloc(cx, strlen(base) + 1 + strlen(tmp) + 1);
+ if (!result)
+ goto out;
+
+ strcpy(result, base);
+ c = strlen(result);
+ if (*tmp) {
+ result[c] = FILESEPARATOR;
+ result[c + 1] = '\0';
+ strcat(result, tmp);
+ }
+ JS_free(cx, tmp);
+ }
+ }
+ JS_free(cx, current);
+ JS_free(cx, base);
+ current = dir;
+ base = js_fileBaseName(cx, current);
+ dir = js_fileDirectoryName(cx, current);
+ }
+
+ tmp = result;
+ result = JS_malloc(cx, strlen(dir)+1+strlen(tmp)+1);
+ if (!result)
+ goto out;
+
+ strcpy(result, dir);
+ c = strlen(result);
+ if (tmp[0]!='\0') {
+ if ((result[c-1]!=FILESEPARATOR)&&(result[c-1]!=FILESEPARATOR2)) {
+ result[c] = FILESEPARATOR;
+ result[c+1] = '\0';
+ }
+ strcat(result, tmp);
+ }
+
+out:
+ if (tmp)
+ JS_free(cx, tmp);
+ if (dir)
+ JS_free(cx, dir);
+ if (base)
+ JS_free(cx, base);
+ if (current)
+ JS_free(cx, current);
+
+ return result;
+}
+
+/* -------------------------- Text conversion ------------------------------- */
+/* The following is ripped from libi18n/unicvt.c and include files.. */
+
+/*
+ * UTF8 defines and macros
+ */
+#define ONE_OCTET_BASE 0x00 /* 0xxxxxxx */
+#define ONE_OCTET_MASK 0x7F /* x1111111 */
+#define CONTINUING_OCTET_BASE 0x80 /* 10xxxxxx */
+#define CONTINUING_OCTET_MASK 0x3F /* 00111111 */
+#define TWO_OCTET_BASE 0xC0 /* 110xxxxx */
+#define TWO_OCTET_MASK 0x1F /* 00011111 */
+#define THREE_OCTET_BASE 0xE0 /* 1110xxxx */
+#define THREE_OCTET_MASK 0x0F /* 00001111 */
+#define FOUR_OCTET_BASE 0xF0 /* 11110xxx */
+#define FOUR_OCTET_MASK 0x07 /* 00000111 */
+#define FIVE_OCTET_BASE 0xF8 /* 111110xx */
+#define FIVE_OCTET_MASK 0x03 /* 00000011 */
+#define SIX_OCTET_BASE 0xFC /* 1111110x */
+#define SIX_OCTET_MASK 0x01 /* 00000001 */
+
+#define IS_UTF8_1ST_OF_1(x) (( (x)&~ONE_OCTET_MASK ) == ONE_OCTET_BASE)
+#define IS_UTF8_1ST_OF_2(x) (( (x)&~TWO_OCTET_MASK ) == TWO_OCTET_BASE)
+#define IS_UTF8_1ST_OF_3(x) (( (x)&~THREE_OCTET_MASK) == THREE_OCTET_BASE)
+#define IS_UTF8_1ST_OF_4(x) (( (x)&~FOUR_OCTET_MASK ) == FOUR_OCTET_BASE)
+#define IS_UTF8_1ST_OF_5(x) (( (x)&~FIVE_OCTET_MASK ) == FIVE_OCTET_BASE)
+#define IS_UTF8_1ST_OF_6(x) (( (x)&~SIX_OCTET_MASK ) == SIX_OCTET_BASE)
+#define IS_UTF8_2ND_THRU_6TH(x) \
+ (( (x)&~CONTINUING_OCTET_MASK ) == CONTINUING_OCTET_BASE)
+#define IS_UTF8_1ST_OF_UCS2(x) \
+ IS_UTF8_1ST_OF_1(x) \
+ || IS_UTF8_1ST_OF_2(x) \
+ || IS_UTF8_1ST_OF_3(x)
+
+
+#define MAX_UCS2 0xFFFF
+#define DEFAULT_CHAR 0x003F /* Default char is "?" */
+#define BYTE_MASK 0xBF
+#define BYTE_MARK 0x80
+
+
+/* Function: one_ucs2_to_utf8_char
+ *
+ * Function takes one UCS-2 char and writes it to a UTF-8 buffer.
+ * We need a UTF-8 buffer because we don't know before this
+ * function how many bytes of utf-8 data will be written. It also
+ * takes a pointer to the end of the UTF-8 buffer so that we don't
+ * overwrite data. This function returns the number of UTF-8 bytes
+ * of data written, or -1 if the buffer would have been overrun.
+ */
+
+#define LINE_SEPARATOR 0x2028
+#define PARAGRAPH_SEPARATOR 0x2029
+static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
+ unsigned char *tobufendp,
+ uint16 onechar)
+{
+ int16 numUTF8bytes = 0;
+
+ if (onechar == LINE_SEPARATOR || onechar == PARAGRAPH_SEPARATOR) {
+ strcpy((char*)tobufp, "\n");
+ return strlen((char*)tobufp);
+ }
+
+ if (onechar < 0x80) {
+ numUTF8bytes = 1;
+ } else if (onechar < 0x800) {
+ numUTF8bytes = 2;
+ } else {
+ /* 0x800 >= onechar <= MAX_UCS2 */
+ numUTF8bytes = 3;
+ }
+
+ tobufp += numUTF8bytes;
+
+ /* return error if we don't have space for the whole character */
+ if (tobufp > tobufendp) {
+ return(-1);
+ }
+
+ switch(numUTF8bytes) {
+ case 3: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
+ *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
+ *--tobufp = onechar | THREE_OCTET_BASE;
+ break;
+
+ case 2: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
+ *--tobufp = onechar | TWO_OCTET_BASE;
+ break;
+
+ case 1: *--tobufp = (unsigned char)onechar;
+ break;
+ }
+
+ return numUTF8bytes;
+}
+
+/*
+ * utf8_to_ucs2_char
+ *
+ * Convert a utf8 multibyte character to ucs2
+ *
+ * inputs: pointer to utf8 character(s)
+ * length of utf8 buffer ("read" length limit)
+ * pointer to return ucs2 character
+ *
+ * outputs: number of bytes in the utf8 character
+ * -1 if not a valid utf8 character sequence
+ * -2 if the buffer is too short
+ */
+static int16
+utf8_to_ucs2_char(const unsigned char *utf8p, int16 buflen, uint16 *ucs2p)
+{
+ uint16 lead, cont1, cont2;
+
+ /*
+ * Check for minimum buffer length
+ */
+ if ((buflen < 1) || (utf8p == NULL)) {
+ return -2;
+ }
+ lead = (uint16) (*utf8p);
+
+ /*
+ * Check for a one octet sequence
+ */
+ if (IS_UTF8_1ST_OF_1(lead)) {
+ *ucs2p = lead & ONE_OCTET_MASK;
+ return 1;
+ }
+
+ /*
+ * Check for a two octet sequence
+ */
+ if (IS_UTF8_1ST_OF_2(*utf8p)) {
+ if (buflen < 2)
+ return -2;
+ cont1 = (uint16) *(utf8p+1);
+ if (!IS_UTF8_2ND_THRU_6TH(cont1))
+ return -1;
+ *ucs2p = (lead & TWO_OCTET_MASK) << 6;
+ *ucs2p |= cont1 & CONTINUING_OCTET_MASK;
+ return 2;
+ }
+
+ /*
+ * Check for a three octet sequence
+ */
+ else if (IS_UTF8_1ST_OF_3(lead)) {
+ if (buflen < 3)
+ return -2;
+ cont1 = (uint16) *(utf8p+1);
+ cont2 = (uint16) *(utf8p+2);
+ if ( (!IS_UTF8_2ND_THRU_6TH(cont1))
+ || (!IS_UTF8_2ND_THRU_6TH(cont2)))
+ return -1;
+ *ucs2p = (lead & THREE_OCTET_MASK) << 12;
+ *ucs2p |= (cont1 & CONTINUING_OCTET_MASK) << 6;
+ *ucs2p |= cont2 & CONTINUING_OCTET_MASK;
+ return 3;
+ }
+ else { /* not a valid utf8/ucs2 character */
+ return -1;
+ }
+}
+
+/* ----------------------------- Helper functions --------------------------- */
+/* Ripped off from lm_win.c .. */
+/* where is strcasecmp?.. for now, it's case sensitive..
+ *
+ * strcasecmp is in strings.h, but on windows it's called _stricmp...
+ * will need to #ifdef this
+*/
+
+static int32
+js_FileHasOption(JSContext *cx, const char *oldoptions, const char *name)
+{
+ char *comma, *equal, *current;
+ char *options = JS_strdup(cx, oldoptions);
+ int32 found = 0;
+
+ current = options;
+ for (;;) {
+ comma = strchr(current, ',');
+ if (comma) *comma = '\0';
+ equal = strchr(current, '=');
+ if (equal) *equal = '\0';
+ if (strcmp(current, name) == 0) {
+ if (!equal || strcmp(equal + 1, "yes") == 0)
+ found = 1;
+ else
+ found = atoi(equal + 1);
+ }
+ if (equal) *equal = '=';
+ if (comma) *comma = ',';
+ if (found || !comma)
+ break;
+ current = comma + 1;
+ }
+ JS_free(cx, options);
+ return found;
+}
+
+/* empty the buffer */
+static void
+js_ResetBuffers(JSFile * file)
+{
+ file->charBufferUsed = JS_FALSE;
+ file->nbBytesInBuf = 0;
+}
+
+/* Reset file attributes */
+static void
+js_ResetAttributes(JSFile * file)
+{
+ file->mode = file->type = 0;
+ file->isOpen = JS_FALSE;
+ file->handle = NULL;
+ file->nativehandle = NULL;
+ file->hasRandomAccess = JS_TRUE; /* Innocent until proven guilty. */
+ file->hasAutoflush = JS_FALSE;
+ file->isNative = JS_FALSE;
+ file->isPipe = JS_FALSE;
+
+ js_ResetBuffers(file);
+}
+
+static JSBool
+js_FileOpen(JSContext *cx, JSObject *obj, JSFile *file, char *mode){
+ JSString *type, *mask;
+ jsval v[2];
+ jsval rval;
+
+ type = JS_InternString(cx, asciistring);
+ mask = JS_NewStringCopyZ(cx, mode);
+ v[0] = STRING_TO_JSVAL(mask);
+ v[1] = STRING_TO_JSVAL(type);
+
+ if (!file_open(cx, obj, 2, v, &rval))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+/* Buffered version of PR_Read. Used by js_FileRead */
+static int32
+js_BufferedRead(JSFile *f, unsigned char *buf, int32 len)
+{
+ int32 count = 0;
+
+ while (f->nbBytesInBuf>0&&len>0) {
+ buf[0] = f->byteBuffer[0];
+ f->byteBuffer[0] = f->byteBuffer[1];
+ f->byteBuffer[1] = f->byteBuffer[2];
+ f->nbBytesInBuf--;
+ len--;
+ buf+=1;
+ count++;
+ }
+
+ if (len > 0) {
+ count += (!f->isNative)
+ ? PR_Read(f->handle, buf, len)
+ : fread(buf, 1, len, f->nativehandle);
+ }
+ return count;
+}
+
+static int32
+js_FileRead(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
+{
+ unsigned char *aux;
+ int32 count = 0, i;
+ jsint remainder;
+ unsigned char utfbuf[3];
+
+ if (file->charBufferUsed) {
+ buf[0] = file->charBuffer;
+ buf++;
+ len--;
+ file->charBufferUsed = JS_FALSE;
+ }
+
+ switch (mode) {
+ case ASCII:
+ aux = (unsigned char*)JS_malloc(cx, len);
+ if (!aux)
+ return 0;
+
+ count = js_BufferedRead(file, aux, len);
+ if (count == -1) {
+ JS_free(cx, aux);
+ return 0;
+ }
+
+ for (i = 0; i < len; i++)
+ buf[i] = (jschar)aux[i];
+
+ JS_free(cx, aux);
+ break;
+
+ case UTF8:
+ remainder = 0;
+ for (count = 0;count<len;count++) {
+ i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
+ if (i<=0) {
+ return count;
+ }
+ i = utf8_to_ucs2_char(utfbuf, (int16)i, &buf[count] );
+ if (i<0) {
+ return count;
+ } else {
+ if (i==1) {
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder = 2;
+ } else if (i==2) {
+ utfbuf[0] = utfbuf[2];
+ remainder = 1;
+ } else if (i==3) {
+ remainder = 0;
+ }
+ }
+ }
+ while (remainder>0) {
+ file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
+ file->nbBytesInBuf++;
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder--;
+ }
+ break;
+
+ case UCS2:
+ count = js_BufferedRead(file, (unsigned char *)buf, len * 2) >> 1;
+ if (count == -1)
+ return 0;
+
+ break;
+
+ default:
+ /* Not reached. */
+ JS_ASSERT(0);
+ }
+
+ if(count == -1) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "read", file->path);
+ }
+
+ return count;
+}
+
+static int32
+js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
+{
+ int32 count = 0, i;
+ jsint remainder;
+ unsigned char utfbuf[3];
+ jschar tmp;
+
+ switch (mode) {
+ case ASCII:
+ count = PR_Seek(file->handle, len, PR_SEEK_CUR);
+ break;
+
+ case UTF8:
+ remainder = 0;
+ for (count = 0;count<len;count++) {
+ i = js_BufferedRead(file, utfbuf+remainder, 3-remainder);
+ if (i<=0) {
+ return 0;
+ }
+ i = utf8_to_ucs2_char(utfbuf, (int16)i, &tmp );
+ if (i<0) {
+ return 0;
+ } else {
+ if (i==1) {
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder = 2;
+ } else if (i==2) {
+ utfbuf[0] = utfbuf[2];
+ remainder = 1;
+ } else if (i==3) {
+ remainder = 0;
+ }
+ }
+ }
+ while (remainder>0) {
+ file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
+ file->nbBytesInBuf++;
+ utfbuf[0] = utfbuf[1];
+ utfbuf[1] = utfbuf[2];
+ remainder--;
+ }
+ break;
+
+ case UCS2:
+ count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2;
+ break;
+
+ default:
+ /* Not reached. */
+ JS_ASSERT(0);
+ }
+
+ if(count == -1) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "seek", file->path);
+ }
+
+ return count;
+}
+
+static int32
+js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
+{
+ unsigned char *aux;
+ int32 count = 0, i, j;
+ unsigned char *utfbuf;
+
+ switch (mode) {
+ case ASCII:
+ aux = (unsigned char*)JS_malloc(cx, len);
+ if (!aux)
+ return 0;
+
+ for (i = 0; i<len; i++)
+ aux[i] = buf[i] % 256;
+
+ count = (!file->isNative)
+ ? PR_Write(file->handle, aux, len)
+ : fwrite(aux, 1, len, file->nativehandle);
+
+ if (count==-1) {
+ JS_free(cx, aux);
+ return 0;
+ }
+
+ JS_free(cx, aux);
+ break;
+
+ case UTF8:
+ utfbuf = (unsigned char*)JS_malloc(cx, len*3);
+ if (!utfbuf) return 0;
+ i = 0;
+ for (count = 0;count<len;count++) {
+ j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]);
+ if (j==-1) {
+ JS_free(cx, utfbuf);
+ return 0;
+ }
+ i+=j;
+ }
+ j = (!file->isNative)
+ ? PR_Write(file->handle, utfbuf, i)
+ : fwrite(utfbuf, 1, i, file->nativehandle);
+
+ if (j<i) {
+ JS_free(cx, utfbuf);
+ return 0;
+ }
+ JS_free(cx, utfbuf);
+ break;
+
+ case UCS2:
+ count = (!file->isNative)
+ ? PR_Write(file->handle, buf, len*2) >> 1
+ : fwrite(buf, 1, len*2, file->nativehandle) >> 1;
+
+ if (count == -1)
+ return 0;
+ break;
+
+ default:
+ /* Not reached. */
+ JS_ASSERT(0);
+ }
+
+ if(count == -1) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "write", file->path);
+ }
+
+ return count;
+}
+
+/* ----------------------------- Property checkers -------------------------- */
+static JSBool
+js_exists(JSContext *cx, JSFile *file)
+{
+ if (file->isNative) {
+ /* It doesn't make sense for a pipe of stdstream. */
+ return JS_FALSE;
+ }
+
+ return PR_Access(file->path, PR_ACCESS_EXISTS) == PR_SUCCESS;
+}
+
+static JSBool
+js_canRead(JSContext *cx, JSFile *file)
+{
+ if (!file->isNative) {
+ if (file->isOpen && !(file->mode & PR_RDONLY))
+ return JS_FALSE;
+ return PR_Access(file->path, PR_ACCESS_READ_OK) == PR_SUCCESS;
+ }
+
+ if (file->isPipe) {
+ /* Is this pipe open for reading? */
+ return file->path[0] == PIPE_SYMBOL;
+ }
+
+ return !strcmp(file->path, STDINPUT_NAME);
+}
+
+static JSBool
+js_canWrite(JSContext *cx, JSFile *file)
+{
+ if (!file->isNative) {
+ if (file->isOpen && !(file->mode & PR_WRONLY))
+ return JS_FALSE;
+ return PR_Access(file->path, PR_ACCESS_WRITE_OK) == PR_SUCCESS;
+ }
+
+ if(file->isPipe) {
+ /* Is this pipe open for writing? */
+ return file->path[strlen(file->path)-1] == PIPE_SYMBOL;
+ }
+
+ return !strcmp(file->path, STDOUTPUT_NAME) ||
+ !strcmp(file->path, STDERROR_NAME);
+}
+
+static JSBool
+js_isFile(JSContext *cx, JSFile *file)
+{
+ if (!file->isNative) {
+ PRFileInfo info;
+
+ if (file->isOpen
+ ? PR_GetOpenFileInfo(file->handle, &info)
+ : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ return JS_FALSE;
+ }
+
+ return info.type == PR_FILE_FILE;
+ }
+
+ /* This doesn't make sense for a pipe of stdstream. */
+ return JS_FALSE;
+}
+
+static JSBool
+js_isDirectory(JSContext *cx, JSFile *file)
+{
+ if(!file->isNative){
+ PRFileInfo info;
+
+ /* Hack needed to get get_property to work. */
+ if (!js_exists(cx, file))
+ return JS_FALSE;
+
+ if (file->isOpen
+ ? PR_GetOpenFileInfo(file->handle, &info)
+ : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ return JS_FALSE;
+ }
+
+ return info.type == PR_FILE_DIRECTORY;
+ }
+
+ /* This doesn't make sense for a pipe of stdstream. */
+ return JS_FALSE;
+}
+
+static jsval
+js_size(JSContext *cx, JSFile *file)
+{
+ PRFileInfo info;
+
+ JSFILE_CHECK_NATIVE("size");
+
+ if (file->isOpen
+ ? PR_GetOpenFileInfo(file->handle, &info)
+ : PR_GetFileInfo(file->path, &info) != PR_SUCCESS) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ return JSVAL_VOID;
+ }
+
+ return INT_TO_JSVAL(info.size);
+
+out:
+ return JSVAL_VOID;
+}
+
+/*
+ * Return the parent object
+ */
+static JSBool
+js_parent(JSContext *cx, JSFile *file, jsval *resultp)
+{
+ char *str;
+
+ /* Since we only care about pipes and native files, return NULL. */
+ if (file->isNative) {
+ *resultp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ str = js_fileDirectoryName(cx, file->path);
+ if (!str)
+ return JS_FALSE;
+
+ /* If the directory is equal to the original path, we're at the root. */
+ if (!strcmp(file->path, str)) {
+ *resultp = JSVAL_NULL;
+ } else {
+ JSObject *obj = js_NewFileObject(cx, str);
+ if (!obj) {
+ JS_free(cx, str);
+ return JS_FALSE;
+ }
+ *resultp = OBJECT_TO_JSVAL(obj);
+ }
+
+ JS_free(cx, str);
+ return JS_TRUE;
+}
+
+static JSBool
+js_name(JSContext *cx, JSFile *file, jsval *vp)
+{
+ char *name;
+ JSString *str;
+
+ if (file->isPipe) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ name = js_fileBaseName(cx, file->path);
+ if (!name)
+ return JS_FALSE;
+
+ str = JS_NewString(cx, name, strlen(name));
+ if (!str) {
+ JS_free(cx, name);
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/* ------------------------------ File object methods ---------------------------- */
+static JSBool
+file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *strmode, *strtype;
+ char *ctype, *mode;
+ int32 mask, type;
+ int len;
+
+ mode = NULL;
+
+ SECURITY_CHECK(cx, NULL, "open", file);
+
+ /* A native file that is already open */
+ if(file->isOpen && file->isNative) {
+ JS_ReportWarning(cx, "Native file %s is already open, proceeding",
+ file->path);
+ goto good;
+ }
+
+ /* Close before proceeding */
+ if (file->isOpen) {
+ JS_ReportWarning(cx, "File %s is already open, we will close it and "
+ "reopen, proceeding", file->path);
+ if(!file_close(cx, obj, 0, NULL, rval))
+ goto out;
+ }
+
+ if (js_isDirectory(cx, file)) {
+ JS_ReportWarning(cx, "%s seems to be a directory, there is no point in "
+ "trying to open it, proceeding", file->path);
+ goto good;
+ }
+
+ /* Path must be defined at this point */
+ len = strlen(file->path);
+
+ /* Mode */
+ if (argc >= 1) {
+ strmode = JS_ValueToString(cx, argv[0]);
+ if (!strmode) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR,
+ argv[0]);
+ goto out;
+ }
+ mode = JS_strdup(cx, JS_GetStringBytes(strmode));
+ } else {
+ if(file->path[0]==PIPE_SYMBOL) {
+ /* pipe default mode */
+ mode = JS_strdup(cx, "read");
+ } else if(file->path[len-1]==PIPE_SYMBOL) {
+ /* pipe default mode */
+ mode = JS_strdup(cx, "write");
+ } else {
+ /* non-destructive, permissive defaults. */
+ mode = JS_strdup(cx, "readWrite,append,create");
+ }
+ }
+
+ /* Process the mode */
+ mask = 0;
+ /* TODO: this is pretty ugly, we walk thru the string too many times */
+ mask |= js_FileHasOption(cx, mode, "read") ? PR_RDONLY : 0;
+ mask |= js_FileHasOption(cx, mode, "write") ? PR_WRONLY : 0;
+ mask |= js_FileHasOption(cx, mode, "readWrite")? PR_RDWR : 0;
+ mask |= js_FileHasOption(cx, mode, "append") ? PR_APPEND : 0;
+ mask |= js_FileHasOption(cx, mode, "create") ? PR_CREATE_FILE : 0;
+ mask |= js_FileHasOption(cx, mode, "replace") ? PR_TRUNCATE : 0;
+
+ if (mask & PR_RDWR)
+ mask |= (PR_RDONLY | PR_WRONLY);
+ if ((mask & PR_RDONLY) && (mask & PR_WRONLY))
+ mask |= PR_RDWR;
+
+ file->hasAutoflush |= js_FileHasOption(cx, mode, "autoflush");
+
+ /* Type */
+ if (argc > 1) {
+ strtype = JS_ValueToString(cx, argv[1]);
+ if (!strtype) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR,
+ argv[1]);
+ goto out;
+ }
+ ctype = JS_GetStringBytes(strtype);
+
+ if(!strcmp(ctype, utfstring)) {
+ type = UTF8;
+ } else if (!strcmp(ctype, unicodestring)) {
+ type = UCS2;
+ } else {
+ if (strcmp(ctype, asciistring)) {
+ JS_ReportWarning(cx, "File type %s is not supported, using "
+ "'text' instead, proceeding", ctype);
+ }
+ type = ASCII;
+ }
+ } else {
+ type = ASCII;
+ }
+
+ /* Save the relevant fields */
+ file->type = type;
+ file->mode = mask;
+ file->nativehandle = NULL;
+ file->hasRandomAccess = (type != UTF8);
+
+ /*
+ * Deal with pipes here. We can't use NSPR for pipes, so we have to use
+ * POPEN.
+ */
+ if (file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL) {
+ if (file->path[0] == PIPE_SYMBOL && file->path[len-1] == PIPE_SYMBOL) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED);
+ goto out;
+ } else {
+ int i = 0;
+ char pipemode[3];
+ SECURITY_CHECK(cx, NULL, "pipe_open", file);
+
+ if(file->path[0] == PIPE_SYMBOL){
+ if(mask & (PR_WRONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES,
+ mode, file->path);
+ goto out;
+ }
+ /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */
+ pipemode[i++] = 'r';
+#ifndef XP_UNIX
+ pipemode[i++] = file->type==UTF8 ? 'b' : 't';
+#endif
+ pipemode[i++] = '\0';
+ file->nativehandle = POPEN(&file->path[1], pipemode);
+ } else if(file->path[len-1] == PIPE_SYMBOL) {
+ char *command = JS_malloc(cx, len);
+
+ strncpy(command, file->path, len-1);
+ command[len-1] = '\0';
+ /* open(STATUS, "netstat -an 2>&1 |") */
+ pipemode[i++] = 'w';
+#ifndef XP_UNIX
+ pipemode[i++] = file->type==UTF8 ? 'b' : 't';
+#endif
+ pipemode[i++] = '\0';
+ file->nativehandle = POPEN(command, pipemode);
+ JS_free(cx, command);
+ }
+ /* set the flags */
+ file->isNative = JS_TRUE;
+ file->isPipe = JS_TRUE;
+ file->hasRandomAccess = JS_FALSE;
+ }
+ } else {
+ /* TODO: what about the permissions?? Java ignores the problem... */
+ file->handle = PR_Open(file->path, mask, 0644);
+ }
+
+ js_ResetBuffers(file);
+ JS_free(cx, mode);
+ mode = NULL;
+
+ /* Set the open flag and return result */
+ if (file->handle == NULL && file->nativehandle == NULL) {
+ file->isOpen = JS_FALSE;
+
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", file->path);
+ goto out;
+ }
+
+good:
+ file->isOpen = JS_TRUE;
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+
+out:
+ if(mode)
+ JS_free(cx, mode);
+ return JS_FALSE;
+}
+
+static JSBool
+file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "close", file);
+
+ if(!file->isOpen){
+ JS_ReportWarning(cx, "File %s is not open, can't close it, proceeding",
+ file->path);
+ goto out;
+ }
+
+ if(!file->isPipe){
+ if(file->isNative){
+ JS_ReportWarning(cx, "Unable to close a native file, proceeding", file->path);
+ goto out;
+ }else{
+ if(file->handle && PR_Close(file->handle)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", file->path);
+
+ goto out;
+ }
+ }
+ }else{
+ if(PCLOSE(file->nativehandle)==-1){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "pclose", file->path);
+ goto out;
+ }
+ }
+
+ js_ResetAttributes(file);
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+
+out:
+ return JS_FALSE;
+}
+
+
+static JSBool
+file_remove(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "remove", file);
+ JSFILE_CHECK_NATIVE("remove");
+ JSFILE_CHECK_CLOSED("remove");
+
+ if ((js_isDirectory(cx, file) ?
+ PR_RmDir(file->path) : PR_Delete(file->path))==PR_SUCCESS) {
+ js_ResetAttributes(file);
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ } else {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "remove", file->path);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+/* Raw PR-based function. No text processing. Just raw data copying. */
+static JSBool
+file_copyTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char *dest = NULL;
+ PRFileDesc *handle = NULL;
+ char *buffer;
+ jsval count, size;
+ JSBool fileInitiallyOpen=JS_FALSE;
+
+ SECURITY_CHECK(cx, NULL, "copyTo", file); /* may need a second argument!*/
+ JSFILE_CHECK_ONE_ARG("copyTo");
+ JSFILE_CHECK_NATIVE("copyTo");
+ /* remeber the state */
+ fileInitiallyOpen = file->isOpen;
+ JSFILE_CHECK_READ;
+
+ dest = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+
+ /* make sure we are not reading a file open for writing */
+ if (file->isOpen && !js_canRead(cx, file)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, file->path);
+ goto out;
+ }
+
+ if (file->handle==NULL){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", file->path);
+ goto out;
+ }
+
+ handle = PR_Open(dest, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 0644);
+
+ if(!handle){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", dest);
+ goto out;
+ }
+
+ if ((size=js_size(cx, file))==JSVAL_VOID) {
+ goto out;
+ }
+
+ buffer = JS_malloc(cx, size);
+
+ count = INT_TO_JSVAL(PR_Read(file->handle, buffer, size));
+
+ /* reading panic */
+ if (count!=size) {
+ JS_free(cx, buffer);
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_COPY_READ_ERROR, file->path);
+ goto out;
+ }
+
+ count = INT_TO_JSVAL(PR_Write(handle, buffer, JSVAL_TO_INT(size)));
+
+ /* writing panic */
+ if (count!=size) {
+ JS_free(cx, buffer);
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_COPY_WRITE_ERROR, file->path);
+ goto out;
+ }
+
+ JS_free(cx, buffer);
+
+ if(!fileInitiallyOpen){
+ if(!file_close(cx, obj, 0, NULL, rval)) goto out;
+ }
+
+ if(PR_Close(handle)!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", dest);
+ goto out;
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ if(file->isOpen && !fileInitiallyOpen){
+ if(PR_Close(file->handle)!=PR_SUCCESS){
+ JS_ReportWarning(cx, "Can't close %s, proceeding", file->path);
+ }
+ }
+
+ if(handle && PR_Close(handle)!=PR_SUCCESS){
+ JS_ReportWarning(cx, "Can't close %s, proceeding", dest);
+ }
+
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_renameTo(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char *dest;
+
+ SECURITY_CHECK(cx, NULL, "renameTo", file); /* may need a second argument!*/
+ JSFILE_CHECK_ONE_ARG("renameTo");
+ JSFILE_CHECK_NATIVE("renameTo");
+ JSFILE_CHECK_CLOSED("renameTo");
+
+ dest = RESOLVE_PATH(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
+
+ if (PR_Rename(file->path, dest)==PR_SUCCESS){
+ /* copy the new filename */
+ JS_free(cx, file->path);
+ file->path = dest;
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_RENAME_FAILED, file->path, dest);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "flush", file);
+ JSFILE_CHECK_NATIVE("flush");
+ JSFILE_CHECK_OPEN("flush");
+
+ if (PR_Sync(file->handle)==PR_SUCCESS){
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "flush", file->path);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+ int32 count;
+ uintN i;
+
+ SECURITY_CHECK(cx, NULL, "write", file);
+ JSFILE_CHECK_WRITE;
+
+ for (i = 0; i<argc; i++) {
+ str = JS_ValueToString(cx, argv[i]);
+ count = js_FileWrite(cx, file, JS_GetStringChars(str),
+ JS_GetStringLength(str), file->type);
+ if (count==-1){
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+ }
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_writeln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+
+ SECURITY_CHECK(cx, NULL, "writeln", file);
+ JSFILE_CHECK_WRITE;
+
+ /* don't report an error here */
+ if(!file_write(cx, obj, argc, argv, rval)) return JS_FALSE;
+ /* don't do security here -- we passed the check in file_write */
+ str = JS_NewStringCopyZ(cx, "\n");
+
+ if (js_FileWrite(cx, file, JS_GetStringChars(str), JS_GetStringLength(str),
+ file->type)==-1){
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+ }
+
+ /* eol causes flush if hasAutoflush is turned on */
+ if (file->hasAutoflush)
+ file_flush(cx, obj, 0, NULL, rval);
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_writeAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ jsuint i;
+ jsuint limit;
+ JSObject *array;
+ JSObject *elem;
+ jsval elemval;
+
+ SECURITY_CHECK(cx, NULL, "writeAll", file);
+ JSFILE_CHECK_ONE_ARG("writeAll");
+ JSFILE_CHECK_WRITE;
+
+ if (!JS_IsArrayObject(cx, JSVAL_TO_OBJECT(argv[0]))) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR);
+ goto out;
+ }
+
+ array = JSVAL_TO_OBJECT(argv[0]);
+
+ JS_GetArrayLength(cx, array, &limit);
+
+ for (i = 0; i<limit; i++) {
+ if (!JS_GetElement(cx, array, i, &elemval)) return JS_FALSE;
+ elem = JSVAL_TO_OBJECT(elemval);
+ file_writeln(cx, obj, 1, &elemval, rval);
+ }
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+ int32 want, count;
+ jschar *buf;
+
+ SECURITY_CHECK(cx, NULL, "read", file);
+ JSFILE_CHECK_ONE_ARG("read");
+ JSFILE_CHECK_READ;
+
+ if (!JS_ValueToInt32(cx, argv[0], &want)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "read", argv[0]);
+ goto out;
+ }
+
+ /* want = (want>262144)?262144:want; * arbitrary size limitation */
+
+ buf = JS_malloc(cx, want*sizeof buf[0]);
+ if (!buf) goto out;
+
+ count = js_FileRead(cx, file, buf, want, file->type);
+ if (count>0) {
+ str = JS_NewUCStringCopyN(cx, buf, count);
+ *rval = STRING_TO_JSVAL(str);
+ JS_free(cx, buf);
+ return JS_TRUE;
+ } else {
+ JS_free(cx, buf);
+ goto out;
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+ jschar *buf = NULL, *tmp;
+ int32 offset, read;
+ intN room;
+ jschar data, data2;
+
+ SECURITY_CHECK(cx, NULL, "readln", file);
+ JSFILE_CHECK_READ;
+
+ buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data);
+ if (!buf)
+ return JS_FALSE;
+
+ room = MAX_LINE_LENGTH - 1;
+ offset = 0;
+
+ for (;;) {
+ read = js_FileRead(cx, file, &data, 1, file->type);
+ if (read < 0)
+ goto out;
+ if (read == 0)
+ goto eof;
+
+ switch (data) {
+ case '\r':
+ read = js_FileRead(cx, file, &data2, 1, file->type);
+ if (read < 0)
+ goto out;
+
+ if (read == 1 && data2 != '\n') {
+ /* We read one char too far. Buffer it. */
+ file->charBuffer = data2;
+ file->charBufferUsed = JS_TRUE;
+ }
+
+ /* Fall through. */
+ case '\n':
+ goto done;
+
+ default:
+ if (--room < 0) {
+ tmp = JS_realloc(cx, buf,
+ (offset + MAX_LINE_LENGTH) * sizeof data);
+ if (!tmp)
+ goto out;
+
+ room = MAX_LINE_LENGTH - 1;
+ buf = tmp;
+ }
+
+ buf[offset++] = data;
+ break;
+ }
+ }
+
+eof:
+ if (offset == 0) {
+ *rval = JSVAL_NULL;
+ return JS_TRUE;
+ }
+
+done:
+ buf[offset] = 0;
+ tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data);
+ if (!tmp)
+ goto out;
+
+ str = JS_NewUCString(cx, tmp, offset);
+ if (!str)
+ goto out;
+
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+
+out:
+ if (buf)
+ JS_free(cx, buf);
+
+ return JS_FALSE;
+}
+
+static JSBool
+file_readAll(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSObject *array;
+ jsint len;
+ jsval line;
+ JSBool lineok = JS_FALSE;
+
+ SECURITY_CHECK(cx, NULL, "readAll", file);
+ JSFILE_CHECK_READ;
+
+ array = JS_NewArrayObject(cx, 0, NULL);
+ if (!array)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(array);
+
+ len = 0;
+
+ lineok = file_readln(cx, obj, 0, NULL, &line);
+ while (lineok && !JSVAL_IS_NULL(line)) {
+ JS_SetElement(cx, array, len++, &line);
+ lineok = file_readln(cx, obj, 0, NULL, &line);
+ }
+
+out:
+ return lineok;
+}
+
+static JSBool
+file_seek(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ int32 toskip;
+ int32 pos;
+
+ SECURITY_CHECK(cx, NULL, "seek", file);
+ JSFILE_CHECK_ONE_ARG("seek");
+ JSFILE_CHECK_NATIVE("seek");
+ JSFILE_CHECK_READ;
+
+ if (!JS_ValueToInt32(cx, argv[0], &toskip)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "seek", argv[0]);
+ goto out;
+ }
+
+ if(!file->hasRandomAccess){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_NO_RANDOM_ACCESS, file->path);
+ goto out;
+ }
+
+ if(js_isDirectory(cx, file)){
+ JS_ReportWarning(cx,"Seek on directories is not supported, proceeding");
+ goto out;
+ }
+
+ pos = js_FileSeek(cx, file, toskip, file->type);
+
+ if (pos!=-1) {
+ *rval = INT_TO_JSVAL(pos);
+ return JS_TRUE;
+ }
+out:
+ *rval = JSVAL_VOID;
+ return JS_FALSE;
+}
+
+static JSBool
+file_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ PRDir *dir;
+ PRDirEntry *entry;
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSObject *array;
+ JSObject *eachFile;
+ jsint len;
+ jsval v;
+ JSRegExp *re = NULL;
+ JSFunction *func = NULL;
+ JSString *str;
+ jsval args[1];
+ char *filePath;
+
+ SECURITY_CHECK(cx, NULL, "list", file);
+ JSFILE_CHECK_NATIVE("list");
+
+ if (argc==1) {
+ if (VALUE_IS_REGEXP(cx, argv[0])) {
+ re = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ }else
+ if (VALUE_IS_FUNCTION(cx, argv[0])) {
+ func = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, argv[0]);
+ goto out;
+ }
+ }
+
+ if (!js_isDirectory(cx, file)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, file->path);
+ goto out;
+ }
+
+ dir = PR_OpenDir(file->path);
+ if(!dir){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "open", file->path);
+ goto out;
+ }
+
+ /* create JSArray here... */
+ array = JS_NewArrayObject(cx, 0, NULL);
+ len = 0;
+
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))!=NULL) {
+ /* first, check if we have a regexp */
+ if (re!=NULL) {
+ size_t index = 0;
+
+ str = JS_NewStringCopyZ(cx, entry->name);
+ if(!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &v)){
+ /* don't report anything here */
+ goto out;
+ }
+ /* not matched! */
+ if (JSVAL_IS_NULL(v)) {
+ continue;
+ }
+ }else
+ if (func!=NULL) {
+ str = JS_NewStringCopyZ(cx, entry->name);
+ args[0] = STRING_TO_JSVAL(str);
+ if(!JS_CallFunction(cx, obj, func, 1, args, &v)){
+ goto out;
+ }
+
+ if (v==JSVAL_FALSE) {
+ continue;
+ }
+ }
+
+ filePath = js_combinePath(cx, file->path, (char*)entry->name);
+
+ eachFile = js_NewFileObject(cx, filePath);
+ JS_free(cx, filePath);
+ if (!eachFile){
+ JS_ReportWarning(cx, "File %s cannot be retrieved", filePath);
+ continue;
+ }
+ v = OBJECT_TO_JSVAL(eachFile);
+ JS_SetElement(cx, array, len, &v);
+ JS_SetProperty(cx, array, entry->name, &v);
+ len++;
+ }
+
+ if(PR_CloseDir(dir)!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", file->path);
+ goto out;
+ }
+ *rval = OBJECT_TO_JSVAL(array);
+ return JS_TRUE;
+out:
+ *rval = JSVAL_NULL;
+ return JS_FALSE;
+}
+
+static JSBool
+file_mkdir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ SECURITY_CHECK(cx, NULL, "mkdir", file);
+ JSFILE_CHECK_ONE_ARG("mkdir");
+ JSFILE_CHECK_NATIVE("mkdir");
+
+ /* if the current file is not a directory, find out the directory name */
+ if (!js_isDirectory(cx, file)) {
+ char *dir = js_fileDirectoryName(cx, file->path);
+ JSObject *dirObj = js_NewFileObject(cx, dir);
+
+ JS_free(cx, dir);
+
+ /* call file_mkdir with the right set of parameters if needed */
+ if (file_mkdir(cx, dirObj, argc, argv, rval))
+ return JS_TRUE;
+ else
+ goto out;
+ }else{
+ char *dirName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
+ char *fullName;
+
+ fullName = js_combinePath(cx, file->path, dirName);
+ if (PR_MkDir(fullName, 0755)==PR_SUCCESS){
+ *rval = JSVAL_TRUE;
+ JS_free(cx, fullName);
+ return JS_TRUE;
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "mkdir", fullName);
+ JS_free(cx, fullName);
+ goto out;
+ }
+ }
+out:
+ *rval = JSVAL_FALSE;
+ return JS_FALSE;
+}
+
+static JSBool
+file_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval*rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ JSString *str;
+
+ str = JS_NewStringCopyZ(cx, file->path);
+ if (!str)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+file_toURL(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char url[MAX_PATH_LENGTH];
+ jschar *urlChars;
+ size_t len;
+ JSString *str;
+
+ JSFILE_CHECK_NATIVE("toURL");
+
+ sprintf(url, "file://%s", file->path);
+
+ len = strlen(url);
+ urlChars = js_InflateString(cx, url, &len);
+ if (!urlChars)
+ return JS_FALSE;
+ str = js_NewString(cx, urlChars, len);
+ if (!str) {
+ JS_free(cx, urlChars);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+
+ /* TODO: js_escape in jsstr.h may go away at some point */
+ return js_str_escape(cx, obj, 0, rval, rval);
+
+out:
+ *rval = JSVAL_VOID;
+ return JS_FALSE;
+}
+
+
+static void
+file_finalize(JSContext *cx, JSObject *obj)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ if(file) {
+ /* Close the file before exiting. */
+ if(file->isOpen && !file->isNative) {
+ jsval vp;
+ file_close(cx, obj, 0, NULL, &vp);
+ }
+
+ if (file->path)
+ JS_free(cx, file->path);
+
+ JS_free(cx, file);
+ }
+}
+
+/*
+ Allocates memory for the file object, sets fields to defaults.
+*/
+static JSFile*
+file_init(JSContext *cx, JSObject *obj, char *bytes)
+{
+ JSFile *file;
+
+ file = JS_malloc(cx, sizeof *file);
+ if (!file)
+ return NULL;
+ memset(file, 0 , sizeof *file);
+
+ js_ResetAttributes(file);
+
+ file->path = RESOLVE_PATH(cx, bytes);
+
+ if (!JS_SetPrivate(cx, obj, file)) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path);
+ JS_free(cx, file);
+ return NULL;
+ }
+
+ return file;
+}
+
+/* Returns a JSObject. This function is globally visible */
+JS_PUBLIC_API(JSObject*)
+js_NewFileObject(JSContext *cx, char *filename)
+{
+ JSObject *obj;
+ JSFile *file;
+
+ obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
+ if (!obj){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObject");
+ return NULL;
+ }
+ file = file_init(cx, obj, filename);
+ if(!file) return NULL;
+ return obj;
+}
+
+/* Internal function, used for cases which NSPR file support doesn't cover */
+JSObject*
+js_NewFileObjectFromFILE(JSContext *cx, FILE *nativehandle, char *filename,
+ int32 mode, JSBool open, JSBool randomAccess)
+{
+ JSObject *obj;
+ JSFile *file;
+
+ obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
+ if (!obj){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OBJECT_CREATION_FAILED, "js_NewFileObjectFromFILE");
+ return NULL;
+ }
+ file = file_init(cx, obj, filename);
+ if(!file) return NULL;
+
+ file->nativehandle = nativehandle;
+
+ /* free result of RESOLVE_PATH from file_init. */
+ JS_ASSERT(file->path != NULL);
+ JS_free(cx, file->path);
+
+ file->path = strdup(filename);
+ file->isOpen = open;
+ file->mode = mode;
+ file->hasRandomAccess = randomAccess;
+ file->isNative = JS_TRUE;
+ return obj;
+}
+
+/*
+ Real file constructor that is called from JavaScript.
+ Basically, does error processing and calls file_init.
+*/
+static JSBool
+file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ JSFile *file;
+
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ /* Replace obj with a new File object. */
+ obj = JS_NewObject(cx, &js_FileClass, NULL, NULL);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ str = (argc == 0)
+ ? JS_InternString(cx, "")
+ : JS_ValueToString(cx, argv[0]);
+
+ if (!str) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR,
+ argv[0]);
+ return JS_FALSE;
+ }
+
+ file = file_init(cx, obj, JS_GetStringBytes(str));
+ if (!file)
+ return JS_FALSE;
+
+ SECURITY_CHECK(cx, NULL, "constructor", file);
+
+ return JS_TRUE;
+}
+
+/* -------------------- File methods and properties ------------------------- */
+static JSFunctionSpec file_functions[] = {
+ { "open", file_open, 0},
+ { "close", file_close, 0},
+ { "remove", file_remove, 0},
+ { "copyTo", file_copyTo, 0},
+ { "renameTo", file_renameTo, 0},
+ { "flush", file_flush, 0},
+ { "seek", file_seek, 0},
+ { "read", file_read, 0},
+ { "readln", file_readln, 0},
+ { "readAll", file_readAll, 0},
+ { "write", file_write, 0},
+ { "writeln", file_writeln, 0},
+ { "writeAll", file_writeAll, 0},
+ { "list", file_list, 0},
+ { "mkdir", file_mkdir, 0},
+ { "toString", file_toString, 0},
+ { "toURL", file_toURL, 0},
+ {0}
+};
+
+enum file_tinyid {
+ FILE_LENGTH = -2,
+ FILE_PARENT = -3,
+ FILE_PATH = -4,
+ FILE_NAME = -5,
+ FILE_ISDIR = -6,
+ FILE_ISFILE = -7,
+ FILE_EXISTS = -8,
+ FILE_CANREAD = -9,
+ FILE_CANWRITE = -10,
+ FILE_OPEN = -11,
+ FILE_TYPE = -12,
+ FILE_MODE = -13,
+ FILE_CREATED = -14,
+ FILE_MODIFIED = -15,
+ FILE_SIZE = -16,
+ FILE_RANDOMACCESS = -17,
+ FILE_POSITION = -18,
+ FILE_APPEND = -19,
+ FILE_REPLACE = -20,
+ FILE_AUTOFLUSH = -21,
+ FILE_ISNATIVE = -22,
+};
+
+static JSPropertySpec file_props[] = {
+ {"length", FILE_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"parent", FILE_PARENT, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"path", FILE_PATH, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"name", FILE_NAME, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"isDirectory", FILE_ISDIR, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"isFile", FILE_ISFILE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"exists", FILE_EXISTS, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canRead", FILE_CANREAD, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canWrite", FILE_CANWRITE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canAppend", FILE_APPEND, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"canReplace", FILE_REPLACE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"isOpen", FILE_OPEN, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"type", FILE_TYPE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"mode", FILE_MODE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"creationTime", FILE_CREATED, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"lastModified", FILE_MODIFIED, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"size", FILE_SIZE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"hasRandomAccess", FILE_RANDOMACCESS, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"hasAutoFlush", FILE_AUTOFLUSH, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {"position", FILE_POSITION, JSPROP_ENUMERATE },
+ {"isNative", FILE_ISNATIVE, JSPROP_ENUMERATE | JSPROP_READONLY },
+ {0}
+};
+
+/* ------------------------- Property getter/setter ------------------------- */
+static JSBool
+file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ char *bytes;
+ JSString *str;
+ jsint tiny;
+ PRFileInfo info;
+ JSBool flag;
+ PRExplodedTime expandedTime;
+
+ tiny = JSVAL_TO_INT(id);
+ if (!file)
+ return JS_TRUE;
+
+ switch (tiny) {
+ case FILE_PARENT:
+ SECURITY_CHECK(cx, NULL, "parent", file);
+ if (!js_parent(cx, file, vp))
+ return JS_FALSE;
+ break;
+ case FILE_PATH:
+ str = JS_NewStringCopyZ(cx, file->path);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ break;
+ case FILE_NAME:
+ if (!js_name(cx, file, vp))
+ return JS_FALSE;
+ break;
+ case FILE_ISDIR:
+ SECURITY_CHECK(cx, NULL, "isDirectory", file);
+ *vp = BOOLEAN_TO_JSVAL(js_isDirectory(cx, file));
+ break;
+ case FILE_ISFILE:
+ SECURITY_CHECK(cx, NULL, "isFile", file);
+ *vp = BOOLEAN_TO_JSVAL(js_isFile(cx, file));
+ break;
+ case FILE_EXISTS:
+ SECURITY_CHECK(cx, NULL, "exists", file);
+ *vp = BOOLEAN_TO_JSVAL(js_exists(cx, file));
+ break;
+ case FILE_ISNATIVE:
+ SECURITY_CHECK(cx, NULL, "isNative", file);
+ *vp = BOOLEAN_TO_JSVAL(file->isNative);
+ break;
+ case FILE_CANREAD:
+ SECURITY_CHECK(cx, NULL, "canRead", file);
+ *vp = BOOLEAN_TO_JSVAL(js_canRead(cx, file));
+ break;
+ case FILE_CANWRITE:
+ SECURITY_CHECK(cx, NULL, "canWrite", file);
+ *vp = BOOLEAN_TO_JSVAL(js_canWrite(cx, file));
+ break;
+ case FILE_OPEN:
+ SECURITY_CHECK(cx, NULL, "isOpen", file);
+ *vp = BOOLEAN_TO_JSVAL(file->isOpen);
+ break;
+ case FILE_APPEND :
+ SECURITY_CHECK(cx, NULL, "canAppend", file);
+ JSFILE_CHECK_OPEN("canAppend");
+ *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
+ (file->mode&PR_APPEND)==PR_APPEND);
+ break;
+ case FILE_REPLACE :
+ SECURITY_CHECK(cx, NULL, "canReplace", file);
+ JSFILE_CHECK_OPEN("canReplace");
+ *vp = BOOLEAN_TO_JSVAL(!file->isNative &&
+ (file->mode&PR_TRUNCATE)==PR_TRUNCATE);
+ break;
+ case FILE_AUTOFLUSH :
+ SECURITY_CHECK(cx, NULL, "hasAutoFlush", file);
+ JSFILE_CHECK_OPEN("hasAutoFlush");
+ *vp = BOOLEAN_TO_JSVAL(!file->isNative && file->hasAutoflush);
+ break;
+ case FILE_TYPE:
+ SECURITY_CHECK(cx, NULL, "type", file);
+ JSFILE_CHECK_OPEN("type");
+ if(js_isDirectory(cx, file)){
+ *vp = JSVAL_VOID;
+ break;
+ }
+
+ switch (file->type) {
+ case ASCII:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, asciistring));
+ break;
+ case UTF8:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, utfstring));
+ break;
+ case UCS2:
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, unicodestring));
+ break;
+ default:
+ JS_ReportWarning(cx, "Unsupported file type %d, proceeding",
+ file->type);
+ }
+ break;
+ case FILE_MODE:
+ SECURITY_CHECK(cx, NULL, "mode", file);
+ JSFILE_CHECK_OPEN("mode");
+ bytes = JS_malloc(cx, MODE_SIZE);
+ bytes[0] = '\0';
+ flag = JS_FALSE;
+
+ if ((file->mode&PR_RDONLY)==PR_RDONLY) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "read");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_WRONLY)==PR_WRONLY) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "write");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_RDWR)==PR_RDWR) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "readWrite");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_APPEND)==PR_APPEND) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "append");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_CREATE_FILE)==PR_CREATE_FILE) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "create");
+ flag = JS_TRUE;
+ }
+ if ((file->mode&PR_TRUNCATE)==PR_TRUNCATE) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "replace");
+ flag = JS_TRUE;
+ }
+ if (file->hasAutoflush) {
+ if (flag) strcat(bytes, ",");
+ strcat(bytes, "hasAutoFlush");
+ flag = JS_TRUE;
+ }
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, bytes));
+ JS_free(cx, bytes);
+ break;
+ case FILE_CREATED:
+ SECURITY_CHECK(cx, NULL, "creationTime", file);
+ JSFILE_CHECK_NATIVE("creationTime");
+ if(((file->isOpen)?
+ PR_GetOpenFileInfo(file->handle, &info):
+ PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ goto out;
+ }
+
+ PR_ExplodeTime(info.creationTime, PR_LocalTimeParameters,&expandedTime);
+ *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
+ expandedTime.tm_month,
+ expandedTime.tm_mday,
+ expandedTime.tm_hour,
+ expandedTime.tm_min,
+ expandedTime.tm_sec));
+ break;
+ case FILE_MODIFIED:
+ SECURITY_CHECK(cx, NULL, "lastModified", file);
+ JSFILE_CHECK_NATIVE("lastModified");
+ if(((file->isOpen)?
+ PR_GetOpenFileInfo(file->handle, &info):
+ PR_GetFileInfo(file->path, &info))!=PR_SUCCESS){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path);
+ goto out;
+ }
+
+ PR_ExplodeTime(info.modifyTime, PR_LocalTimeParameters, &expandedTime);
+ *vp = OBJECT_TO_JSVAL(js_NewDateObject(cx, expandedTime.tm_year,
+ expandedTime.tm_month,
+ expandedTime.tm_mday,
+ expandedTime.tm_hour,
+ expandedTime.tm_min,
+ expandedTime.tm_sec));
+ break;
+ case FILE_SIZE:
+ SECURITY_CHECK(cx, NULL, "size", file);
+ *vp = js_size(cx, file);
+ break;
+ case FILE_LENGTH:
+ SECURITY_CHECK(cx, NULL, "length", file);
+ JSFILE_CHECK_NATIVE("length");
+
+ if (js_isDirectory(cx, file)) { /* XXX debug me */
+ PRDir *dir;
+ PRDirEntry *entry;
+ jsint count = 0;
+
+ if(!(dir = PR_OpenDir(file->path))){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_OPEN_DIR, file->path);
+ goto out;
+ }
+
+ while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH))) {
+ count++;
+ }
+
+ if(!PR_CloseDir(dir)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_OP_FAILED, "close", file->path);
+
+ goto out;
+ }
+
+ *vp = INT_TO_JSVAL(count);
+ break;
+ }else{
+ /* return file size */
+ *vp = js_size(cx, file);
+ }
+ break;
+ case FILE_RANDOMACCESS:
+ SECURITY_CHECK(cx, NULL, "hasRandomAccess", file);
+ JSFILE_CHECK_OPEN("hasRandomAccess");
+ *vp = BOOLEAN_TO_JSVAL(file->hasRandomAccess);
+ break;
+ case FILE_POSITION:
+ SECURITY_CHECK(cx, NULL, "position", file);
+ JSFILE_CHECK_NATIVE("position");
+ JSFILE_CHECK_OPEN("position");
+
+ if(!file->hasRandomAccess){
+ JS_ReportWarning(cx, "File %s doesn't support random access, can't report the position, proceeding");
+ *vp = JSVAL_VOID;
+ break;
+ }
+
+ if (file->isOpen && js_isFile(cx, file)) {
+ int pos = PR_Seek(file->handle, 0, PR_SEEK_CUR);
+ if(pos!=-1){
+ *vp = INT_TO_JSVAL(pos);
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_REPORT_POSITION, file->path);
+ goto out;
+ }
+ }else {
+ JS_ReportWarning(cx, "File %s is closed or not a plain file,"
+ " can't report position, proceeding");
+ goto out;
+ }
+ break;
+ default:
+ SECURITY_CHECK(cx, NULL, "file_access", file);
+
+ /* this is some other property -- try to use the dir["file"] syntax */
+ if (js_isDirectory(cx, file)) {
+ PRDir *dir = NULL;
+ PRDirEntry *entry = NULL;
+ char *prop_name;
+
+ str = JS_ValueToString(cx, id);
+ if (!str)
+ return JS_FALSE;
+
+ prop_name = JS_GetStringBytes(str);
+
+ /* no native files past this point */
+ dir = PR_OpenDir(file->path);
+ if(!dir) {
+ /* This is probably not a directory */
+ JS_ReportWarning(cx, "Can't open directory %s", file->path);
+ return JS_FALSE;
+ }
+
+ while ((entry = PR_ReadDir(dir, PR_SKIP_NONE)) != NULL) {
+ if (!strcmp(entry->name, prop_name)){
+ bytes = js_combinePath(cx, file->path, prop_name);
+ *vp = OBJECT_TO_JSVAL(js_NewFileObject(cx, bytes));
+ PR_CloseDir(dir);
+ JS_free(cx, bytes);
+ return !JSVAL_IS_NULL(*vp);
+ }
+ }
+ PR_CloseDir(dir);
+ }
+ }
+ return JS_TRUE;
+
+out:
+ return JS_FALSE;
+}
+
+static JSBool
+file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSFile *file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+ jsint slot;
+
+ if (JSVAL_IS_STRING(id)){
+ return JS_TRUE;
+ }
+
+ slot = JSVAL_TO_INT(id);
+
+ switch (slot) {
+ /* File.position = 10 */
+ case FILE_POSITION:
+ SECURITY_CHECK(cx, NULL, "set_position", file);
+ JSFILE_CHECK_NATIVE("set_position");
+
+ if(!file->hasRandomAccess){
+ JS_ReportWarning(cx, "File %s doesn't support random access, can't "
+ "report the position, proceeding");
+ goto out;
+ }
+
+ if (file->isOpen && js_isFile(cx, file)) {
+ int32 pos;
+ int32 offset;
+
+ if (!JS_ValueToInt32(cx, *vp, &offset)){
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, "position", *vp);
+ goto out;
+ }
+
+ pos = PR_Seek(file->handle, offset, PR_SEEK_SET);
+
+ if(pos!=-1){
+ *vp = INT_TO_JSVAL(pos);
+ }else{
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_CANNOT_SET_POSITION, file->path);
+ goto out;
+ }
+ } else {
+ JS_ReportWarning(cx, "File %s is closed or not a file, can't set "
+ "position, proceeding", file->path);
+ goto out;
+ }
+ }
+
+ return JS_TRUE;
+out:
+ return JS_FALSE;
+}
+
+/*
+ File.currentDir = new File("D:\") or File.currentDir = "D:\"
+*/
+static JSBool
+file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSFile *file;
+
+ file = JS_GetInstancePrivate(cx, obj, &js_FileClass, NULL);
+
+ /* Look at the rhs and extract a file object from it */
+ if (JSVAL_IS_OBJECT(*vp)) {
+ if (JS_InstanceOf(cx, obj, &js_FileClass, NULL)) {
+ /* Braindamaged rhs -- just return the old value */
+ if (file && (!js_exists(cx, file) || !js_isDirectory(cx, file))) {
+ JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
+ return JS_FALSE;
+ } else {
+ chdir(file->path);
+ return JS_TRUE;
+ }
+ } else {
+ return JS_FALSE;
+ }
+ } else {
+ JSObject *rhsObject;
+ char *path;
+
+ path = JS_GetStringBytes(JS_ValueToString(cx, *vp));
+ rhsObject = js_NewFileObject(cx, path);
+ if (!rhsObject)
+ return JS_FALSE;
+
+ if (!file || !js_exists(cx, file) || !js_isDirectory(cx, file)){
+ JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
+ } else {
+ *vp = OBJECT_TO_JSVAL(rhsObject);
+ chdir(path);
+ }
+ }
+
+ return JS_TRUE;
+}
+
+/* Declare class */
+JSClass js_FileClass = {
+ "File", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_File),
+ JS_PropertyStub, JS_PropertyStub, file_getProperty, file_setProperty,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, file_finalize
+};
+
+/* -------------------- Functions exposed to the outside -------------------- */
+JS_PUBLIC_API(JSObject*)
+js_InitFileClass(JSContext *cx, JSObject* obj)
+{
+ JSObject *file, *ctor, *afile;
+ jsval vp;
+ char *currentdir;
+ char separator[2];
+
+ file = JS_InitClass(cx, obj, NULL, &js_FileClass, file_constructor, 1,
+ file_props, file_functions, NULL, NULL);
+ if (!file) {
+ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
+ JSFILEMSG_INIT_FAILED);
+ return NULL;
+ }
+
+ ctor = JS_GetConstructor(cx, file);
+ if (!ctor) return NULL;
+
+ /* Define CURRENTDIR property. We are doing this to get a
+ slash at the end of the current dir */
+ afile = js_NewFileObject(cx, CURRENT_DIR);
+ currentdir = JS_malloc(cx, MAX_PATH_LENGTH);
+ currentdir = getcwd(currentdir, MAX_PATH_LENGTH);
+ afile = js_NewFileObject(cx, currentdir);
+ JS_free(cx, currentdir);
+ vp = OBJECT_TO_JSVAL(afile);
+ JS_DefinePropertyWithTinyId(cx, ctor, CURRENTDIR_PROPERTY, 0, vp,
+ JS_PropertyStub, file_currentDirSetter,
+ JSPROP_ENUMERATE | JSPROP_READONLY );
+
+ /* Define input */
+ vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin,
+ STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE));
+ JS_SetProperty(cx, ctor, "input", &vp);
+
+ /* Define output */
+ vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdout,
+ STDOUTPUT_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
+ JS_SetProperty(cx, ctor, "output", &vp);
+
+ /* Define error */
+ vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stderr,
+ STDERROR_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
+ JS_SetProperty(cx, ctor, "error", &vp);
+
+ separator[0] = FILESEPARATOR;
+ separator[1] = '\0';
+ vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, separator));
+ JS_DefinePropertyWithTinyId(cx, ctor, SEPARATOR_PROPERTY, 0, vp,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_READONLY );
+ return file;
+}
+#endif /* JS_HAS_FILE_OBJECT */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfile.h b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.h
new file mode 100644
index 0000000..78707e8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _jsfile_h__
+#define _jsfile_h__
+
+#if JS_HAS_FILE_OBJECT
+
+#include "jsobj.h"
+
+extern JS_PUBLIC_API(JSObject*)
+js_InitFileClass(JSContext *cx, JSObject* obj);
+
+extern JS_PUBLIC_API(JSObject*)
+js_NewFileObject(JSContext *cx, char *bytes);
+
+extern JSClass js_FileClass;
+
+#endif /* JS_HAS_FILE_OBJECT */
+#endif /* _jsfile_h__ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg
new file mode 100644
index 0000000..137b35d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfile.msg
@@ -0,0 +1,90 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ Error messages for jsfile.c. See js.msg for format specification.
+*/
+
+MSG_DEF(JSFILEMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSFILEMSG_FILE_CONSTRUCTOR_UNDEFINED_ERROR, 1, 0, JSEXN_NONE, "File constructor is undefined")
+MSG_DEF(JSFILEMSG_FILE_CURRENTDIR_UNDEFINED_ERROR, 2, 0, JSEXN_NONE, "File.currentDir is undefined")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, 3, 1, JSEXN_NONE, "The first argument {0} to file.open must be a string")
+MSG_DEF(JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, 4, 0, JSEXN_NONE, "The second argument to file.open must be a string")
+MSG_DEF(JSFILEMSG_CANNOT_COPY_FILE_OPEN_FOR_WRITING_ERROR, 5, 1, JSEXN_NONE, "Cannot copy file {0} open for writing")
+MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_INFO_ERROR, 6, 1, JSEXN_NONE, "Cannot access file information for {0}")
+MSG_DEF(JSFILEMSG_COPY_READ_ERROR, 7, 1, JSEXN_NONE, "An error occured while attempting to read a file {0} to copy")
+MSG_DEF(JSFILEMSG_COPY_WRITE_ERROR, 8, 1, JSEXN_NONE, "An error occured while attempting to copy into file {0}")
+MSG_DEF(JSFILEMSG_EXPECTS_ONE_ARG_ERROR, 9, 0, JSEXN_NONE, "Operation {0} expects one argument, not {1}")
+MSG_DEF(JSFILEMSG_CANNOT_FLUSH_CLOSE_FILE_ERROR, 10, 1, JSEXN_NONE, "Cannot flush closed file {0}")
+MSG_DEF(JSFILEMSG_CANNOT_OPEN_WRITING_ERROR, 11, 1, JSEXN_NONE, "Cannot open file {0} for writing")
+MSG_DEF(JSFILEMSG_WRITEALL_EXPECTS_ONE_ARG_ERROR, 12, 0, JSEXN_NONE, "writeAll expects one argument")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR, 13, 0, JSEXN_NONE, "writeAll expects an array as an argument")
+MSG_DEF(JSFILEMSG_UNUSED0, 14, 0, JSEXN_NONE, "Unused error message slot")
+MSG_DEF(JSFILEMSG_CANNOT_OPEN_FILE_ERROR, 15, 1, JSEXN_NONE, "Cannot open file {0}")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, 16, 1, JSEXN_NONE, "The argument to the File constructor {0} must be a string")
+MSG_DEF(JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED, 17, 0, JSEXN_NONE, "Bidirectional pipes are not supported")
+MSG_DEF(JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES, 18, 2, JSEXN_NONE, "The opening mode you have chosen {0} is not supported by the pipe you are trying to open: {1}")
+MSG_DEF(JSFILEMSG_OPEN_FAILED, 19, 1, JSEXN_NONE, "open on file {0} failed")
+MSG_DEF(JSFILEMSG_CLOSE_FAILED, 20, 1, JSEXN_NONE, "close on file {0} failed")
+MSG_DEF(JSFILEMSG_PCLOSE_FAILED, 21, 1, JSEXN_NONE, "pclose on file {0} failed")
+MSG_DEF(JSFILEMSG_REMOVE_FAILED, 22, 1, JSEXN_NONE, "remove on file {0} failed")
+MSG_DEF(JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, 23, 1, JSEXN_NONE, "Cannot access file status for {0}")
+MSG_DEF(JSFILEMSG_RENAME_FAILED, 24, 2, JSEXN_NONE, "Cannot rename {0} to {1}")
+MSG_DEF(JSFILEMSG_WRITE_FAILED, 25, 1, JSEXN_NONE, "Write failed on file {0}")
+MSG_DEF(JSFILEMSG_READ_FAILED, 26, 1, JSEXN_NONE, "Read failed on file {0}")
+MSG_DEF(JSFILEMSG_SKIP_FAILED, 27, 1, JSEXN_NONE, "Skip failed on file {0}")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_FUNCTION_OR_REGEX, 28, 1, JSEXN_NONE, "The first argument to file.list must be a function or a regex")
+MSG_DEF(JSFILEMSG_CANNOT_DO_LIST_ON_A_FILE, 29, 1, JSEXN_NONE, "{0} must be a directory, cannot do list")
+MSG_DEF(JSFILEMSG_NATIVE_OPERATION_IS_NOT_SUPPORTED, 30, 2, JSEXN_NONE, "Native operation {0} is not supported on {1}")
+MSG_DEF(JSFILEMSG_CANNOT_SET_PRIVATE_FILE, 31, 1, JSEXN_NONE, "Cannot set private data for file {0}")
+MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_MUST_BE_A_NUMBER, 32, 2, JSEXN_NONE, "First argument to {0} must be a number, not {1}")
+MSG_DEF(JSFILEMSG_CANNOT_WRITE, 33, 1, JSEXN_NONE, "Cannot write to {0}, file mode is different")
+MSG_DEF(JSFILEMSG_CANNOT_READ, 34, 1, JSEXN_NONE, "Cannot read from {0}, file mode is different")
+MSG_DEF(JSFILEMSG_CANNOT_FLUSH, 35, 1, JSEXN_NONE, "Flush failed on {0}")
+MSG_DEF(JSFILEMSG_OP_FAILED, 36, 1, JSEXN_NONE, "File operation {0} failed")
+MSG_DEF(JSFILEMSG_FILE_MUST_BE_OPEN, 37, 1, JSEXN_NONE, "File must be open for {0}")
+MSG_DEF(JSFILEMSG_FILE_MUST_BE_CLOSED, 38, 1, JSEXN_NONE, "File must be closed for {0}")
+MSG_DEF(JSFILEMSG_NO_RANDOM_ACCESS, 39, 1, JSEXN_NONE, "File {0} doesn't allow random access")
+MSG_DEF(JSFILEMSG_OBJECT_CREATION_FAILED, 40, 1, JSEXN_NONE, "Couldn't create {0}")
+MSG_DEF(JSFILEMSG_CANNOT_OPEN_DIR, 41, 1, JSEXN_NONE, "Couldn't open directory {0}")
+MSG_DEF(JSFILEMSG_CANNOT_REPORT_POSITION, 42, 1, JSEXN_NONE, "Couldn't report position for {0}")
+MSG_DEF(JSFILEMSG_CANNOT_SET_POSITION, 43, 1, JSEXN_NONE, "Couldn't set position for {0}")
+MSG_DEF(JSFILEMSG_INIT_FAILED, 44, 0, JSEXN_NONE, "File class initialization failed")
+
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp
new file mode 100644
index 0000000..a492bcc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.cpp
@@ -0,0 +1,2706 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS function support.
+ */
+#include "jsstddef.h"
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsexn.h"
+#include "jsstaticcheck.h"
+
+#if JS_HAS_GENERATORS
+# include "jsiter.h"
+#endif
+
+#if JS_HAS_XDR
+# include "jsxdrapi.h"
+#endif
+
+/* Generic function/call/arguments tinyids -- also reflected bit numbers. */
+enum {
+ CALL_ARGUMENTS = -1, /* predefined arguments local variable */
+ ARGS_LENGTH = -2, /* number of actual args, arity if inactive */
+ ARGS_CALLEE = -3, /* reference from arguments to active funobj */
+ FUN_ARITY = -4, /* number of formal parameters; desired argc */
+ FUN_NAME = -5, /* function name, "" if anonymous */
+ FUN_CALLER = -6 /* Function.prototype.caller, backward compat */
+};
+
+#if JSFRAME_OVERRIDE_BITS < 8
+# error "not enough override bits in JSStackFrame.flags!"
+#endif
+
+#define TEST_OVERRIDE_BIT(fp, tinyid) \
+ ((fp)->flags & JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))
+
+#define SET_OVERRIDE_BIT(fp, tinyid) \
+ ((fp)->flags |= JS_BIT(JSFRAME_OVERRIDE_SHIFT - ((tinyid) + 1)))
+
+JSBool
+js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp)
+{
+ JSObject *argsobj;
+
+ if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ JS_ASSERT(fp->callobj);
+ return OBJ_GET_PROPERTY(cx, fp->callobj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .argumentsAtom),
+ vp);
+ }
+ argsobj = js_GetArgsObject(cx, fp);
+ if (!argsobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(argsobj);
+ return JS_TRUE;
+}
+
+static JSBool
+MarkArgDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)
+{
+ JSObject *argsobj;
+ jsval bmapval, bmapint;
+ size_t nbits, nbytes;
+ jsbitmap *bitmap;
+
+ argsobj = fp->argsobj;
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
+ nbits = fp->argc;
+ JS_ASSERT(slot < nbits);
+ if (JSVAL_IS_VOID(bmapval)) {
+ if (nbits <= JSVAL_INT_BITS) {
+ bmapint = 0;
+ bitmap = (jsbitmap *) &bmapint;
+ } else {
+ nbytes = JS_HOWMANY(nbits, JS_BITS_PER_WORD) * sizeof(jsbitmap);
+ bitmap = (jsbitmap *) JS_malloc(cx, nbytes);
+ if (!bitmap)
+ return JS_FALSE;
+ memset(bitmap, 0, nbytes);
+ bmapval = PRIVATE_TO_JSVAL(bitmap);
+ JS_SetReservedSlot(cx, argsobj, 0, bmapval);
+ }
+ } else {
+ if (nbits <= JSVAL_INT_BITS) {
+ bmapint = JSVAL_TO_INT(bmapval);
+ bitmap = (jsbitmap *) &bmapint;
+ } else {
+ bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);
+ }
+ }
+ JS_SET_BIT(bitmap, slot);
+ if (bitmap == (jsbitmap *) &bmapint) {
+ bmapval = INT_TO_JSVAL(bmapint);
+ JS_SetReservedSlot(cx, argsobj, 0, bmapval);
+ }
+ return JS_TRUE;
+}
+
+/* NB: Infallible predicate, false does not mean error/exception. */
+static JSBool
+ArgWasDeleted(JSContext *cx, JSStackFrame *fp, uintN slot)
+{
+ JSObject *argsobj;
+ jsval bmapval, bmapint;
+ jsbitmap *bitmap;
+
+ argsobj = fp->argsobj;
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
+ if (JSVAL_IS_VOID(bmapval))
+ return JS_FALSE;
+ if (fp->argc <= JSVAL_INT_BITS) {
+ bmapint = JSVAL_TO_INT(bmapval);
+ bitmap = (jsbitmap *) &bmapint;
+ } else {
+ bitmap = (jsbitmap *) JSVAL_TO_PRIVATE(bmapval);
+ }
+ return JS_TEST_BIT(bitmap, slot) != 0;
+}
+
+JSBool
+js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp)
+{
+ jsval val;
+ JSObject *obj;
+ uintN slot;
+
+ if (TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ JS_ASSERT(fp->callobj);
+ if (!OBJ_GET_PROPERTY(cx, fp->callobj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .argumentsAtom),
+ &val)) {
+ return JS_FALSE;
+ }
+ if (JSVAL_IS_PRIMITIVE(val)) {
+ obj = js_ValueToNonNullObject(cx, val);
+ if (!obj)
+ return JS_FALSE;
+ } else {
+ obj = JSVAL_TO_OBJECT(val);
+ }
+ return OBJ_GET_PROPERTY(cx, obj, id, vp);
+ }
+
+ *vp = JSVAL_VOID;
+ if (JSID_IS_INT(id)) {
+ slot = (uintN) JSID_TO_INT(id);
+ if (slot < fp->argc) {
+ if (fp->argsobj && ArgWasDeleted(cx, fp, slot))
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
+ *vp = fp->argv[slot];
+ } else {
+ /*
+ * Per ECMA-262 Ed. 3, 10.1.8, last bulleted item, do not share
+ * storage between the formal parameter and arguments[k] for all
+ * fp->argc <= k && k < fp->fun->nargs. For example, in
+ *
+ * function f(x) { x = 42; return arguments[0]; }
+ * f();
+ *
+ * the call to f should return undefined, not 42. If fp->argsobj
+ * is null at this point, as it would be in the example, return
+ * undefined in *vp.
+ */
+ if (fp->argsobj)
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
+ }
+ } else {
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
+ if (fp->argsobj && TEST_OVERRIDE_BIT(fp, ARGS_LENGTH))
+ return OBJ_GET_PROPERTY(cx, fp->argsobj, id, vp);
+ *vp = INT_TO_JSVAL((jsint) fp->argc);
+ }
+ }
+ return JS_TRUE;
+}
+
+JSObject *
+js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *argsobj, *global, *parent;
+
+ /*
+ * We must be in a function activation; the function must be lightweight
+ * or else fp must have a variable object.
+ */
+ JS_ASSERT(fp->fun && (!(fp->fun->flags & JSFUN_HEAVYWEIGHT) || fp->varobj));
+
+ /* Skip eval and debugger frames. */
+ while (fp->flags & JSFRAME_SPECIAL)
+ fp = fp->down;
+
+ /* Create an arguments object for fp only if it lacks one. */
+ argsobj = fp->argsobj;
+ if (argsobj)
+ return argsobj;
+
+ /* Link the new object to fp so it can get actual argument values. */
+ argsobj = js_NewObject(cx, &js_ArgumentsClass, NULL, NULL, 0);
+ if (!argsobj || !JS_SetPrivate(cx, argsobj, fp)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+
+ /*
+ * Give arguments an intrinsic scope chain link to fp's global object.
+ * Since the arguments object lacks a prototype because js_ArgumentsClass
+ * is not initialized, js_NewObject won't assign a default parent to it.
+ *
+ * Therefore if arguments is used as the head of an eval scope chain (via
+ * a direct or indirect call to eval(program, arguments)), any reference
+ * to a standard class object in the program will fail to resolve due to
+ * js_GetClassPrototype not being able to find a global object containing
+ * the standard prototype by starting from arguments and following parent.
+ */
+ global = fp->scopeChain;
+ while ((parent = OBJ_GET_PARENT(cx, global)) != NULL)
+ global = parent;
+ STOBJ_SET_PARENT(argsobj, global);
+ fp->argsobj = argsobj;
+ return argsobj;
+}
+
+static JSBool
+args_enumerate(JSContext *cx, JSObject *obj);
+
+JS_FRIEND_API(JSBool)
+js_PutArgsObject(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *argsobj;
+ jsval bmapval, rval;
+ JSBool ok;
+ JSRuntime *rt;
+
+ /*
+ * Reuse args_enumerate here to reflect fp's actual arguments as indexed
+ * elements of argsobj. Do this first, before clearing and freeing the
+ * deleted argument slot bitmap, because args_enumerate depends on that.
+ */
+ argsobj = fp->argsobj;
+ ok = args_enumerate(cx, argsobj);
+
+ /*
+ * Now clear the deleted argument number bitmap slot and free the bitmap,
+ * if one was actually created due to 'delete arguments[0]' or similar.
+ */
+ (void) JS_GetReservedSlot(cx, argsobj, 0, &bmapval);
+ if (!JSVAL_IS_VOID(bmapval)) {
+ JS_SetReservedSlot(cx, argsobj, 0, JSVAL_VOID);
+ if (fp->argc > JSVAL_INT_BITS)
+ JS_free(cx, JSVAL_TO_PRIVATE(bmapval));
+ }
+
+ /*
+ * Now get the prototype properties so we snapshot fp->fun and fp->argc
+ * before fp goes away.
+ */
+ rt = cx->runtime;
+ ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
+ &rval);
+ ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.calleeAtom),
+ &rval);
+ ok &= js_GetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
+ &rval);
+ ok &= js_SetProperty(cx, argsobj, ATOM_TO_JSID(rt->atomState.lengthAtom),
+ &rval);
+
+ /*
+ * Clear the private pointer to fp, which is about to go away (js_Invoke).
+ * Do this last because the args_enumerate and js_GetProperty calls above
+ * need to follow the private slot to find fp.
+ */
+ ok &= JS_SetPrivate(cx, argsobj, NULL);
+ fp->argsobj = NULL;
+ return ok;
+}
+
+static JSBool
+args_delProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSStackFrame *fp;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case ARGS_CALLEE:
+ case ARGS_LENGTH:
+ SET_OVERRIDE_BIT(fp, slot);
+ break;
+
+ default:
+ if ((uintN)slot < fp->argc && !MarkArgDeleted(cx, fp, slot))
+ return JS_FALSE;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+args_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSStackFrame *fp;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case ARGS_CALLEE:
+ if (!TEST_OVERRIDE_BIT(fp, slot))
+ *vp = OBJECT_TO_JSVAL(fp->callee);
+ break;
+
+ case ARGS_LENGTH:
+ if (!TEST_OVERRIDE_BIT(fp, slot))
+ *vp = INT_TO_JSVAL((jsint)fp->argc);
+ break;
+
+ default:
+ if ((uintN)slot < fp->argc && !ArgWasDeleted(cx, fp, slot))
+ *vp = fp->argv[slot];
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+args_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSStackFrame *fp;
+ jsint slot;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case ARGS_CALLEE:
+ case ARGS_LENGTH:
+ SET_OVERRIDE_BIT(fp, slot);
+ break;
+
+ default:
+ if (FUN_INTERPRETED(fp->fun) &&
+ (uintN)slot < fp->argc &&
+ !ArgWasDeleted(cx, fp, slot)) {
+ fp->argv[slot] = *vp;
+ }
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+args_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSStackFrame *fp;
+ uintN slot;
+ JSString *str;
+ JSAtom *atom;
+ intN tinyid;
+ jsval value;
+
+ *objp = NULL;
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ if (JSVAL_IS_INT(id)) {
+ slot = JSVAL_TO_INT(id);
+ if (slot < fp->argc && !ArgWasDeleted(cx, fp, slot)) {
+ /* XXX ECMA specs DontEnum, contrary to other array-like objects */
+ if (!js_DefineProperty(cx, obj, INT_JSVAL_TO_JSID(id),
+ fp->argv[slot],
+ args_getProperty, args_setProperty,
+ 0, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ } else {
+ str = JSVAL_TO_STRING(id);
+ atom = cx->runtime->atomState.lengthAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ tinyid = ARGS_LENGTH;
+ value = INT_TO_JSVAL(fp->argc);
+ } else {
+ atom = cx->runtime->atomState.calleeAtom;
+ if (str == ATOM_TO_STRING(atom)) {
+ tinyid = ARGS_CALLEE;
+ value = OBJECT_TO_JSVAL(fp->callee);
+ } else {
+ atom = NULL;
+
+ /* Quell GCC overwarnings. */
+ tinyid = 0;
+ value = JSVAL_NULL;
+ }
+ }
+
+ if (atom && !TEST_OVERRIDE_BIT(fp, tinyid)) {
+ if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom), value,
+ args_getProperty, args_setProperty, 0,
+ SPROP_HAS_SHORTID, tinyid, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+args_enumerate(JSContext *cx, JSObject *obj)
+{
+ JSStackFrame *fp;
+ JSObject *pobj;
+ JSProperty *prop;
+ uintN slot, argc;
+
+ fp = (JSStackFrame *)
+ JS_GetInstancePrivate(cx, obj, &js_ArgumentsClass, NULL);
+ if (!fp)
+ return JS_TRUE;
+ JS_ASSERT(fp->argsobj);
+
+ /*
+ * Trigger reflection with value snapshot in args_resolve using a series
+ * of js_LookupProperty calls. We handle length, callee, and the indexed
+ * argument properties. We know that args_resolve covers all these cases
+ * and creates direct properties of obj, but that it may fail to resolve
+ * length or callee if overridden.
+ */
+ if (!js_LookupProperty(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.lengthAtom),
+ &pobj, &prop)) {
+ return JS_FALSE;
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ if (!js_LookupProperty(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.calleeAtom),
+ &pobj, &prop)) {
+ return JS_FALSE;
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ argc = fp->argc;
+ for (slot = 0; slot < argc; slot++) {
+ if (!js_LookupProperty(cx, obj, INT_TO_JSID((jsint)slot), &pobj, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+
+#if JS_HAS_GENERATORS
+/*
+ * If a generator-iterator's arguments or call object escapes, it needs to
+ * mark its generator object.
+ */
+static void
+args_or_call_trace(JSTracer *trc, JSObject *obj)
+{
+ JSStackFrame *fp;
+
+ fp = (JSStackFrame *) JS_GetPrivate(trc->context, obj);
+ if (fp && (fp->flags & JSFRAME_GENERATOR)) {
+ JS_CALL_OBJECT_TRACER(trc, FRAME_TO_GENERATOR(fp)->obj,
+ "FRAME_TO_GENERATOR(fp)->obj");
+ }
+}
+#else
+# define args_or_call_trace NULL
+#endif
+
+/*
+ * The Arguments class is not initialized via JS_InitClass, and must not be,
+ * because its name is "Object". Per ECMA, that causes instances of it to
+ * delegate to the object named by Object.prototype. It also ensures that
+ * arguments.toString() returns "[object Object]".
+ *
+ * The JSClass functions below collaborate to lazily reflect and synchronize
+ * actual argument values, argument count, and callee function object stored
+ * in a JSStackFrame with their corresponding property values in the frame's
+ * arguments object.
+ */
+JSClass js_ArgumentsClass = {
+ js_Object_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
+ JS_PropertyStub, args_delProperty,
+ args_getProperty, args_setProperty,
+ args_enumerate, (JSResolveOp) args_resolve,
+ JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ JS_CLASS_TRACE(args_or_call_trace), NULL
+};
+
+#define JSSLOT_SCRIPTED_FUNCTION (JSSLOT_PRIVATE + 1)
+#define JSSLOT_CALL_ARGUMENTS (JSSLOT_PRIVATE + 2)
+#define CALL_CLASS_FIXED_RESERVED_SLOTS 2
+
+JSObject *
+js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent)
+{
+ JSObject *callobj, *funobj;
+
+ /* Create a call object for fp only if it lacks one. */
+ JS_ASSERT(fp->fun);
+ callobj = fp->callobj;
+ if (callobj)
+ return callobj;
+
+ /* The default call parent is its function's parent (static link). */
+ if (!parent) {
+ funobj = fp->callee;
+ if (funobj)
+ parent = OBJ_GET_PARENT(cx, funobj);
+ }
+
+ /* Create the call object and link it to its stack frame. */
+ callobj = js_NewObject(cx, &js_CallClass, NULL, parent, 0);
+ if (!callobj)
+ return NULL;
+
+ JS_SetPrivate(cx, callobj, fp);
+ STOBJ_SET_SLOT(callobj, JSSLOT_SCRIPTED_FUNCTION,
+ OBJECT_TO_JSVAL(FUN_OBJECT(fp->fun)));
+ fp->callobj = callobj;
+
+ /* Make callobj be the scope chain and the variables object. */
+ JS_ASSERT(fp->scopeChain == parent);
+ fp->scopeChain = callobj;
+ fp->varobj = callobj;
+ return callobj;
+}
+
+JSFunction *
+js_GetCallObjectFunction(JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_CallClass);
+ v = STOBJ_GET_SLOT(obj, JSSLOT_SCRIPTED_FUNCTION);
+ if (JSVAL_IS_VOID(v)) {
+ /* Newborn or prototype object. */
+ return NULL;
+ }
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ return (JSFunction *) JSVAL_TO_OBJECT(v);
+}
+
+JS_FRIEND_API(JSBool)
+js_PutCallObject(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *callobj;
+ JSBool ok;
+ JSFunction *fun;
+ uintN n;
+ JSScope *scope;
+
+ /*
+ * Since for a call object all fixed slots happen to be taken, we can copy
+ * arguments and variables straight into JSObject.dslots.
+ */
+ JS_STATIC_ASSERT(JS_INITIAL_NSLOTS - JSSLOT_PRIVATE ==
+ 1 + CALL_CLASS_FIXED_RESERVED_SLOTS);
+
+ callobj = fp->callobj;
+ if (!callobj)
+ return JS_TRUE;
+
+ /*
+ * Get the arguments object to snapshot fp's actual argument values.
+ */
+ ok = JS_TRUE;
+ if (fp->argsobj) {
+ if (!TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ STOBJ_SET_SLOT(callobj, JSSLOT_CALL_ARGUMENTS,
+ OBJECT_TO_JSVAL(fp->argsobj));
+ }
+ ok &= js_PutArgsObject(cx, fp);
+ }
+
+ fun = fp->fun;
+ JS_ASSERT(fun == js_GetCallObjectFunction(callobj));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n != 0) {
+ JS_LOCK_OBJ(cx, callobj);
+ n += JS_INITIAL_NSLOTS;
+ if (n > STOBJ_NSLOTS(callobj))
+ ok &= js_ReallocSlots(cx, callobj, n, JS_TRUE);
+ scope = OBJ_SCOPE(callobj);
+ if (ok) {
+ memcpy(callobj->dslots, fp->argv, fun->nargs * sizeof(jsval));
+ memcpy(callobj->dslots + fun->nargs, fp->slots,
+ fun->u.i.nvars * sizeof(jsval));
+ if (scope->object == callobj && n > scope->map.freeslot)
+ scope->map.freeslot = n;
+ }
+ JS_UNLOCK_SCOPE(cx, scope);
+ }
+
+ /*
+ * Clear the private pointer to fp, which is about to go away (js_Invoke).
+ * Do this last because js_GetProperty calls above need to follow the
+ * private slot to find fp.
+ */
+ JS_SetPrivate(cx, callobj, NULL);
+ fp->callobj = NULL;
+ return ok;
+}
+
+static JSBool
+call_enumerate(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+ uintN n, i;
+ void *mark;
+ jsuword *names;
+ JSBool ok;
+ JSAtom *name;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ fun = js_GetCallObjectFunction(obj);
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0)
+ return JS_TRUE;
+
+ mark = JS_ARENA_MARK(&cx->tempPool);
+
+ MUST_FLOW_THROUGH("out");
+ names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
+ if (!names) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ for (i = 0; i != n; ++i) {
+ name = JS_LOCAL_NAME_TO_ATOM(names[i]);
+ if (!name)
+ continue;
+
+ /*
+ * Trigger reflection by looking up the name of the argument or
+ * variable.
+ */
+ ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(name), &pobj, &prop);
+ if (!ok)
+ goto out;
+
+ /*
+ * At this point the call object always has a property corresponding
+ * to the local name because call_resolve creates the property using
+ * JSPROP_PERMANENT.
+ */
+ JS_ASSERT(prop && pobj == obj);
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ ok = JS_TRUE;
+
+ out:
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return ok;
+}
+
+typedef enum JSCallPropertyKind {
+ JSCPK_ARGUMENTS,
+ JSCPK_ARG,
+ JSCPK_VAR
+} JSCallPropertyKind;
+
+static JSBool
+CallPropertyOp(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSCallPropertyKind kind, JSBool setter)
+{
+ JSFunction *fun;
+ JSStackFrame *fp;
+ uintN i;
+ jsval *array;
+
+ if (STOBJ_GET_CLASS(obj) != &js_CallClass)
+ return JS_TRUE;
+
+ fun = js_GetCallObjectFunction(obj);
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+
+ if (kind == JSCPK_ARGUMENTS) {
+ if (setter) {
+ if (fp)
+ SET_OVERRIDE_BIT(fp, CALL_ARGUMENTS);
+ STOBJ_SET_SLOT(obj, JSSLOT_CALL_ARGUMENTS, *vp);
+ } else {
+ if (fp && !TEST_OVERRIDE_BIT(fp, CALL_ARGUMENTS)) {
+ JSObject *argsobj;
+
+ argsobj = js_GetArgsObject(cx, fp);
+ if (!argsobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(argsobj);
+ } else {
+ *vp = STOBJ_GET_SLOT(obj, JSSLOT_CALL_ARGUMENTS);
+ }
+ }
+ return JS_TRUE;
+ }
+
+ JS_ASSERT((int16) JSVAL_TO_INT(id) == JSVAL_TO_INT(id));
+ i = (uint16) JSVAL_TO_INT(id);
+ JS_ASSERT_IF(kind == JSCPK_ARG, i < fun->nargs);
+ JS_ASSERT_IF(kind == JSCPK_VAR, i < fun->u.i.nvars);
+
+ if (!fp) {
+ i += CALL_CLASS_FIXED_RESERVED_SLOTS;
+ if (kind == JSCPK_VAR)
+ i += fun->nargs;
+ else
+ JS_ASSERT(kind == JSCPK_ARG);
+ return setter
+ ? JS_SetReservedSlot(cx, obj, i, *vp)
+ : JS_GetReservedSlot(cx, obj, i, vp);
+ }
+
+ if (kind == JSCPK_ARG) {
+ array = fp->argv;
+ } else {
+ JS_ASSERT(kind == JSCPK_VAR);
+ array = fp->slots;
+ }
+ if (setter)
+ array[i] = *vp;
+ else
+ *vp = array[i];
+ return JS_TRUE;
+}
+
+static JSBool
+GetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_FALSE);
+}
+
+static JSBool
+SetCallArguments(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARGUMENTS, JS_TRUE);
+}
+
+JSBool
+js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_FALSE);
+}
+
+static JSBool
+SetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_ARG, JS_TRUE);
+}
+
+JSBool
+js_GetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_FALSE);
+}
+
+static JSBool
+SetCallVar(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return CallPropertyOp(cx, obj, id, vp, JSCPK_VAR, JS_TRUE);
+}
+
+static JSBool
+call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
+ JSObject **objp)
+{
+ JSFunction *fun;
+ jsid id;
+ JSLocalKind localKind;
+ JSPropertyOp getter, setter;
+ uintN slot, attrs;
+
+ if (!JSVAL_IS_STRING(idval))
+ return JS_TRUE;
+
+ fun = js_GetCallObjectFunction(obj);
+ if (!fun)
+ return JS_TRUE;
+
+ if (!js_ValueToStringId(cx, idval, &id))
+ return JS_FALSE;
+
+ localKind = js_LookupLocal(cx, fun, JSID_TO_ATOM(id), &slot);
+ if (localKind != JSLOCAL_NONE) {
+ JS_ASSERT((uint16) slot == slot);
+ attrs = JSPROP_PERMANENT | JSPROP_SHARED;
+ if (localKind == JSLOCAL_ARG) {
+ JS_ASSERT(slot < fun->nargs);
+ getter = js_GetCallArg;
+ setter = SetCallArg;
+ } else {
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+ JS_ASSERT(slot < fun->u.i.nvars);
+ getter = js_GetCallVar;
+ setter = SetCallVar;
+ if (localKind == JSLOCAL_CONST)
+ attrs |= JSPROP_READONLY;
+ }
+ if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID, getter, setter,
+ attrs, SPROP_HAS_SHORTID, (int16) slot,
+ NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+
+ /*
+ * Resolve arguments so that we never store a particular Call object's
+ * arguments object reference in a Call prototype's |arguments| slot.
+ */
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.argumentsAtom)) {
+ if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID,
+ GetCallArguments, SetCallArguments,
+ JSPROP_PERMANENT | JSPROP_SHARED,
+ 0, 0, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ JSStackFrame *fp;
+
+ if (type == JSTYPE_FUNCTION) {
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+ if (fp) {
+ JS_ASSERT(fp->fun);
+ *vp = OBJECT_TO_JSVAL(fp->callee);
+ }
+ }
+ return JS_TRUE;
+}
+
+static uint32
+call_reserveSlots(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+
+ fun = js_GetCallObjectFunction(obj);
+ return JS_GET_LOCAL_NAME_COUNT(fun);
+}
+
+JS_FRIEND_DATA(JSClass) js_CallClass = {
+ js_Call_str,
+ JSCLASS_HAS_PRIVATE |
+ JSCLASS_HAS_RESERVED_SLOTS(CALL_CLASS_FIXED_RESERVED_SLOTS) |
+ JSCLASS_NEW_RESOLVE | JSCLASS_IS_ANONYMOUS |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Call),
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ call_enumerate, (JSResolveOp)call_resolve,
+ call_convert, JS_FinalizeStub,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, NULL,
+ JS_CLASS_TRACE(args_or_call_trace), call_reserveSlots
+};
+
+static JSBool
+fun_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSFunction *fun;
+ JSStackFrame *fp;
+ JSSecurityCallbacks *callbacks;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ slot = JSVAL_TO_INT(id);
+
+ /*
+ * Loop because getter and setter can be delegated from another class,
+ * but loop only for ARGS_LENGTH because we must pretend that f.length
+ * is in each function instance f, per ECMA-262, instead of only in the
+ * Function.prototype object (we use JSPROP_PERMANENT with JSPROP_SHARED
+ * to make it appear so).
+ *
+ * This code couples tightly to the attributes for the function_props[]
+ * initializers above, and to js_SetProperty and js_HasOwnProperty.
+ *
+ * It's important to allow delegating objects, even though they inherit
+ * this getter (fun_getProperty), to override arguments, arity, caller,
+ * and name. If we didn't return early for slot != ARGS_LENGTH, we would
+ * clobber *vp with the native property value, instead of letting script
+ * override that value in delegating objects.
+ *
+ * Note how that clobbering is what simulates JSPROP_READONLY for all of
+ * the non-standard properties when the directly addressed object (obj)
+ * is a function object (i.e., when this loop does not iterate).
+ */
+ while (!(fun = (JSFunction *)
+ JS_GetInstancePrivate(cx, obj, &js_FunctionClass, NULL))) {
+ if (slot != ARGS_LENGTH)
+ return JS_TRUE;
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (!obj)
+ return JS_TRUE;
+ }
+
+ /* Find fun's top-most activation record. */
+ for (fp = cx->fp; fp && (fp->fun != fun || (fp->flags & JSFRAME_SPECIAL));
+ fp = fp->down) {
+ continue;
+ }
+
+ switch (slot) {
+ case CALL_ARGUMENTS:
+ /* Warn if strict about f.arguments or equivalent unqualified uses. */
+ if (!JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_DEPRECATED_USAGE,
+ js_arguments_str)) {
+ return JS_FALSE;
+ }
+ if (fp) {
+ if (!js_GetArgsValue(cx, fp, vp))
+ return JS_FALSE;
+ } else {
+ *vp = JSVAL_NULL;
+ }
+ break;
+
+ case ARGS_LENGTH:
+ case FUN_ARITY:
+ *vp = INT_TO_JSVAL((jsint)fun->nargs);
+ break;
+
+ case FUN_NAME:
+ *vp = fun->atom
+ ? ATOM_KEY(fun->atom)
+ : STRING_TO_JSVAL(cx->runtime->emptyString);
+ break;
+
+ case FUN_CALLER:
+ if (fp && fp->down && fp->down->fun)
+ *vp = OBJECT_TO_JSVAL(fp->down->callee);
+ else
+ *vp = JSVAL_NULL;
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->checkObjectAccess) {
+ id = ATOM_KEY(cx->runtime->atomState.callerAtom);
+ if (!callbacks->checkObjectAccess(cx, obj, id, JSACC_READ, vp))
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ default:
+ /* XXX fun[0] and fun.arguments[0] are equivalent. */
+ if (fp && fp->fun && (uintN)slot < fp->fun->nargs)
+ *vp = fp->argv[slot];
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+/*
+ * ECMA-262 specifies that length is a property of function object instances,
+ * but we can avoid that space cost by delegating to a prototype property that
+ * is JSPROP_PERMANENT and JSPROP_SHARED. Each fun_getProperty call computes
+ * a fresh length value based on the arity of the individual function object's
+ * private data.
+ *
+ * The extensions below other than length, i.e., the ones not in ECMA-262,
+ * are neither JSPROP_READONLY nor JSPROP_SHARED, because for compatibility
+ * with ECMA we must allow a delegating object to override them. Therefore to
+ * avoid entraining garbage in Function.prototype slots, they must be resolved
+ * in non-prototype function objects, wherefore the lazy_function_props table
+ * and fun_resolve's use of it.
+ */
+#define LENGTH_PROP_ATTRS (JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED)
+
+static JSPropertySpec function_props[] = {
+ {js_length_str, ARGS_LENGTH, LENGTH_PROP_ATTRS, fun_getProperty, JS_PropertyStub},
+ {0,0,0,0,0}
+};
+
+typedef struct LazyFunctionProp {
+ uint16 atomOffset;
+ int8 tinyid;
+ uint8 attrs;
+} LazyFunctionProp;
+
+/* NB: no sentinel at the end -- use JS_ARRAY_LENGTH to bound loops. */
+static LazyFunctionProp lazy_function_props[] = {
+ {ATOM_OFFSET(arguments), CALL_ARGUMENTS, JSPROP_PERMANENT},
+ {ATOM_OFFSET(arity), FUN_ARITY, JSPROP_PERMANENT},
+ {ATOM_OFFSET(caller), FUN_CALLER, JSPROP_PERMANENT},
+ {ATOM_OFFSET(name), FUN_NAME, JSPROP_PERMANENT},
+};
+
+static JSBool
+fun_enumerate(JSContext *cx, JSObject *obj)
+{
+ jsid prototypeId;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ prototypeId = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, prototypeId, &pobj, &prop))
+ return JS_FALSE;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return JS_TRUE;
+}
+
+static JSBool
+fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ JSFunction *fun;
+ JSAtom *atom;
+ uintN i;
+
+ if (!JSVAL_IS_STRING(id))
+ return JS_TRUE;
+
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+
+ /*
+ * No need to reflect fun.prototype in 'fun.prototype = ... '.
+ *
+ * This is not just an optimization, because we must not resolve when
+ * defining hidden properties during compilation. The setup code for the
+ * prototype and the lazy properties below eventually calls the property
+ * hooks for the function object. That in turn calls fun_reserveSlots to
+ * get the number of the reserved slots which is just the number of
+ * regular expressions literals in the function. When compiling, that
+ * number is not yet ready so we must make sure that fun_resolve does
+ * nothing until the code for the function is generated.
+ */
+ if (flags & JSRESOLVE_ASSIGNING)
+ return JS_TRUE;
+
+ /*
+ * Ok, check whether id is 'prototype' and bootstrap the function object's
+ * prototype property.
+ */
+ atom = cx->runtime->atomState.classPrototypeAtom;
+ if (id == ATOM_KEY(atom)) {
+ JSObject *proto;
+
+ /*
+ * Beware of the wacky case of a user function named Object -- trying
+ * to find a prototype for that will recur back here _ad perniciem_.
+ */
+ if (fun->atom == CLASS_ATOM(cx, Object))
+ return JS_TRUE;
+
+ /*
+ * Make the prototype object to have the same parent as the function
+ * object itself.
+ */
+ proto = js_NewObject(cx, &js_ObjectClass, NULL, OBJ_GET_PARENT(cx, obj),
+ 0);
+ if (!proto)
+ return JS_FALSE;
+
+ /*
+ * ECMA (15.3.5.2) says that constructor.prototype is DontDelete for
+ * user-defined functions, but DontEnum | ReadOnly | DontDelete for
+ * native "system" constructors such as Object or Function. So lazily
+ * set the former here in fun_resolve, but eagerly define the latter
+ * in JS_InitClass, with the right attributes.
+ */
+ if (!js_SetClassPrototype(cx, obj, proto,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+
+ for (i = 0; i < JS_ARRAY_LENGTH(lazy_function_props); i++) {
+ LazyFunctionProp *lfp = &lazy_function_props[i];
+
+ atom = OFFSET_TO_ATOM(cx->runtime, lfp->atomOffset);
+ if (id == ATOM_KEY(atom)) {
+ if (!js_DefineNativeProperty(cx, obj,
+ ATOM_TO_JSID(atom), JSVAL_VOID,
+ fun_getProperty, JS_PropertyStub,
+ lfp->attrs, SPROP_HAS_SHORTID,
+ lfp->tinyid, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ return JS_TRUE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+fun_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
+{
+ switch (type) {
+ case JSTYPE_FUNCTION:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ default:
+ return js_TryValueOf(cx, obj, type, vp);
+ }
+}
+
+#if JS_HAS_XDR
+
+/* XXX store parent and proto, if defined */
+static JSBool
+fun_xdrObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSContext *cx;
+ JSFunction *fun;
+ uint32 nullAtom; /* flag to indicate if fun->atom is NULL */
+ uintN nargs, nvars, n;
+ uint32 localsword; /* word to xdr argument and variable counts */
+ uint32 flagsword; /* originally only flags was JS_XDRUint8'd */
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ cx = xdr->cx;
+ if (xdr->mode == JSXDR_ENCODE) {
+ fun = GET_FUNCTION_PRIVATE(cx, *objp);
+ if (!FUN_INTERPRETED(fun)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NOT_SCRIPTED_FUNCTION,
+ JS_GetFunctionName(fun));
+ return JS_FALSE;
+ }
+ nullAtom = !fun->atom;
+ nargs = fun->nargs;
+ nvars = fun->u.i.nvars;
+ localsword = (nargs << 16) | nvars;
+ flagsword = fun->flags;
+ } else {
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
+ if (!fun)
+ return JS_FALSE;
+ STOBJ_CLEAR_PARENT(FUN_OBJECT(fun));
+ STOBJ_CLEAR_PROTO(FUN_OBJECT(fun));
+#ifdef __GNUC__
+ nvars = nargs = 0; /* quell GCC uninitialized warning */
+#endif
+ }
+
+ /* From here on, control flow must flow through label out. */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, FUN_OBJECT(fun), &tvr);
+ ok = JS_TRUE;
+
+ if (!JS_XDRUint32(xdr, &nullAtom))
+ goto bad;
+ if (!nullAtom && !js_XDRStringAtom(xdr, &fun->atom))
+ goto bad;
+ if (!JS_XDRUint32(xdr, &localsword) ||
+ !JS_XDRUint32(xdr, &flagsword)) {
+ goto bad;
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ nargs = localsword >> 16;
+ nvars = localsword & JS_BITMASK(16);
+ JS_ASSERT(flagsword | JSFUN_INTERPRETED);
+ fun->flags = (uint16) flagsword;
+ }
+
+ /* do arguments and local vars */
+ n = nargs + nvars;
+ if (n != 0) {
+ void *mark;
+ uintN i;
+ uintN bitmapLength;
+ uint32 *bitmap;
+ jsuword *names;
+ JSAtom *name;
+ JSLocalKind localKind;
+
+ mark = JS_ARENA_MARK(&xdr->cx->tempPool);
+
+ /*
+ * From this point the control must flow via the label release_mark.
+ *
+ * To xdr the names we prefix the names with a bitmap descriptor and
+ * then xdr the names as strings. For argument names (indexes below
+ * nargs) the corresponding bit in the bitmap is unset when the name
+ * is null. Such null names are not encoded or decoded. For variable
+ * names (indexes starting from nargs) bitmap's bit is set when the
+ * name is declared as const, not as ordinary var.
+ * */
+ bitmapLength = JS_HOWMANY(n, JS_BITS_PER_UINT32);
+ JS_ARENA_ALLOCATE_CAST(bitmap, uint32 *, &xdr->cx->tempPool,
+ bitmapLength * sizeof *bitmap);
+ if (!bitmap) {
+ js_ReportOutOfScriptQuota(xdr->cx);
+ ok = JS_FALSE;
+ goto release_mark;
+ }
+ if (xdr->mode == JSXDR_ENCODE) {
+ names = js_GetLocalNameArray(xdr->cx, fun, &xdr->cx->tempPool);
+ if (!names) {
+ ok = JS_FALSE;
+ goto release_mark;
+ }
+ memset(bitmap, 0, bitmapLength * sizeof *bitmap);
+ for (i = 0; i != n; ++i) {
+ if (i < fun->nargs
+ ? JS_LOCAL_NAME_TO_ATOM(names[i]) != NULL
+ : JS_LOCAL_NAME_IS_CONST(names[i])) {
+ bitmap[i >> JS_BITS_PER_UINT32_LOG2] |=
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1));
+ }
+ }
+ }
+#ifdef __GNUC__
+ else {
+ names = NULL; /* quell GCC uninitialized warning */
+ }
+#endif
+ for (i = 0; i != bitmapLength; ++i) {
+ ok = JS_XDRUint32(xdr, &bitmap[i]);
+ if (!ok)
+ goto release_mark;
+ }
+ for (i = 0; i != n; ++i) {
+ if (i < nargs &&
+ !(bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1)))) {
+ if (xdr->mode == JSXDR_DECODE) {
+ ok = js_AddLocal(xdr->cx, fun, NULL, JSLOCAL_ARG);
+ if (!ok)
+ goto release_mark;
+ } else {
+ JS_ASSERT(!JS_LOCAL_NAME_TO_ATOM(names[i]));
+ }
+ continue;
+ }
+ if (xdr->mode == JSXDR_ENCODE)
+ name = JS_LOCAL_NAME_TO_ATOM(names[i]);
+ ok = js_XDRStringAtom(xdr, &name);
+ if (!ok)
+ goto release_mark;
+ if (xdr->mode == JSXDR_DECODE) {
+ localKind = (i < nargs)
+ ? JSLOCAL_ARG
+ : bitmap[i >> JS_BITS_PER_UINT32_LOG2] &
+ JS_BIT(i & (JS_BITS_PER_UINT32 - 1))
+ ? JSLOCAL_CONST
+ : JSLOCAL_VAR;
+ ok = js_AddLocal(xdr->cx, fun, name, localKind);
+ if (!ok)
+ goto release_mark;
+ }
+ }
+ ok = JS_TRUE;
+
+ release_mark:
+ JS_ARENA_RELEASE(&xdr->cx->tempPool, mark);
+ if (!ok)
+ goto out;
+
+ if (xdr->mode == JSXDR_DECODE)
+ js_FreezeLocalNames(cx, fun);
+ }
+
+ if (!js_XDRScript(xdr, &fun->u.i.script, NULL))
+ goto bad;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ *objp = FUN_OBJECT(fun);
+#ifdef CHECK_SCRIPT_OWNER
+ fun->u.i.script->owner = NULL;
+#endif
+ js_CallNewScriptHook(cx, fun->u.i.script, fun);
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+
+bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+#else /* !JS_HAS_XDR */
+
+#define fun_xdrObject NULL
+
+#endif /* !JS_HAS_XDR */
+
+/*
+ * [[HasInstance]] internal method for Function objects: fetch the .prototype
+ * property of its 'this' parameter, and walks the prototype chain of v (only
+ * if v is an object) returning true if .prototype is found.
+ */
+static JSBool
+fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ jsval pval;
+
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &pval)) {
+ return JS_FALSE;
+ }
+
+ if (JSVAL_IS_PRIMITIVE(pval)) {
+ /*
+ * Throw a runtime error if instanceof is called on a function that
+ * has a non-object as its .prototype value.
+ */
+ js_ReportValueError(cx, JSMSG_BAD_PROTOTYPE,
+ -1, OBJECT_TO_JSVAL(obj), NULL);
+ return JS_FALSE;
+ }
+
+ return js_IsDelegate(cx, JSVAL_TO_OBJECT(pval), v, bp);
+}
+
+static void
+TraceLocalNames(JSTracer *trc, JSFunction *fun);
+
+static void
+DestroyLocalNames(JSContext *cx, JSFunction *fun);
+
+static void
+fun_trace(JSTracer *trc, JSObject *obj)
+{
+ JSFunction *fun;
+
+ /* A newborn function object may have a not yet initialized private slot. */
+ fun = (JSFunction *) JS_GetPrivate(trc->context, obj);
+ if (!fun)
+ return;
+
+ if (FUN_OBJECT(fun) != obj) {
+ /* obj is cloned function object, trace the original. */
+ JS_CALL_TRACER(trc, FUN_OBJECT(fun), JSTRACE_OBJECT, "private");
+ return;
+ }
+ if (fun->atom)
+ JS_CALL_STRING_TRACER(trc, ATOM_TO_STRING(fun->atom), "atom");
+ if (FUN_INTERPRETED(fun)) {
+ if (fun->u.i.script)
+ js_TraceScript(trc, fun->u.i.script);
+ TraceLocalNames(trc, fun);
+ }
+}
+
+static void
+fun_finalize(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+
+ /* Ignore newborn and cloned function objects. */
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
+ if (!fun || FUN_OBJECT(fun) != obj)
+ return;
+
+ /*
+ * Null-check of u.i.script is required since the parser sets interpreted
+ * very early.
+ */
+ if (FUN_INTERPRETED(fun)) {
+ if (fun->u.i.script)
+ js_DestroyScript(cx, fun->u.i.script);
+ DestroyLocalNames(cx, fun);
+ }
+}
+
+static uint32
+fun_reserveSlots(JSContext *cx, JSObject *obj)
+{
+ JSFunction *fun;
+ uint32 nslots;
+
+ /*
+ * We use JS_GetPrivate and not GET_FUNCTION_PRIVATE because during
+ * js_InitFunctionClass invocation the function is called before the
+ * private slot of the function object is set.
+ */
+ fun = (JSFunction *) JS_GetPrivate(cx, obj);
+ nslots = 0;
+ if (fun && FUN_INTERPRETED(fun) && fun->u.i.script) {
+ if (fun->u.i.script->upvarsOffset != 0)
+ nslots = JS_SCRIPT_UPVARS(fun->u.i.script)->length;
+ if (fun->u.i.script->regexpsOffset != 0)
+ nslots += JS_SCRIPT_REGEXPS(fun->u.i.script)->length;
+ }
+ return nslots;
+}
+
+/*
+ * Reserve two slots in all function objects for XPConnect. Note that this
+ * does not bloat every instance, only those on which reserved slots are set,
+ * and those on which ad-hoc properties are defined.
+ */
+JS_FRIEND_DATA(JSClass) js_FunctionClass = {
+ js_Function_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ fun_enumerate, (JSResolveOp)fun_resolve,
+ fun_convert, fun_finalize,
+ NULL, NULL,
+ NULL, NULL,
+ fun_xdrObject, fun_hasInstance,
+ JS_CLASS_TRACE(fun_trace), fun_reserveSlots
+};
+
+static JSBool
+fun_toStringHelper(JSContext *cx, uint32 indent, uintN argc, jsval *vp)
+{
+ jsval fval;
+ JSObject *obj;
+ JSFunction *fun;
+ JSString *str;
+
+ fval = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(fval))
+ return JS_FALSE;
+
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ /*
+ * If we don't have a function to start off with, try converting the
+ * object to a function. If that doesn't work, complain.
+ */
+ if (!JSVAL_IS_PRIMITIVE(fval)) {
+ obj = JSVAL_TO_OBJECT(fval);
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION,
+ &fval)) {
+ return JS_FALSE;
+ }
+ vp[1] = fval;
+ }
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ js_Function_str, js_toString_str,
+ JS_GetTypeName(cx, JS_TypeOfValue(cx, fval)));
+ return JS_FALSE;
+ }
+ }
+
+ obj = JSVAL_TO_OBJECT(fval);
+ if (argc != 0) {
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(JS_ObjectIsFunction(cx, obj));
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+ if (!fun)
+ return JS_TRUE;
+ str = JS_DecompileFunction(cx, fun, (uintN)indent);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+fun_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return fun_toStringHelper(cx, 0, argc, vp);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+fun_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ return fun_toStringHelper(cx, JS_DONT_PRETTY_PRINT, argc, vp);
+}
+#endif
+
+JSBool
+js_fun_call(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval fval, *argv, *invokevp;
+ JSString *str;
+ void *mark;
+ JSBool ok;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
+ return JS_FALSE;
+ fval = vp[1];
+
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ str = JS_ValueToString(cx, fval);
+ if (str) {
+ const char *bytes = js_GetStringBytes(cx, str);
+
+ if (bytes) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ js_Function_str, js_call_str,
+ bytes);
+ }
+ }
+ return JS_FALSE;
+ }
+
+ argv = vp + 2;
+ if (argc == 0) {
+ /* Call fun with its global object as the 'this' param if no args. */
+ obj = NULL;
+ } else {
+ /* Otherwise convert the first arg to 'this' and skip over it. */
+ if (!JSVAL_IS_PRIMITIVE(argv[0]))
+ obj = JSVAL_TO_OBJECT(argv[0]);
+ else if (!js_ValueToObject(cx, argv[0], &obj))
+ return JS_FALSE;
+ argc--;
+ argv++;
+ }
+
+ /* Allocate stack space for fval, obj, and the args. */
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ /* Push fval, obj, and the args. */
+ invokevp[0] = fval;
+ invokevp[1] = OBJECT_TO_JSVAL(obj);
+ memcpy(invokevp + 2, argv, argc * sizeof *argv);
+
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ *vp = *invokevp;
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+JSBool
+js_fun_apply(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj, *aobj;
+ jsval fval, *invokevp, *sp;
+ JSString *str;
+ jsuint length;
+ JSBool arraylike, ok;
+ void *mark;
+ uintN i;
+
+ if (argc == 0) {
+ /* Will get globalObject as 'this' and no other arguments. */
+ return js_fun_call(cx, argc, vp);
+ }
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &vp[1]))
+ return JS_FALSE;
+ fval = vp[1];
+
+ if (!VALUE_IS_FUNCTION(cx, fval)) {
+ str = JS_ValueToString(cx, fval);
+ if (str) {
+ const char *bytes = js_GetStringBytes(cx, str);
+
+ if (bytes) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_PROTO,
+ js_Function_str, js_apply_str,
+ bytes);
+ }
+ }
+ return JS_FALSE;
+ }
+
+ /* Quell GCC overwarnings. */
+ aobj = NULL;
+ length = 0;
+
+ if (argc >= 2) {
+ /* If the 2nd arg is null or void, call the function with 0 args. */
+ if (JSVAL_IS_NULL(vp[3]) || JSVAL_IS_VOID(vp[3])) {
+ argc = 0;
+ } else {
+ /* The second arg must be an array (or arguments object). */
+ arraylike = JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(vp[3])) {
+ aobj = JSVAL_TO_OBJECT(vp[3]);
+ if (!js_IsArrayLike(cx, aobj, &arraylike, &length))
+ return JS_FALSE;
+ }
+ if (!arraylike) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_APPLY_ARGS, js_apply_str);
+ return JS_FALSE;
+ }
+ }
+ }
+
+ /* Convert the first arg to 'this' and skip over it. */
+ if (!JSVAL_IS_PRIMITIVE(vp[2]))
+ obj = JSVAL_TO_OBJECT(vp[2]);
+ else if (!js_ValueToObject(cx, vp[2], &obj))
+ return JS_FALSE;
+
+ /* Allocate stack space for fval, obj, and the args. */
+ argc = (uintN)JS_MIN(length, ARRAY_INIT_LIMIT - 1);
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ /* Push fval, obj, and aobj's elements as args. */
+ sp = invokevp;
+ *sp++ = fval;
+ *sp++ = OBJECT_TO_JSVAL(obj);
+ for (i = 0; i < argc; i++) {
+ ok = JS_GetElement(cx, aobj, (jsint)i, sp);
+ if (!ok)
+ goto out;
+ sp++;
+ }
+
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ *vp = *invokevp;
+out:
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+#ifdef NARCISSUS
+static JSBool
+fun_applyConstructor(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *aobj;
+ uintN length, i;
+ void *mark;
+ jsval *invokevp, *sp;
+ JSBool ok;
+
+ if (JSVAL_IS_PRIMITIVE(vp[2]) ||
+ (aobj = JSVAL_TO_OBJECT(vp[2]),
+ OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass &&
+ OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_APPLY_ARGS, "__applyConstruct__");
+ return JS_FALSE;
+ }
+
+ if (!js_GetLengthProperty(cx, aobj, &length))
+ return JS_FALSE;
+
+ if (length >= ARRAY_INIT_LIMIT)
+ length = ARRAY_INIT_LIMIT - 1;
+ invokevp = js_AllocStack(cx, 2 + length, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ sp = invokevp;
+ *sp++ = vp[1];
+ *sp++ = JSVAL_NULL; /* this is filled automagically */
+ for (i = 0; i < length; i++) {
+ ok = JS_GetElement(cx, aobj, (jsint)i, sp);
+ if (!ok)
+ goto out;
+ sp++;
+ }
+
+ ok = js_InvokeConstructor(cx, length, JS_TRUE, invokevp);
+ *vp = *invokevp;
+out:
+ js_FreeStack(cx, mark);
+ return ok;
+}
+#endif
+
+static JSFunctionSpec function_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, fun_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, fun_toString, 0,0),
+ JS_FN(js_apply_str, js_fun_apply, 2,0),
+ JS_FN(js_call_str, js_fun_call, 1,0),
+#ifdef NARCISSUS
+ JS_FN("__applyConstructor__", fun_applyConstructor, 1,0),
+#endif
+ JS_FS_END
+};
+
+static JSBool
+Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSStackFrame *fp, *caller;
+ JSFunction *fun;
+ JSObject *parent;
+ uintN i, n, lineno;
+ JSAtom *atom;
+ const char *filename;
+ JSBool ok;
+ JSString *str, *arg;
+ JSTokenStream ts;
+ JSPrincipals *principals;
+ jschar *collected_args, *cp;
+ void *mark;
+ size_t arg_length, args_length, old_args_length;
+ JSTokenType tt;
+
+ fp = cx->fp;
+ if (!(fp->flags & JSFRAME_CONSTRUCTING)) {
+ obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ } else {
+ /*
+ * The constructor is called before the private slot is initialized so
+ * we must use JS_GetPrivate, not GET_FUNCTION_PRIVATE here.
+ */
+ if (JS_GetPrivate(cx, obj))
+ return JS_TRUE;
+ }
+
+ /*
+ * NB: (new Function) is not lexically closed by its caller, it's just an
+ * anonymous function in the top-level scope that its constructor inhabits.
+ * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
+ * and so would a call to f from another top-level's script or function.
+ *
+ * In older versions, before call objects, a new Function was adopted by
+ * its running context's globalObject, which might be different from the
+ * top-level reachable from scopeChain (in HTML frames, e.g.).
+ */
+ parent = OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]));
+
+ fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
+ parent, cx->runtime->atomState.anonymousAtom);
+
+ if (!fun)
+ return JS_FALSE;
+
+ /*
+ * Function is static and not called directly by other functions in this
+ * file, therefore it is callable only as a native function by js_Invoke.
+ * Find the scripted caller, possibly skipping other native frames such as
+ * are built for Function.prototype.call or .apply activations that invoke
+ * Function indirectly from a script.
+ */
+ JS_ASSERT(!fp->script && fp->fun && fp->fun->u.n.native == Function);
+ caller = JS_GetScriptedCaller(cx, fp);
+ if (caller) {
+ principals = JS_EvalFramePrincipals(cx, fp, caller);
+ filename = js_ComputeFilename(cx, caller, principals, &lineno);
+ } else {
+ filename = NULL;
+ lineno = 0;
+ principals = NULL;
+ }
+
+ /* Belt-and-braces: check that the caller has access to parent. */
+ if (!js_CheckPrincipalsAccess(cx, parent, principals,
+ CLASS_ATOM(cx, Function))) {
+ return JS_FALSE;
+ }
+
+ n = argc ? argc - 1 : 0;
+ if (n > 0) {
+ enum { OK, BAD, BAD_FORMAL } state;
+
+ /*
+ * Collect the function-argument arguments into one string, separated
+ * by commas, then make a tokenstream from that string, and scan it to
+ * get the arguments. We need to throw the full scanner at the
+ * problem, because the argument string can legitimately contain
+ * comments and linefeeds. XXX It might be better to concatenate
+ * everything up into a function definition and pass it to the
+ * compiler, but doing it this way is less of a delta from the old
+ * code. See ECMA 15.3.2.1.
+ */
+ state = BAD_FORMAL;
+ args_length = 0;
+ for (i = 0; i < n; i++) {
+ /* Collect the lengths for all the function-argument arguments. */
+ arg = js_ValueToString(cx, argv[i]);
+ if (!arg)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(arg);
+
+ /*
+ * Check for overflow. The < test works because the maximum
+ * JSString length fits in 2 fewer bits than size_t has.
+ */
+ old_args_length = args_length;
+ args_length = old_args_length + JSSTRING_LENGTH(arg);
+ if (args_length < old_args_length) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+ }
+
+ /* Add 1 for each joining comma and check for overflow (two ways). */
+ old_args_length = args_length;
+ args_length = old_args_length + n - 1;
+ if (args_length < old_args_length ||
+ args_length >= ~(size_t)0 / sizeof(jschar)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ /*
+ * Allocate a string to hold the concatenated arguments, including room
+ * for a terminating 0. Mark cx->tempPool for later release, to free
+ * collected_args and its tokenstream in one swoop.
+ */
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool,
+ (args_length+1) * sizeof(jschar));
+ if (!cp) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ collected_args = cp;
+
+ /*
+ * Concatenate the arguments into the new string, separated by commas.
+ */
+ for (i = 0; i < n; i++) {
+ arg = JSVAL_TO_STRING(argv[i]);
+ arg_length = JSSTRING_LENGTH(arg);
+ (void) js_strncpy(cp, JSSTRING_CHARS(arg), arg_length);
+ cp += arg_length;
+
+ /* Add separating comma or terminating 0. */
+ *cp++ = (i + 1 < n) ? ',' : 0;
+ }
+
+ /* Initialize a tokenstream that reads from the given string. */
+ if (!js_InitTokenStream(cx, &ts, collected_args, args_length,
+ NULL, filename, lineno)) {
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return JS_FALSE;
+ }
+
+ /* The argument string may be empty or contain no tokens. */
+ tt = js_GetToken(cx, &ts);
+ if (tt != TOK_EOF) {
+ for (;;) {
+ /*
+ * Check that it's a name. This also implicitly guards against
+ * TOK_ERROR, which was already reported.
+ */
+ if (tt != TOK_NAME)
+ goto after_args;
+
+ /*
+ * Get the atom corresponding to the name from the token
+ * stream; we're assured at this point that it's a valid
+ * identifier.
+ */
+ atom = CURRENT_TOKEN(&ts).t_atom;
+
+ /* Check for a duplicate parameter name. */
+ if (js_LookupLocal(cx, fun, atom, NULL) != JSLOCAL_NONE) {
+ const char *name;
+
+ name = js_AtomToPrintableString(cx, atom);
+ ok = name &&
+ js_ReportCompileErrorNumber(cx, &ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_DUPLICATE_FORMAL,
+ name);
+ if (!ok)
+ goto after_args;
+ }
+ if (!js_AddLocal(cx, fun, atom, JSLOCAL_ARG))
+ goto after_args;
+
+ /*
+ * Get the next token. Stop on end of stream. Otherwise
+ * insist on a comma, get another name, and iterate.
+ */
+ tt = js_GetToken(cx, &ts);
+ if (tt == TOK_EOF)
+ break;
+ if (tt != TOK_COMMA)
+ goto after_args;
+ tt = js_GetToken(cx, &ts);
+ }
+ }
+
+ state = OK;
+ after_args:
+ if (state == BAD_FORMAL && !(ts.flags & TSF_ERROR)) {
+ /*
+ * Report "malformed formal parameter" iff no illegal char or
+ * similar scanner error was already reported.
+ */
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_FORMAL);
+ }
+ js_CloseTokenStream(cx, &ts);
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ if (state != OK)
+ return JS_FALSE;
+ }
+
+ if (argc) {
+ str = js_ValueToString(cx, argv[argc-1]);
+ if (!str)
+ return JS_FALSE;
+ argv[argc-1] = STRING_TO_JSVAL(str);
+ } else {
+ str = cx->runtime->emptyString;
+ }
+
+ return js_CompileFunctionBody(cx, fun, principals,
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
+ filename, lineno);
+}
+
+JSObject *
+js_InitFunctionClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+ JSFunction *fun;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,
+ function_props, function_methods, NULL, NULL);
+ if (!proto)
+ return NULL;
+ fun = js_NewFunction(cx, proto, NULL, 0, JSFUN_INTERPRETED, obj, NULL);
+ if (!fun)
+ goto bad;
+ fun->u.i.script = js_NewScript(cx, 1, 1, 0, 0, 0, 0, 0);
+ if (!fun->u.i.script)
+ goto bad;
+ fun->u.i.script->code[0] = JSOP_STOP;
+ *SCRIPT_NOTES(fun->u.i.script) = SRC_NULL;
+#ifdef CHECK_SCRIPT_OWNER
+ fun->u.i.script->owner = NULL;
+#endif
+ return proto;
+
+bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+}
+
+JSObject *
+js_InitCallClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_CallClass, NULL, 0,
+ NULL, NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ /*
+ * Null Call.prototype's proto slot so that Object.prototype.* does not
+ * pollute the scope of heavyweight functions.
+ */
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+JSFunction *
+js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
+ uintN flags, JSObject *parent, JSAtom *atom)
+{
+ JSFunction *fun;
+
+ if (funobj) {
+ JS_ASSERT(HAS_FUNCTION_CLASS(funobj));
+ OBJ_SET_PARENT(cx, funobj, parent);
+ } else {
+ funobj = js_NewObject(cx, &js_FunctionClass, NULL, parent, 0);
+ if (!funobj)
+ return NULL;
+ }
+ JS_ASSERT(JSVAL_IS_VOID(funobj->fslots[JSSLOT_PRIVATE]));
+ fun = (JSFunction *) funobj;
+
+ /* Initialize all function members. */
+ fun->nargs = nargs;
+ fun->flags = flags & (JSFUN_FLAGS_MASK | JSFUN_INTERPRETED | JSFUN_TRACEABLE);
+ if (flags & JSFUN_INTERPRETED) {
+ JS_ASSERT(!native);
+ JS_ASSERT(nargs == 0);
+ fun->u.i.nvars = 0;
+ fun->u.i.nupvars = 0;
+ fun->u.i.script = NULL;
+#ifdef DEBUG
+ fun->u.i.names.taggedAtom = 0;
+#endif
+ } else {
+ fun->u.n.extra = 0;
+ fun->u.n.spare = 0;
+ if (flags & JSFUN_TRACEABLE) {
+#ifdef JS_TRACER
+ JSTraceableNative *trcinfo = (JSTraceableNative *) native;
+ fun->u.n.native = (JSNative) trcinfo->native;
+ FUN_TRCINFO(fun) = trcinfo;
+#else
+ JS_ASSERT(0);
+#endif
+ } else {
+ fun->u.n.native = native;
+ FUN_CLASP(fun) = NULL;
+ }
+ }
+ fun->atom = atom;
+
+ /* Set private to self to indicate non-cloned fully initialized function. */
+ FUN_OBJECT(fun)->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
+ return fun;
+}
+
+JSObject *
+js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent)
+{
+ JSObject *clone;
+
+ /*
+ * The cloned function object does not need the extra fields beyond
+ * JSObject as it points to fun via the private slot.
+ */
+ clone = js_NewObject(cx, &js_FunctionClass, NULL, parent,
+ sizeof(JSObject));
+ if (!clone)
+ return NULL;
+ clone->fslots[JSSLOT_PRIVATE] = PRIVATE_TO_JSVAL(fun);
+ return clone;
+}
+
+JSFunction *
+js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
+ uintN nargs, uintN attrs)
+{
+ JSFunction *fun;
+ JSPropertyOp gsop;
+
+ fun = js_NewFunction(cx, NULL, native, nargs, attrs, obj, atom);
+ if (!fun)
+ return NULL;
+ gsop = (attrs & JSFUN_STUB_GSOPS) ? JS_PropertyStub : NULL;
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom),
+ OBJECT_TO_JSVAL(FUN_OBJECT(fun)),
+ gsop, gsop,
+ attrs & ~JSFUN_FLAGS_MASK, NULL)) {
+ return NULL;
+ }
+ return fun;
+}
+
+#if (JSV2F_CONSTRUCT & JSV2F_SEARCH_STACK)
+# error "JSINVOKE_CONSTRUCT and JSV2F_SEARCH_STACK are not disjoint!"
+#endif
+
+JSFunction *
+js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags)
+{
+ jsval v;
+ JSObject *obj;
+
+ v = *vp;
+ obj = NULL;
+ if (JSVAL_IS_OBJECT(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (obj && OBJ_GET_CLASS(cx, obj) != &js_FunctionClass) {
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &v))
+ return NULL;
+ obj = VALUE_IS_FUNCTION(cx, v) ? JSVAL_TO_OBJECT(v) : NULL;
+ }
+ }
+ if (!obj) {
+ js_ReportIsNotFunction(cx, vp, flags);
+ return NULL;
+ }
+ return GET_FUNCTION_PRIVATE(cx, obj);
+}
+
+JSObject *
+js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
+{
+ JSFunction *fun;
+ JSStackFrame *caller;
+ JSPrincipals *principals;
+
+ if (VALUE_IS_FUNCTION(cx, *vp))
+ return JSVAL_TO_OBJECT(*vp);
+
+ fun = js_ValueToFunction(cx, vp, flags);
+ if (!fun)
+ return NULL;
+ *vp = OBJECT_TO_JSVAL(FUN_OBJECT(fun));
+
+ caller = JS_GetScriptedCaller(cx, cx->fp);
+ if (caller) {
+ principals = JS_StackFramePrincipals(cx, caller);
+ } else {
+ /* No scripted caller, don't allow access. */
+ principals = NULL;
+ }
+
+ if (!js_CheckPrincipalsAccess(cx, FUN_OBJECT(fun), principals,
+ fun->atom
+ ? fun->atom
+ : cx->runtime->atomState.anonymousAtom)) {
+ return NULL;
+ }
+ return FUN_OBJECT(fun);
+}
+
+JSObject *
+js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags)
+{
+ JSObject *callable;
+
+ callable = JSVAL_IS_PRIMITIVE(*vp) ? NULL : JSVAL_TO_OBJECT(*vp);
+ if (callable &&
+ ((callable->map->ops == &js_ObjectOps)
+ ? OBJ_GET_CLASS(cx, callable)->call
+ : callable->map->ops->call)) {
+ *vp = OBJECT_TO_JSVAL(callable);
+ } else {
+ callable = js_ValueToFunctionObject(cx, vp, flags);
+ }
+ return callable;
+}
+
+void
+js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
+{
+ JSStackFrame *fp;
+ uintN error;
+ const char *name, *source;
+ JSTempValueRooter tvr;
+
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+ continue;
+ name = source = NULL;
+ JS_PUSH_TEMP_ROOT_STRING(cx, NULL, &tvr);
+ if (flags & JSV2F_ITERATOR) {
+ error = JSMSG_BAD_ITERATOR;
+ name = js_iterator_str;
+ tvr.u.string = js_ValueToSource(cx, *vp);
+ if (!tvr.u.string)
+ goto out;
+ tvr.u.string = js_QuoteString(cx, tvr.u.string, 0);
+ if (!tvr.u.string)
+ goto out;
+ source = js_GetStringBytes(cx, tvr.u.string);
+ if (!source)
+ goto out;
+ } else if (flags & JSV2F_CONSTRUCT) {
+ error = JSMSG_NOT_CONSTRUCTOR;
+ } else {
+ error = JSMSG_NOT_FUNCTION;
+ }
+
+ js_ReportValueError3(cx, error,
+ (fp && fp->regs &&
+ StackBase(fp) <= vp && vp < fp->regs->sp)
+ ? vp - fp->regs->sp
+ : (flags & JSV2F_SEARCH_STACK)
+ ? JSDVG_SEARCH_STACK
+ : JSDVG_IGNORE_STACK,
+ *vp, NULL,
+ name, source);
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+}
+
+/*
+ * When a function has between 2 and MAX_ARRAY_LOCALS arguments and variables,
+ * their name are stored as the JSLocalNames.array.
+ */
+#define MAX_ARRAY_LOCALS 8
+
+JS_STATIC_ASSERT(2 <= MAX_ARRAY_LOCALS);
+JS_STATIC_ASSERT(MAX_ARRAY_LOCALS < JS_BITMASK(16));
+
+/*
+ * We use the lowest bit of the string atom to distinguish const from var
+ * name when there is only single name or when names are stored as an array.
+ */
+JS_STATIC_ASSERT((JSVAL_STRING & 1) == 0);
+
+/*
+ * When we use a hash table to store the local names, we use a singly linked
+ * list to record the indexes of duplicated parameter names to preserve the
+ * duplicates for the decompiler.
+ */
+typedef struct JSNameIndexPair JSNameIndexPair;
+
+struct JSNameIndexPair {
+ JSAtom *name;
+ uint16 index;
+ JSNameIndexPair *link;
+};
+
+struct JSLocalNameMap {
+ JSDHashTable names;
+ JSNameIndexPair *lastdup;
+};
+
+typedef struct JSLocalNameHashEntry {
+ JSDHashEntryHdr hdr;
+ JSAtom *name;
+ uint16 index;
+ uint8 localKind;
+} JSLocalNameHashEntry;
+
+static void
+FreeLocalNameHash(JSContext *cx, JSLocalNameMap *map)
+{
+ JSNameIndexPair *dup, *next;
+
+ for (dup = map->lastdup; dup; dup = next) {
+ next = dup->link;
+ JS_free(cx, dup);
+ }
+ JS_DHashTableFinish(&map->names);
+ JS_free(cx, map);
+}
+
+static JSBool
+HashLocalName(JSContext *cx, JSLocalNameMap *map, JSAtom *name,
+ JSLocalKind localKind, uintN index)
+{
+ JSLocalNameHashEntry *entry;
+ JSNameIndexPair *dup;
+
+ JS_ASSERT(index <= JS_BITMASK(16));
+#if JS_HAS_DESTRUCTURING
+ if (!name) {
+ /* A destructuring pattern does not need a hash entry. */
+ JS_ASSERT(localKind == JSLOCAL_ARG);
+ return JS_TRUE;
+ }
+#endif
+ JS_ASSERT(ATOM_IS_STRING(name));
+ entry = (JSLocalNameHashEntry *)
+ JS_DHashTableOperate(&map->names, name, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ if (entry->name) {
+ JS_ASSERT(entry->name == name);
+ JS_ASSERT(entry->localKind == JSLOCAL_ARG);
+ dup = (JSNameIndexPair *) JS_malloc(cx, sizeof *dup);
+ if (!dup)
+ return JS_FALSE;
+ dup->name = entry->name;
+ dup->index = entry->index;
+ dup->link = map->lastdup;
+ map->lastdup = dup;
+ }
+ entry->name = name;
+ entry->index = (uint16) index;
+ entry->localKind = (uint8) localKind;
+ return JS_TRUE;
+}
+
+JSBool
+js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind)
+{
+ jsuword taggedAtom;
+ uint16 *indexp;
+ uintN n, i;
+ jsuword *array;
+ JSLocalNameMap *map;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ JS_ASSERT(!fun->u.i.script);
+ JS_ASSERT(((jsuword) atom & 1) == 0);
+ taggedAtom = (jsuword) atom;
+ if (kind == JSLOCAL_ARG) {
+ indexp = &fun->nargs;
+ } else if (kind == JSLOCAL_UPVAR) {
+ indexp = &fun->u.i.nupvars;
+ } else {
+ indexp = &fun->u.i.nvars;
+ if (kind == JSLOCAL_CONST)
+ taggedAtom |= 1;
+ else
+ JS_ASSERT(kind == JSLOCAL_VAR);
+ }
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0) {
+ JS_ASSERT(fun->u.i.names.taggedAtom == 0);
+ fun->u.i.names.taggedAtom = taggedAtom;
+ } else if (n < MAX_ARRAY_LOCALS) {
+ if (n > 1) {
+ array = fun->u.i.names.array;
+ } else {
+ array = (jsuword *) JS_malloc(cx, MAX_ARRAY_LOCALS * sizeof *array);
+ if (!array)
+ return JS_FALSE;
+ array[0] = fun->u.i.names.taggedAtom;
+ fun->u.i.names.array = array;
+ }
+ if (kind == JSLOCAL_ARG) {
+ /*
+ * A destructuring argument pattern adds variables, not arguments,
+ * so for the following arguments nvars != 0.
+ */
+#if JS_HAS_DESTRUCTURING
+ if (fun->u.i.nvars != 0) {
+ memmove(array + fun->nargs + 1, array + fun->nargs,
+ fun->u.i.nvars * sizeof *array);
+ }
+#else
+ JS_ASSERT(fun->u.i.nvars == 0);
+#endif
+ array[fun->nargs] = taggedAtom;
+ } else {
+ array[n] = taggedAtom;
+ }
+ } else if (n == MAX_ARRAY_LOCALS) {
+ array = fun->u.i.names.array;
+ map = (JSLocalNameMap *) JS_malloc(cx, sizeof *map);
+ if (!map)
+ return JS_FALSE;
+ if (!JS_DHashTableInit(&map->names, JS_DHashGetStubOps(),
+ NULL, sizeof(JSLocalNameHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(MAX_ARRAY_LOCALS
+ * 2))) {
+ JS_ReportOutOfMemory(cx);
+ JS_free(cx, map);
+ return JS_FALSE;
+ }
+
+ map->lastdup = NULL;
+ for (i = 0; i != MAX_ARRAY_LOCALS; ++i) {
+ taggedAtom = array[i];
+ if (!HashLocalName(cx, map, (JSAtom *) (taggedAtom & ~1),
+ (i < fun->nargs)
+ ? JSLOCAL_ARG
+ : (taggedAtom & 1) ? JSLOCAL_CONST : JSLOCAL_VAR,
+ (i < fun->nargs) ? i : i - fun->nargs)) {
+ FreeLocalNameHash(cx, map);
+ return JS_FALSE;
+ }
+ }
+ if (!HashLocalName(cx, map, atom, kind, *indexp)) {
+ FreeLocalNameHash(cx, map);
+ return JS_FALSE;
+ }
+
+ /*
+ * At this point the entry is added and we cannot fail. It is time
+ * to replace fun->u.i.names with the built map.
+ */
+ fun->u.i.names.map = map;
+ JS_free(cx, array);
+ } else {
+ if (*indexp == JS_BITMASK(16)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ (kind == JSLOCAL_ARG)
+ ? JSMSG_TOO_MANY_FUN_ARGS
+ : JSMSG_TOO_MANY_LOCALS);
+ return JS_FALSE;
+ }
+ if (!HashLocalName(cx, fun->u.i.names.map, atom, kind, *indexp))
+ return JS_FALSE;
+ }
+
+ /* Update the argument or variable counter. */
+ ++*indexp;
+ return JS_TRUE;
+}
+
+JSLocalKind
+js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp)
+{
+ uintN n, i, upvar_base;
+ jsuword *array;
+ JSLocalNameHashEntry *entry;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0)
+ return JSLOCAL_NONE;
+ if (n <= MAX_ARRAY_LOCALS) {
+ array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
+
+ /* Search from the tail to pick up the last duplicated name. */
+ i = n;
+ upvar_base = JS_UPVAR_LOCAL_NAME_START(fun);
+ do {
+ --i;
+ if (atom == JS_LOCAL_NAME_TO_ATOM(array[i])) {
+ if (i < fun->nargs) {
+ if (indexp)
+ *indexp = i;
+ return JSLOCAL_ARG;
+ }
+ if (i >= upvar_base) {
+ if (indexp)
+ *indexp = i - upvar_base;
+ return JSLOCAL_UPVAR;
+ }
+ if (indexp)
+ *indexp = i - fun->nargs;
+ return JS_LOCAL_NAME_IS_CONST(array[i])
+ ? JSLOCAL_CONST
+ : JSLOCAL_VAR;
+ }
+ } while (i != 0);
+ } else {
+ entry = (JSLocalNameHashEntry *)
+ JS_DHashTableOperate(&fun->u.i.names.map->names, atom,
+ JS_DHASH_LOOKUP);
+ if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr)) {
+ JS_ASSERT(entry->localKind != JSLOCAL_NONE);
+ if (indexp)
+ *indexp = entry->index;
+ return (JSLocalKind) entry->localKind;
+ }
+ }
+ return JSLOCAL_NONE;
+}
+
+typedef struct JSLocalNameEnumeratorArgs {
+ JSFunction *fun;
+ jsuword *names;
+#ifdef DEBUG
+ uintN nCopiedArgs;
+ uintN nCopiedVars;
+#endif
+} JSLocalNameEnumeratorArgs;
+
+static JSDHashOperator
+get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSLocalNameHashEntry *entry;
+ JSLocalNameEnumeratorArgs *args;
+ uint i;
+ jsuword constFlag;
+
+ entry = (JSLocalNameHashEntry *) hdr;
+ args = (JSLocalNameEnumeratorArgs *) arg;
+ JS_ASSERT(entry->name);
+ if (entry->localKind == JSLOCAL_ARG) {
+ JS_ASSERT(entry->index < args->fun->nargs);
+ JS_ASSERT(args->nCopiedArgs++ < args->fun->nargs);
+ i = entry->index;
+ constFlag = 0;
+ } else {
+ JS_ASSERT(entry->localKind == JSLOCAL_VAR ||
+ entry->localKind == JSLOCAL_CONST);
+ JS_ASSERT(entry->index < args->fun->u.i.nvars);
+ JS_ASSERT(args->nCopiedVars++ < args->fun->u.i.nvars);
+ i = args->fun->nargs + entry->index;
+ constFlag = (entry->localKind == JSLOCAL_CONST);
+ }
+ args->names[i] = (jsuword) entry->name | constFlag;
+ return JS_DHASH_NEXT;
+}
+
+jsuword *
+js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
+{
+ uintN n;
+ jsuword *names;
+ JSLocalNameMap *map;
+ JSLocalNameEnumeratorArgs args;
+ JSNameIndexPair *dup;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ JS_ASSERT(n != 0);
+
+ if (n <= MAX_ARRAY_LOCALS)
+ return (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
+
+ /*
+ * No need to check for overflow of the allocation size as we are making a
+ * copy of already allocated data. As such it must fit size_t.
+ */
+ JS_ARENA_ALLOCATE_CAST(names, jsuword *, pool, (size_t) n * sizeof *names);
+ if (!names) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+
+#if JS_HAS_DESTRUCTURING
+ /* Some parameter names can be NULL due to destructuring patterns. */
+ memset(names, 0, fun->nargs * sizeof *names);
+#endif
+ map = fun->u.i.names.map;
+ args.fun = fun;
+ args.names = names;
+#ifdef DEBUG
+ args.nCopiedArgs = 0;
+ args.nCopiedVars = 0;
+#endif
+ JS_DHashTableEnumerate(&map->names, get_local_names_enumerator, &args);
+ for (dup = map->lastdup; dup; dup = dup->link) {
+ JS_ASSERT(dup->index < fun->nargs);
+ JS_ASSERT(args.nCopiedArgs++ < fun->nargs);
+ names[dup->index] = (jsuword) dup->name;
+ }
+#if !JS_HAS_DESTRUCTURING
+ JS_ASSERT(args.nCopiedArgs == fun->nargs);
+#endif
+ JS_ASSERT(args.nCopiedVars == fun->u.i.nvars);
+
+ return names;
+}
+
+static JSDHashOperator
+trace_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
+ uint32 number, void *arg)
+{
+ JSLocalNameHashEntry *entry;
+ JSTracer *trc;
+
+ entry = (JSLocalNameHashEntry *) hdr;
+ JS_ASSERT(entry->name);
+ trc = (JSTracer *) arg;
+ JS_SET_TRACING_INDEX(trc,
+ entry->localKind == JSLOCAL_ARG ? "arg" : "var",
+ entry->index);
+ JS_CallTracer(trc, ATOM_TO_STRING(entry->name), JSTRACE_STRING);
+ return JS_DHASH_NEXT;
+}
+
+static void
+TraceLocalNames(JSTracer *trc, JSFunction *fun)
+{
+ uintN n, i;
+ JSAtom *atom;
+ jsuword *array;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ n = JS_GET_LOCAL_NAME_COUNT(fun);
+ if (n == 0)
+ return;
+ if (n <= MAX_ARRAY_LOCALS) {
+ array = (n == 1) ? &fun->u.i.names.taggedAtom : fun->u.i.names.array;
+ i = n;
+ do {
+ --i;
+ atom = (JSAtom *) (array[i] & ~1);
+ if (atom) {
+ JS_SET_TRACING_INDEX(trc,
+ i < fun->nargs ? "arg" : "var",
+ i < fun->nargs ? i : i - fun->nargs);
+ JS_CallTracer(trc, ATOM_TO_STRING(atom), JSTRACE_STRING);
+ }
+ } while (i != 0);
+ } else {
+ JS_DHashTableEnumerate(&fun->u.i.names.map->names,
+ trace_local_names_enumerator, trc);
+
+ /*
+ * No need to trace the list of duplicates in map->lastdup as the
+ * names there are traced when enumerating the hash table.
+ */
+ }
+}
+
+void
+DestroyLocalNames(JSContext *cx, JSFunction *fun)
+{
+ uintN n;
+
+ n = fun->nargs + fun->u.i.nvars;
+ if (n <= 1)
+ return;
+ if (n <= MAX_ARRAY_LOCALS)
+ JS_free(cx, fun->u.i.names.array);
+ else
+ FreeLocalNameHash(cx, fun->u.i.names.map);
+}
+
+void
+js_FreezeLocalNames(JSContext *cx, JSFunction *fun)
+{
+ uintN n;
+ jsuword *array;
+
+ JS_ASSERT(FUN_INTERPRETED(fun));
+ JS_ASSERT(!fun->u.i.script);
+ n = fun->nargs + fun->u.i.nvars + fun->u.i.nupvars;
+ if (2 <= n && n < MAX_ARRAY_LOCALS) {
+ /* Shrink over-allocated array ignoring realloc failures. */
+ array = (jsuword *) JS_realloc(cx, fun->u.i.names.array,
+ n * sizeof *array);
+ if (array)
+ fun->u.i.names.array = array;
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsfun.h b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.h
new file mode 100644
index 0000000..d13ccfd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsfun.h
@@ -0,0 +1,296 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsfun_h___
+#define jsfun_h___
+/*
+ * JS function definitions.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsobj.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef struct JSLocalNameMap JSLocalNameMap;
+
+/*
+ * Depending on the number of arguments and variables in the function their
+ * names and attributes are stored either as a single atom or as an array of
+ * tagged atoms (when there are few locals) or as a hash-based map (when there
+ * are many locals). In the first 2 cases the lowest bit of the atom is used
+ * as a tag to distinguish const from var. See jsfun.c for details.
+ */
+typedef union JSLocalNames {
+ jsuword taggedAtom;
+ jsuword *array;
+ JSLocalNameMap *map;
+} JSLocalNames;
+
+struct JSFunction {
+ JSObject object; /* GC'ed object header */
+ uint16 nargs; /* maximum number of specified arguments,
+ reflected as f.length/f.arity */
+ uint16 flags; /* flags, see JSFUN_* below and in jsapi.h */
+ union {
+ struct {
+ uint16 extra; /* number of arg slots for local GC roots */
+ uint16 spare; /* reserved for future use */
+ JSNative native; /* native method pointer or null */
+ union {
+ JSClass *clasp; /* class of objects constructed
+ by this function */
+ JSTraceableNative *trcinfo; /* tracer metadata; can be first
+ element of array */
+ } u;
+ } n;
+ struct {
+ uint16 nvars; /* number of local variables */
+ uint16 nupvars; /* number of upvars (computable from script
+ but here for faster access) */
+ JSScript *script; /* interpreted bytecode descriptor or null */
+ JSLocalNames names; /* argument and variable names */
+ } i;
+ } u;
+ JSAtom *atom; /* name for diagnostics and decompiling */
+};
+
+#define JSFUN_TRACEABLE 0x2000 /* can trace across calls to this native
+ function; use FUN_TRCINFO if set,
+ FUN_CLASP if unset */
+#define JSFUN_EXPR_CLOSURE 0x4000 /* expression closure: function(x)x*x */
+#define JSFUN_INTERPRETED 0x8000 /* use u.i if set, u.n if unset */
+
+#define JSFUN_SCRIPT_OR_FAST_NATIVE (JSFUN_INTERPRETED | JSFUN_FAST_NATIVE)
+
+#define FUN_OBJECT(fun) (&(fun)->object)
+#define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED)
+#define FUN_SLOW_NATIVE(fun) (!((fun)->flags & JSFUN_SCRIPT_OR_FAST_NATIVE))
+#define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL)
+#define FUN_NATIVE(fun) (FUN_SLOW_NATIVE(fun) ? (fun)->u.n.native : NULL)
+#define FUN_FAST_NATIVE(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
+ ? (JSFastNative) (fun)->u.n.native \
+ : NULL)
+#define FUN_MINARGS(fun) (((fun)->flags & JSFUN_FAST_NATIVE) \
+ ? 0 \
+ : (fun)->nargs)
+#define FUN_CLASP(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
+ JS_ASSERT(!((fun)->flags & JSFUN_TRACEABLE)), \
+ fun->u.n.u.clasp)
+#define FUN_TRCINFO(fun) (JS_ASSERT(!FUN_INTERPRETED(fun)), \
+ JS_ASSERT((fun)->flags & JSFUN_TRACEABLE), \
+ fun->u.n.u.trcinfo)
+
+/*
+ * Traceable native. This expands to a JSFunctionSpec initializer (like JS_FN
+ * in jsapi.h). fastcall is a JSFastNative; trcinfo is a JSTraceableNative *.
+ */
+#ifdef JS_TRACER
+/* MSVC demands the intermediate (void *) cast here. */
+# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
+ {name, (JSNative)(void *)(trcinfo), nargs, \
+ (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS | JSFUN_TRACEABLE, 0}
+#else
+# define JS_TN(name,fastcall,nargs,flags,trcinfo) \
+ JS_FN(name, fastcall, nargs, flags)
+#endif
+
+extern JSClass js_ArgumentsClass;
+extern JS_FRIEND_DATA(JSClass) js_CallClass;
+
+/* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */
+extern JS_FRIEND_DATA(JSClass) js_FunctionClass;
+
+#define HAS_FUNCTION_CLASS(obj) (STOBJ_GET_CLASS(obj) == &js_FunctionClass)
+
+/*
+ * NB: jsapi.h and jsobj.h must be included before any call to this macro.
+ */
+#define VALUE_IS_FUNCTION(cx, v) \
+ (!JSVAL_IS_PRIMITIVE(v) && HAS_FUNCTION_CLASS(JSVAL_TO_OBJECT(v)))
+
+/*
+ * Macro to access the private slot of the function object after the slot is
+ * initialized.
+ */
+#define GET_FUNCTION_PRIVATE(cx, funobj) \
+ (JS_ASSERT(HAS_FUNCTION_CLASS(funobj)), \
+ (JSFunction *) OBJ_GET_PRIVATE(cx, funobj))
+
+extern JSObject *
+js_InitFunctionClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitArgumentsClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitCallClass(JSContext *cx, JSObject *obj);
+
+extern JSFunction *
+js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,
+ uintN flags, JSObject *parent, JSAtom *atom);
+
+extern void
+js_TraceFunction(JSTracer *trc, JSFunction *fun);
+
+extern void
+js_FinalizeFunction(JSContext *cx, JSFunction *fun);
+
+extern JSObject *
+js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent);
+
+extern JSBool
+js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object);
+
+extern JSFunction *
+js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native,
+ uintN nargs, uintN flags);
+
+/*
+ * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the
+ * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that
+ * with #if/#error in jsfun.c.
+ */
+#define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT
+#define JSV2F_ITERATOR JSINVOKE_ITERATOR
+#define JSV2F_SEARCH_STACK 0x10000
+
+extern JSFunction *
+js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags);
+
+extern JSObject *
+js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags);
+
+extern JSObject *
+js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags);
+
+extern void
+js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags);
+
+extern JSObject *
+js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent);
+
+extern JS_FRIEND_API(JSBool)
+js_PutCallObject(JSContext *cx, JSStackFrame *fp);
+
+extern JSBool
+js_GetCallArg(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_GetCallVar(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JSBool
+js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp);
+
+extern JSBool
+js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, jsval *vp);
+
+extern JSObject *
+js_GetArgsObject(JSContext *cx, JSStackFrame *fp);
+
+extern JS_FRIEND_API(JSBool)
+js_PutArgsObject(JSContext *cx, JSStackFrame *fp);
+
+extern JSBool
+js_XDRFunction(JSXDRState *xdr, JSObject **objp);
+
+typedef enum JSLocalKind {
+ JSLOCAL_NONE,
+ JSLOCAL_ARG,
+ JSLOCAL_VAR,
+ JSLOCAL_CONST,
+ JSLOCAL_UPVAR
+} JSLocalKind;
+
+#define JS_UPVAR_LOCAL_NAME_START(fun) ((fun)->nargs + (fun)->u.i.nvars)
+#define JS_GET_LOCAL_NAME_COUNT(fun) (JS_UPVAR_LOCAL_NAME_START(fun) + \
+ (fun)->u.i.nupvars)
+
+extern JSBool
+js_AddLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, JSLocalKind kind);
+
+/*
+ * Look up an argument or variable name returning its kind when found or
+ * JSLOCAL_NONE when no such name exists. When indexp is not null and the name
+ * exists, *indexp will receive the index of the corresponding argument or
+ * variable.
+ */
+extern JSLocalKind
+js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
+
+/*
+ * Functions to work with local names as an array of words.
+ *
+ * js_GetLocalNameArray returns the array, or null if we are out of memory.
+ * This function must not be called when JS_GET_LOCAL_NAME_COUNT(fun) is zero.
+ *
+ * The supplied pool is used to allocate the returned array, so the caller is
+ * obligated to mark and release to free it.
+ *
+ * The elements of the array with index less than fun->nargs correspond to the
+ * names of function formal parameters. An index >= fun->nargs addresses a var
+ * binding. Use JS_LOCAL_NAME_TO_ATOM to convert array's element to an atom
+ * pointer. This pointer can be null when the element is for a formal parameter
+ * corresponding to a destructuring pattern.
+ *
+ * If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
+ * check if nameWord corresponds to the const declaration.
+ */
+extern jsuword *
+js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
+
+#define JS_LOCAL_NAME_TO_ATOM(nameWord) \
+ ((JSAtom *) ((nameWord) & ~(jsuword) 1))
+
+#define JS_LOCAL_NAME_IS_CONST(nameWord) \
+ ((((nameWord) & (jsuword) 1)) != 0)
+
+extern void
+js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
+
+extern JSBool
+js_fun_apply(JSContext *cx, uintN argc, jsval *vp);
+
+extern JSBool
+js_fun_call(JSContext *cx, uintN argc, jsval *vp);
+
+
+JS_END_EXTERN_C
+
+#endif /* jsfun_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp
new file mode 100644
index 0000000..ac29021
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.cpp
@@ -0,0 +1,3763 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS Mark-and-Sweep Garbage Collector.
+ *
+ * This GC allocates fixed-sized things with sizes up to GC_NBYTES_MAX (see
+ * jsgc.h). It allocates from a special GC arena pool with each arena allocated
+ * using malloc. It uses an ideally parallel array of flag bytes to hold the
+ * mark bit, finalizer type index, etc.
+ *
+ * XXX swizzle page to freelist for better locality of reference
+ */
+#include "jsstddef.h"
+#include <stdlib.h> /* for free */
+#include <math.h>
+#include <string.h> /* for memset used when DEBUG */
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsbit.h"
+#include "jsclist.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jstracer.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+/*
+ * Check if posix_memalign is available.
+ */
+#if _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || MOZ_MEMORY
+# define HAS_POSIX_MEMALIGN 1
+#else
+# define HAS_POSIX_MEMALIGN 0
+#endif
+
+/*
+ * jemalloc provides posix_memalign.
+ */
+#ifdef MOZ_MEMORY
+extern "C" {
+#include "../../memory/jemalloc/jemalloc.h"
+}
+#endif
+
+/*
+ * Include the headers for mmap unless we have posix_memalign and do not
+ * insist on mmap.
+ */
+#if JS_GC_USE_MMAP || (!defined JS_GC_USE_MMAP && !HAS_POSIX_MEMALIGN)
+# if defined(XP_WIN)
+# ifndef JS_GC_USE_MMAP
+# define JS_GC_USE_MMAP 1
+# endif
+# include <windows.h>
+# else
+# if defined(XP_UNIX) || defined(XP_BEOS)
+# include <unistd.h>
+# endif
+# if _POSIX_MAPPED_FILES > 0
+# ifndef JS_GC_USE_MMAP
+# define JS_GC_USE_MMAP 1
+# endif
+# include <sys/mman.h>
+
+/* On Mac OS X MAP_ANONYMOUS is not defined. */
+# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+# else
+# if JS_GC_USE_MMAP
+# error "JS_GC_USE_MMAP is set when mmap is not available"
+# endif
+# endif
+# endif
+#endif
+
+/*
+ * A GC arena contains a fixed number of flag bits for each thing in its heap,
+ * and supports O(1) lookup of a flag given its thing's address.
+ *
+ * To implement this, we allocate things of the same size from a GC arena
+ * containing GC_ARENA_SIZE bytes aligned on GC_ARENA_SIZE boundary. The
+ * following picture shows arena's layout:
+ *
+ * +------------------------------+--------------------+---------------+
+ * | allocation area for GC thing | flags of GC things | JSGCArenaInfo |
+ * +------------------------------+--------------------+---------------+
+ *
+ * To find the flag bits for the thing we calculate the thing index counting
+ * from arena's start using:
+ *
+ * thingIndex = (thingAddress & GC_ARENA_MASK) / thingSize
+ *
+ * The details of flag's lookup depend on thing's kind. For all GC things
+ * except doubles we use one byte of flags where the 4 bits determine thing's
+ * type and the rest is used to implement GC marking, finalization and
+ * locking. We calculate the address of flag's byte using:
+ *
+ * flagByteAddress =
+ * (thingAddress | GC_ARENA_MASK) - sizeof(JSGCArenaInfo) - thingIndex
+ *
+ * where
+ *
+ * (thingAddress | GC_ARENA_MASK) - sizeof(JSGCArenaInfo)
+ *
+ * is the last byte of flags' area.
+ *
+ * This implies that the things are allocated from the start of their area and
+ * flags are allocated from the end. This arrangement avoids a relatively
+ * expensive calculation of the location of the boundary separating things and
+ * flags. The boundary's offset from the start of the arena is given by:
+ *
+ * thingsPerArena * thingSize
+ *
+ * where thingsPerArena is the number of things that the arena can hold:
+ *
+ * (GC_ARENA_SIZE - sizeof(JSGCArenaInfo)) / (thingSize + 1).
+ *
+ * To allocate doubles we use a specialized arena. It can contain only numbers
+ * so we do not need the type bits. Moreover, since the doubles do not require
+ * a finalizer and very few of them are locked via js_LockGCThing API, we use
+ * just one bit of flags per double to denote if it was marked during the
+ * marking phase of the GC. The locking is implemented via a hash table. Thus
+ * for doubles the flag area becomes a bitmap.
+ *
+ * JS_GC_USE_MMAP macro governs the choice of the aligned arena allocator.
+ * When it is true, a platform-dependent function like mmap is used to get
+ * memory aligned on CPU page boundaries. If the macro is false or undefined,
+ * posix_memalign is used when available. Otherwise the code uses malloc to
+ * over-allocate a chunk with js_gcArenasPerChunk aligned arenas. The
+ * approximate space overhead of this is 1/js_gcArenasPerChunk. For details,
+ * see NewGCChunk/DestroyGCChunk below.
+ *
+ * The code also allocates arenas in chunks when JS_GC_USE_MMAP is 1 to
+ * minimize the overhead of mmap/munmap. In this case js_gcArenasPerChunk can
+ * not be a compile-time constant as the system page size is not known until
+ * runtime.
+ */
+#if JS_GC_USE_MMAP
+static uint32 js_gcArenasPerChunk = 0;
+static JSBool js_gcUseMmap = JS_FALSE;
+#elif HAS_POSIX_MEMALIGN
+# define js_gcArenasPerChunk 1
+#else
+# define js_gcArenasPerChunk 7
+#endif
+
+#if defined(js_gcArenasPerChunk) && js_gcArenasPerChunk == 1
+# define CHUNKED_ARENA_ALLOCATION 0
+#else
+# define CHUNKED_ARENA_ALLOCATION 1
+#endif
+
+#define GC_ARENA_SHIFT 12
+#define GC_ARENA_MASK ((jsuword) JS_BITMASK(GC_ARENA_SHIFT))
+#define GC_ARENA_SIZE JS_BIT(GC_ARENA_SHIFT)
+
+/*
+ * JS_GC_ARENA_PAD defines the number of bytes to pad JSGCArenaInfo structure.
+ * It is used to improve allocation efficiency when using posix_memalign. If
+ * malloc's implementation uses internal headers, then calling
+ *
+ * posix_memalign(&p, GC_ARENA_SIZE, GC_ARENA_SIZE * js_gcArenasPerChunk)
+ *
+ * in a sequence leaves holes between allocations of the size GC_ARENA_SIZE
+ * due to the need to fit headers. JS_GC_ARENA_PAD mitigates that so the code
+ * calls
+ *
+ * posix_memalign(&p, GC_ARENA_SIZE,
+ * GC_ARENA_SIZE * js_gcArenasPerChunk - JS_GC_ARENA_PAD)
+ *
+ * When JS_GC_ARENA_PAD is equal or greater than the number of words in the
+ * system header, the system can pack all allocations together without holes.
+ *
+ * With JS_GC_USE_MEMALIGN we want at least 2 word pad unless posix_memalign
+ * comes from jemalloc that does not use any headers/trailers.
+ */
+#ifndef JS_GC_ARENA_PAD
+# if HAS_POSIX_MEMALIGN && !MOZ_MEMORY
+# define JS_GC_ARENA_PAD (2 * JS_BYTES_PER_WORD)
+# else
+# define JS_GC_ARENA_PAD 0
+# endif
+#endif
+
+struct JSGCArenaInfo {
+ /*
+ * Allocation list for the arena or NULL if the arena holds double values.
+ */
+ JSGCArenaList *list;
+
+ /*
+ * Pointer to the previous arena in a linked list. The arena can either
+ * belong to one of JSContext.gcArenaList lists or, when it does not have
+ * any allocated GC things, to the list of free arenas in the chunk with
+ * head stored in JSGCChunkInfo.lastFreeArena.
+ */
+ JSGCArenaInfo *prev;
+
+#if !CHUNKED_ARENA_ALLOCATION
+ jsuword prevUntracedPage;
+#else
+ /*
+ * A link field for the list of arenas with marked but not yet traced
+ * things. The field is encoded as arena's page to share the space with
+ * firstArena and arenaIndex fields.
+ */
+ jsuword prevUntracedPage : JS_BITS_PER_WORD - GC_ARENA_SHIFT;
+
+ /*
+ * When firstArena is false, the index of arena in the chunk. When
+ * firstArena is true, the index of a free arena holding JSGCChunkInfo or
+ * NO_FREE_ARENAS if there are no free arenas in the chunk.
+ *
+ * GET_ARENA_INDEX and GET_CHUNK_INFO_INDEX are convenience macros to
+ * access either of indexes.
+ */
+ jsuword arenaIndex : GC_ARENA_SHIFT - 1;
+
+ /* Flag indicating if the arena is the first in the chunk. */
+ jsuword firstArena : 1;
+#endif
+
+ union {
+ jsuword untracedThings; /* bitset for fast search of marked
+ but not yet traced things */
+ JSBool hasMarkedDoubles; /* the arena has marked doubles */
+ } u;
+
+#if JS_GC_ARENA_PAD != 0
+ uint8 pad[JS_GC_ARENA_PAD];
+#endif
+};
+
+/*
+ * Verify that the bit fields are indeed shared and JSGCArenaInfo is as small
+ * as possible. The code does not rely on this check so if on a particular
+ * platform this does not compile, then, as a workaround, comment the assert
+ * out and submit a bug report.
+ */
+JS_STATIC_ASSERT(offsetof(JSGCArenaInfo, u) == 3 * sizeof(jsuword));
+
+/*
+ * Macros to convert between JSGCArenaInfo, the start address of the arena and
+ * arena's page defined as (start address) >> GC_ARENA_SHIFT.
+ */
+#define ARENA_INFO_OFFSET (GC_ARENA_SIZE - (uint32) sizeof(JSGCArenaInfo))
+
+#define IS_ARENA_INFO_ADDRESS(arena) \
+ (((jsuword) (arena) & GC_ARENA_MASK) == ARENA_INFO_OFFSET)
+
+#define ARENA_START_TO_INFO(arenaStart) \
+ (JS_ASSERT(((arenaStart) & (jsuword) GC_ARENA_MASK) == 0), \
+ (JSGCArenaInfo *) ((arenaStart) + (jsuword) ARENA_INFO_OFFSET))
+
+#define ARENA_INFO_TO_START(arena) \
+ (JS_ASSERT(IS_ARENA_INFO_ADDRESS(arena)), \
+ (jsuword) (arena) & ~(jsuword) GC_ARENA_MASK)
+
+#define ARENA_PAGE_TO_INFO(arenaPage) \
+ (JS_ASSERT(arenaPage != 0), \
+ JS_ASSERT(!((jsuword)(arenaPage) >> (JS_BITS_PER_WORD-GC_ARENA_SHIFT))), \
+ ARENA_START_TO_INFO((arenaPage) << GC_ARENA_SHIFT))
+
+#define ARENA_INFO_TO_PAGE(arena) \
+ (JS_ASSERT(IS_ARENA_INFO_ADDRESS(arena)), \
+ ((jsuword) (arena) >> GC_ARENA_SHIFT))
+
+#define GET_ARENA_INFO(chunk, index) \
+ (JS_ASSERT((index) < js_gcArenasPerChunk), \
+ ARENA_START_TO_INFO(chunk + ((index) << GC_ARENA_SHIFT)))
+
+#if CHUNKED_ARENA_ALLOCATION
+/*
+ * Definitions for allocating arenas in chunks.
+ *
+ * All chunks that have at least one free arena are put on the doubly-linked
+ * list with the head stored in JSRuntime.gcChunkList. JSGCChunkInfo contains
+ * the head of the chunk's free arena list together with the link fields for
+ * gcChunkList.
+ *
+ * Structure stored in one of chunk's free arenas. GET_CHUNK_INFO_INDEX gives
+ * the index of this arena. When all arenas in the chunk are used, it is
+ * removed from the list and the index is set to NO_FREE_ARENAS indicating
+ * that the chunk is not on gcChunkList and has no JSGCChunkInfo available.
+ */
+
+struct JSGCChunkInfo {
+ JSGCChunkInfo **prevp;
+ JSGCChunkInfo *next;
+ JSGCArenaInfo *lastFreeArena;
+ uint32 numFreeArenas;
+};
+
+#define NO_FREE_ARENAS JS_BITMASK(GC_ARENA_SHIFT - 1)
+
+#ifdef js_gcArenasPerChunk
+JS_STATIC_ASSERT(1 <= js_gcArenasPerChunk &&
+ js_gcArenasPerChunk <= NO_FREE_ARENAS);
+#endif
+
+#define GET_ARENA_CHUNK(arena, index) \
+ (JS_ASSERT(GET_ARENA_INDEX(arena) == index), \
+ ARENA_INFO_TO_START(arena) - ((index) << GC_ARENA_SHIFT))
+
+#define GET_ARENA_INDEX(arena) \
+ ((arena)->firstArena ? 0 : (uint32) (arena)->arenaIndex)
+
+#define GET_CHUNK_INFO_INDEX(chunk) \
+ ((uint32) ARENA_START_TO_INFO(chunk)->arenaIndex)
+
+#define SET_CHUNK_INFO_INDEX(chunk, index) \
+ (JS_ASSERT((index) < js_gcArenasPerChunk || (index) == NO_FREE_ARENAS), \
+ (void) (ARENA_START_TO_INFO(chunk)->arenaIndex = (jsuword) (index)))
+
+#define GET_CHUNK_INFO(chunk, infoIndex) \
+ (JS_ASSERT(GET_CHUNK_INFO_INDEX(chunk) == (infoIndex)), \
+ JS_ASSERT((uint32) (infoIndex) < js_gcArenasPerChunk), \
+ (JSGCChunkInfo *) ((chunk) + ((infoIndex) << GC_ARENA_SHIFT)))
+
+#define CHUNK_INFO_TO_INDEX(ci) \
+ GET_ARENA_INDEX(ARENA_START_TO_INFO((jsuword)ci))
+
+#endif
+
+/*
+ * Macros for GC-thing operations.
+ */
+#define THINGS_PER_ARENA(thingSize) \
+ ((GC_ARENA_SIZE - (uint32) sizeof(JSGCArenaInfo)) / ((thingSize) + 1U))
+
+#define THING_TO_ARENA(thing) \
+ ((JSGCArenaInfo *)(((jsuword) (thing) | GC_ARENA_MASK) + \
+ 1 - sizeof(JSGCArenaInfo)))
+
+#define THING_TO_INDEX(thing, thingSize) \
+ ((uint32) ((jsuword) (thing) & GC_ARENA_MASK) / (uint32) (thingSize))
+
+#define THING_FLAGS_END(arena) ((uint8 *)(arena))
+
+#define THING_FLAGP(arena, thingIndex) \
+ (JS_ASSERT((jsuword) (thingIndex) \
+ < (jsuword) THINGS_PER_ARENA((arena)->list->thingSize)), \
+ (uint8 *)(arena) - 1 - (thingIndex))
+
+#define THING_TO_FLAGP(thing, thingSize) \
+ THING_FLAGP(THING_TO_ARENA(thing), THING_TO_INDEX(thing, thingSize))
+
+#define FLAGP_TO_ARENA(flagp) THING_TO_ARENA(flagp)
+
+#define FLAGP_TO_INDEX(flagp) \
+ (JS_ASSERT(((jsuword) (flagp) & GC_ARENA_MASK) < ARENA_INFO_OFFSET), \
+ (ARENA_INFO_OFFSET - 1 - (uint32) ((jsuword) (flagp) & GC_ARENA_MASK)))
+
+#define FLAGP_TO_THING(flagp, thingSize) \
+ (JS_ASSERT(((jsuword) (flagp) & GC_ARENA_MASK) >= \
+ (ARENA_INFO_OFFSET - THINGS_PER_ARENA(thingSize))), \
+ (JSGCThing *)(((jsuword) (flagp) & ~GC_ARENA_MASK) + \
+ (thingSize) * FLAGP_TO_INDEX(flagp)))
+
+/*
+ * Macros for the specialized arena for doubles.
+ *
+ * DOUBLES_PER_ARENA defines the maximum number of doubles that the arena can
+ * hold. We find it as the following. Let n be the number of doubles in the
+ * arena. Together with the bitmap of flags and JSGCArenaInfo they should fit
+ * the arena. Hence DOUBLES_PER_ARENA or n_max is the maximum value of n for
+ * which the following holds:
+ *
+ * n*s + ceil(n/B) <= M (1)
+ *
+ * where "/" denotes normal real division,
+ * ceil(r) gives the least integer not smaller than the number r,
+ * s is the number of words in jsdouble,
+ * B is number of bits per word or B == JS_BITS_PER_WORD
+ * M is the number of words in the arena before JSGCArenaInfo or
+ * M == (GC_ARENA_SIZE - sizeof(JSGCArenaInfo)) / sizeof(jsuword).
+ * M == ARENA_INFO_OFFSET / sizeof(jsuword)
+ *
+ * We rewrite the inequality as
+ *
+ * n*B*s/B + ceil(n/B) <= M,
+ * ceil(n*B*s/B + n/B) <= M,
+ * ceil(n*(B*s + 1)/B) <= M (2)
+ *
+ * We define a helper function e(n, s, B),
+ *
+ * e(n, s, B) := ceil(n*(B*s + 1)/B) - n*(B*s + 1)/B, 0 <= e(n, s, B) < 1.
+ *
+ * It gives:
+ *
+ * n*(B*s + 1)/B + e(n, s, B) <= M,
+ * n + e*B/(B*s + 1) <= M*B/(B*s + 1)
+ *
+ * We apply the floor function to both sides of the last equation, where
+ * floor(r) gives the biggest integer not greater than r. As a consequence we
+ * have:
+ *
+ * floor(n + e*B/(B*s + 1)) <= floor(M*B/(B*s + 1)),
+ * n + floor(e*B/(B*s + 1)) <= floor(M*B/(B*s + 1)),
+ * n <= floor(M*B/(B*s + 1)), (3)
+ *
+ * where floor(e*B/(B*s + 1)) is zero as e*B/(B*s + 1) < B/(B*s + 1) < 1.
+ * Thus any n that satisfies the original constraint (1) or its equivalent (2),
+ * must also satisfy (3). That is, we got an upper estimate for the maximum
+ * value of n. Lets show that this upper estimate,
+ *
+ * floor(M*B/(B*s + 1)), (4)
+ *
+ * also satisfies (1) and, as such, gives the required maximum value.
+ * Substituting it into (2) gives:
+ *
+ * ceil(floor(M*B/(B*s + 1))*(B*s + 1)/B) == ceil(floor(M/X)*X)
+ *
+ * where X == (B*s + 1)/B > 1. But then floor(M/X)*X <= M/X*X == M and
+ *
+ * ceil(floor(M/X)*X) <= ceil(M) == M.
+ *
+ * Thus the value of (4) gives the maximum n satisfying (1).
+ *
+ * For the final result we observe that in (4)
+ *
+ * M*B == ARENA_INFO_OFFSET / sizeof(jsuword) * JS_BITS_PER_WORD
+ * == ARENA_INFO_OFFSET * JS_BITS_PER_BYTE
+ *
+ * and
+ *
+ * B*s == JS_BITS_PER_WORD * sizeof(jsdouble) / sizeof(jsuword)
+ * == JS_BITS_PER_DOUBLE.
+ */
+#define DOUBLES_PER_ARENA \
+ ((ARENA_INFO_OFFSET * JS_BITS_PER_BYTE) / (JS_BITS_PER_DOUBLE + 1))
+
+/*
+ * Check that ARENA_INFO_OFFSET and sizeof(jsdouble) divides sizeof(jsuword).
+ */
+JS_STATIC_ASSERT(ARENA_INFO_OFFSET % sizeof(jsuword) == 0);
+JS_STATIC_ASSERT(sizeof(jsdouble) % sizeof(jsuword) == 0);
+JS_STATIC_ASSERT(sizeof(jsbitmap) == sizeof(jsuword));
+
+#define DOUBLES_ARENA_BITMAP_WORDS \
+ (JS_HOWMANY(DOUBLES_PER_ARENA, JS_BITS_PER_WORD))
+
+/* Check that DOUBLES_PER_ARENA indeed maximises (1). */
+JS_STATIC_ASSERT(DOUBLES_PER_ARENA * sizeof(jsdouble) +
+ DOUBLES_ARENA_BITMAP_WORDS * sizeof(jsuword) <=
+ ARENA_INFO_OFFSET);
+
+JS_STATIC_ASSERT((DOUBLES_PER_ARENA + 1) * sizeof(jsdouble) +
+ sizeof(jsuword) *
+ JS_HOWMANY((DOUBLES_PER_ARENA + 1), JS_BITS_PER_WORD) >
+ ARENA_INFO_OFFSET);
+
+/*
+ * When DOUBLES_PER_ARENA % BITS_PER_DOUBLE_FLAG_UNIT != 0, some bits in the
+ * last byte of the occupation bitmap are unused.
+ */
+#define UNUSED_DOUBLE_BITMAP_BITS \
+ (DOUBLES_ARENA_BITMAP_WORDS * JS_BITS_PER_WORD - DOUBLES_PER_ARENA)
+
+JS_STATIC_ASSERT(UNUSED_DOUBLE_BITMAP_BITS < JS_BITS_PER_WORD);
+
+#define DOUBLES_ARENA_BITMAP_OFFSET \
+ (ARENA_INFO_OFFSET - DOUBLES_ARENA_BITMAP_WORDS * sizeof(jsuword))
+
+#define CHECK_DOUBLE_ARENA_INFO(arenaInfo) \
+ (JS_ASSERT(IS_ARENA_INFO_ADDRESS(arenaInfo)), \
+ JS_ASSERT(!(arenaInfo)->list)) \
+
+/*
+ * Get the start of the bitmap area containing double mark flags in the arena.
+ * To access the flag the code uses
+ *
+ * JS_TEST_BIT(bitmapStart, index)
+ *
+ * That is, compared with the case of arenas with non-double things, we count
+ * flags from the start of the bitmap area, not from the end.
+ */
+#define DOUBLE_ARENA_BITMAP(arenaInfo) \
+ (CHECK_DOUBLE_ARENA_INFO(arenaInfo), \
+ (jsbitmap *) arenaInfo - DOUBLES_ARENA_BITMAP_WORDS)
+
+#define DOUBLE_THING_TO_INDEX(thing) \
+ (CHECK_DOUBLE_ARENA_INFO(THING_TO_ARENA(thing)), \
+ JS_ASSERT(((jsuword) (thing) & GC_ARENA_MASK) < \
+ DOUBLES_ARENA_BITMAP_OFFSET), \
+ ((uint32) (((jsuword) (thing) & GC_ARENA_MASK) / sizeof(jsdouble))))
+
+static void
+ClearDoubleArenaFlags(JSGCArenaInfo *a)
+{
+ jsbitmap *bitmap, mask;
+ uintN nused;
+
+ /*
+ * When some high bits in the last byte of the double occupation bitmap
+ * are unused, we must set them. Otherwise RefillDoubleFreeList will
+ * assume that they corresponds to some free cells and tries to allocate
+ * them.
+ *
+ * Note that the code works correctly with UNUSED_DOUBLE_BITMAP_BITS == 0.
+ */
+ bitmap = DOUBLE_ARENA_BITMAP(a);
+ memset(bitmap, 0, (DOUBLES_ARENA_BITMAP_WORDS - 1) * sizeof *bitmap);
+ mask = ((jsbitmap) 1 << UNUSED_DOUBLE_BITMAP_BITS) - 1;
+ nused = JS_BITS_PER_WORD - UNUSED_DOUBLE_BITMAP_BITS;
+ bitmap[DOUBLES_ARENA_BITMAP_WORDS - 1] = mask << nused;
+}
+
+static JS_ALWAYS_INLINE JSBool
+IsMarkedDouble(JSGCArenaInfo *a, uint32 index)
+{
+ jsbitmap *bitmap;
+
+ JS_ASSERT(a->u.hasMarkedDoubles);
+ bitmap = DOUBLE_ARENA_BITMAP(a);
+ return JS_TEST_BIT(bitmap, index);
+}
+
+/*
+ * JSRuntime.gcDoubleArenaList.nextDoubleFlags points either to:
+ *
+ * 1. The next byte in the bitmap area for doubles to check for unmarked
+ * (or free) doubles.
+ * 2. Or to the end of the bitmap area when all GC cells of the arena are
+ * allocated.
+ * 3. Or to a special sentinel value indicating that there are no arenas
+ * to check for unmarked doubles.
+ *
+ * We set the sentinel to ARENA_INFO_OFFSET so the single check
+ *
+ * ((jsuword) nextDoubleFlags & GC_ARENA_MASK) == ARENA_INFO_OFFSET
+ *
+ * will cover both the second and the third cases.
+ */
+#define DOUBLE_BITMAP_SENTINEL ((jsbitmap *) ARENA_INFO_OFFSET)
+
+#ifdef JS_THREADSAFE
+/*
+ * The maximum number of things to put on the local free list by taking
+ * several things from the global free list or from the tail of the last
+ * allocated arena to amortize the cost of rt->gcLock.
+ *
+ * We use number 8 based on benchmarks from bug 312238.
+ */
+#define MAX_THREAD_LOCAL_THINGS 8
+
+#endif
+
+JS_STATIC_ASSERT(sizeof(JSStackHeader) >= 2 * sizeof(jsval));
+
+JS_STATIC_ASSERT(sizeof(JSGCThing) >= sizeof(JSString));
+JS_STATIC_ASSERT(sizeof(JSGCThing) >= sizeof(jsdouble));
+
+/* We want to use all the available GC thing space for object's slots. */
+JS_STATIC_ASSERT(sizeof(JSObject) % sizeof(JSGCThing) == 0);
+
+/*
+ * Ensure that JSObject is allocated from a different GC-list rather than
+ * jsdouble and JSString so we can easily finalize JSObject before these 2
+ * types of GC things. See comments in js_GC.
+ */
+JS_STATIC_ASSERT(GC_FREELIST_INDEX(sizeof(JSString)) !=
+ GC_FREELIST_INDEX(sizeof(JSObject)));
+JS_STATIC_ASSERT(GC_FREELIST_INDEX(sizeof(jsdouble)) !=
+ GC_FREELIST_INDEX(sizeof(JSObject)));
+
+/*
+ * JSPtrTable capacity growth descriptor. The table grows by powers of two
+ * starting from capacity JSPtrTableInfo.minCapacity, but switching to linear
+ * growth when capacity reaches JSPtrTableInfo.linearGrowthThreshold.
+ */
+typedef struct JSPtrTableInfo {
+ uint16 minCapacity;
+ uint16 linearGrowthThreshold;
+} JSPtrTableInfo;
+
+#define GC_ITERATOR_TABLE_MIN 4
+#define GC_ITERATOR_TABLE_LINEAR 1024
+
+static const JSPtrTableInfo iteratorTableInfo = {
+ GC_ITERATOR_TABLE_MIN,
+ GC_ITERATOR_TABLE_LINEAR
+};
+
+/* Calculate table capacity based on the current value of JSPtrTable.count. */
+static size_t
+PtrTableCapacity(size_t count, const JSPtrTableInfo *info)
+{
+ size_t linear, log, capacity;
+
+ linear = info->linearGrowthThreshold;
+ JS_ASSERT(info->minCapacity <= linear);
+
+ if (count == 0) {
+ capacity = 0;
+ } else if (count < linear) {
+ log = JS_CEILING_LOG2W(count);
+ JS_ASSERT(log != JS_BITS_PER_WORD);
+ capacity = (size_t)1 << log;
+ if (capacity < info->minCapacity)
+ capacity = info->minCapacity;
+ } else {
+ capacity = JS_ROUNDUP(count, linear);
+ }
+
+ JS_ASSERT(capacity >= count);
+ return capacity;
+}
+
+static void
+FreePtrTable(JSPtrTable *table, const JSPtrTableInfo *info)
+{
+ if (table->array) {
+ JS_ASSERT(table->count > 0);
+ free(table->array);
+ table->array = NULL;
+ table->count = 0;
+ }
+ JS_ASSERT(table->count == 0);
+}
+
+static JSBool
+AddToPtrTable(JSContext *cx, JSPtrTable *table, const JSPtrTableInfo *info,
+ void *ptr)
+{
+ size_t count, capacity;
+ void **array;
+
+ count = table->count;
+ capacity = PtrTableCapacity(count, info);
+
+ if (count == capacity) {
+ if (capacity < info->minCapacity) {
+ JS_ASSERT(capacity == 0);
+ JS_ASSERT(!table->array);
+ capacity = info->minCapacity;
+ } else {
+ /*
+ * Simplify the overflow detection assuming pointer is bigger
+ * than byte.
+ */
+ JS_STATIC_ASSERT(2 <= sizeof table->array[0]);
+ capacity = (capacity < info->linearGrowthThreshold)
+ ? 2 * capacity
+ : capacity + info->linearGrowthThreshold;
+ if (capacity > (size_t)-1 / sizeof table->array[0])
+ goto bad;
+ }
+ array = (void **) realloc(table->array,
+ capacity * sizeof table->array[0]);
+ if (!array)
+ goto bad;
+#ifdef DEBUG
+ memset(array + count, JS_FREE_PATTERN,
+ (capacity - count) * sizeof table->array[0]);
+#endif
+ table->array = array;
+ }
+
+ table->array[count] = ptr;
+ table->count = count + 1;
+
+ return JS_TRUE;
+
+ bad:
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+}
+
+static void
+ShrinkPtrTable(JSPtrTable *table, const JSPtrTableInfo *info,
+ size_t newCount)
+{
+ size_t oldCapacity, capacity;
+ void **array;
+
+ JS_ASSERT(newCount <= table->count);
+ if (newCount == table->count)
+ return;
+
+ oldCapacity = PtrTableCapacity(table->count, info);
+ table->count = newCount;
+ capacity = PtrTableCapacity(newCount, info);
+
+ if (oldCapacity != capacity) {
+ array = table->array;
+ JS_ASSERT(array);
+ if (capacity == 0) {
+ free(array);
+ table->array = NULL;
+ return;
+ }
+ array = (void **) realloc(array, capacity * sizeof array[0]);
+ if (array)
+ table->array = array;
+ }
+#ifdef DEBUG
+ memset(table->array + newCount, JS_FREE_PATTERN,
+ (capacity - newCount) * sizeof table->array[0]);
+#endif
+}
+
+#ifdef JS_GCMETER
+# define METER(x) ((void) (x))
+# define METER_IF(condition, x) ((void) ((condition) && (x)))
+#else
+# define METER(x) ((void) 0)
+# define METER_IF(condition, x) ((void) 0)
+#endif
+
+#define METER_UPDATE_MAX(maxLval, rval) \
+ METER_IF((maxLval) < (rval), (maxLval) = (rval))
+
+#if JS_GC_USE_MMAP || !HAS_POSIX_MEMALIGN
+
+/*
+ * For chunks allocated via over-sized malloc, get a pointer to store the gap
+ * between the malloc's result and the first arena in the chunk.
+ */
+static uint32 *
+GetMallocedChunkGapPtr(jsuword chunk)
+{
+ JS_ASSERT((chunk & GC_ARENA_MASK) == 0);
+
+ /* Use the memory after the chunk, see NewGCChunk for details. */
+ return (uint32 *) (chunk + (js_gcArenasPerChunk << GC_ARENA_SHIFT));
+}
+
+#endif
+
+static jsuword
+NewGCChunk(void)
+{
+ void *p;
+
+#if JS_GC_USE_MMAP
+ if (js_gcUseMmap) {
+# if defined(XP_WIN)
+ p = VirtualAlloc(NULL, js_gcArenasPerChunk << GC_ARENA_SHIFT,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ return (jsuword) p;
+# else
+ p = mmap(NULL, js_gcArenasPerChunk << GC_ARENA_SHIFT,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ return (p == MAP_FAILED) ? 0 : (jsuword) p;
+# endif
+ }
+#endif
+
+#if HAS_POSIX_MEMALIGN
+ if (0 != posix_memalign(&p, GC_ARENA_SIZE,
+ GC_ARENA_SIZE * js_gcArenasPerChunk -
+ JS_GC_ARENA_PAD)) {
+ return 0;
+ }
+ return (jsuword) p;
+#else
+ /*
+ * Implement chunk allocation using oversized malloc if mmap and
+ * posix_memalign are not available.
+ *
+ * Since malloc allocates pointers aligned on the word boundary, to get
+ * js_gcArenasPerChunk aligned arenas, we need to malloc only
+ *
+ * ((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT) - sizeof(size_t)
+ *
+ * bytes. But since we stores the gap between the malloced pointer and the
+ * first arena in the chunk after the chunk, we need to ask for
+ *
+ * ((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT)
+ *
+ * bytes to ensure that we always have room to store the gap.
+ */
+ p = malloc((js_gcArenasPerChunk + 1) << GC_ARENA_SHIFT);
+ if (!p)
+ return 0;
+
+ {
+ jsuword chunk;
+
+ chunk = ((jsuword) p + GC_ARENA_MASK) & ~GC_ARENA_MASK;
+ *GetMallocedChunkGapPtr(chunk) = (uint32) (chunk - (jsuword) p);
+ return chunk;
+ }
+#endif
+}
+
+static void
+DestroyGCChunk(jsuword chunk)
+{
+ JS_ASSERT((chunk & GC_ARENA_MASK) == 0);
+#if JS_GC_USE_MMAP
+ if (js_gcUseMmap) {
+# if defined(XP_WIN)
+ VirtualFree((void *) chunk, 0, MEM_RELEASE);
+# elif defined(SOLARIS)
+ munmap((char *) chunk, js_gcArenasPerChunk << GC_ARENA_SHIFT);
+# else
+ munmap((void *) chunk, js_gcArenasPerChunk << GC_ARENA_SHIFT);
+# endif
+ return;
+ }
+#endif
+
+#if HAS_POSIX_MEMALIGN
+ free((void *) chunk);
+#else
+ /* See comments in NewGCChunk. */
+ JS_ASSERT(*GetMallocedChunkGapPtr(chunk) < GC_ARENA_SIZE);
+ free((void *) (chunk - *GetMallocedChunkGapPtr(chunk)));
+#endif
+}
+
+#if CHUNKED_ARENA_ALLOCATION
+
+static void
+AddChunkToList(JSRuntime *rt, JSGCChunkInfo *ci)
+{
+ ci->prevp = &rt->gcChunkList;
+ ci->next = rt->gcChunkList;
+ if (rt->gcChunkList) {
+ JS_ASSERT(rt->gcChunkList->prevp == &rt->gcChunkList);
+ rt->gcChunkList->prevp = &ci->next;
+ }
+ rt->gcChunkList = ci;
+}
+
+static void
+RemoveChunkFromList(JSRuntime *rt, JSGCChunkInfo *ci)
+{
+ *ci->prevp = ci->next;
+ if (ci->next) {
+ JS_ASSERT(ci->next->prevp == &ci->next);
+ ci->next->prevp = ci->prevp;
+ }
+}
+
+#endif
+
+static JSGCArenaInfo *
+NewGCArena(JSRuntime *rt)
+{
+ jsuword chunk;
+ JSGCArenaInfo *a;
+
+ if (rt->gcBytes >= rt->gcMaxBytes)
+ return NULL;
+
+#if CHUNKED_ARENA_ALLOCATION
+ if (js_gcArenasPerChunk == 1) {
+#endif
+ chunk = NewGCChunk();
+ if (chunk == 0)
+ return NULL;
+ a = ARENA_START_TO_INFO(chunk);
+#if CHUNKED_ARENA_ALLOCATION
+ } else {
+ JSGCChunkInfo *ci;
+ uint32 i;
+ JSGCArenaInfo *aprev;
+
+ ci = rt->gcChunkList;
+ if (!ci) {
+ chunk = NewGCChunk();
+ if (chunk == 0)
+ return NULL;
+ JS_ASSERT((chunk & GC_ARENA_MASK) == 0);
+ a = GET_ARENA_INFO(chunk, 0);
+ a->firstArena = JS_TRUE;
+ a->arenaIndex = 0;
+ aprev = NULL;
+ i = 0;
+ do {
+ a->prev = aprev;
+ aprev = a;
+ ++i;
+ a = GET_ARENA_INFO(chunk, i);
+ a->firstArena = JS_FALSE;
+ a->arenaIndex = i;
+ } while (i != js_gcArenasPerChunk - 1);
+ ci = GET_CHUNK_INFO(chunk, 0);
+ ci->lastFreeArena = aprev;
+ ci->numFreeArenas = js_gcArenasPerChunk - 1;
+ AddChunkToList(rt, ci);
+ } else {
+ JS_ASSERT(ci->prevp == &rt->gcChunkList);
+ a = ci->lastFreeArena;
+ aprev = a->prev;
+ if (!aprev) {
+ JS_ASSERT(ci->numFreeArenas == 1);
+ JS_ASSERT(ARENA_INFO_TO_START(a) == (jsuword) ci);
+ RemoveChunkFromList(rt, ci);
+ chunk = GET_ARENA_CHUNK(a, GET_ARENA_INDEX(a));
+ SET_CHUNK_INFO_INDEX(chunk, NO_FREE_ARENAS);
+ } else {
+ JS_ASSERT(ci->numFreeArenas >= 2);
+ JS_ASSERT(ARENA_INFO_TO_START(a) != (jsuword) ci);
+ ci->lastFreeArena = aprev;
+ ci->numFreeArenas--;
+ }
+ }
+ }
+#endif
+
+ rt->gcBytes += GC_ARENA_SIZE;
+ a->prevUntracedPage = 0;
+ memset(&a->u, 0, sizeof(a->u));
+
+ return a;
+}
+
+static void
+DestroyGCArenas(JSRuntime *rt, JSGCArenaInfo *last)
+{
+ JSGCArenaInfo *a;
+
+ while (last) {
+ a = last;
+ last = last->prev;
+
+ METER(rt->gcStats.afree++);
+ JS_ASSERT(rt->gcBytes >= GC_ARENA_SIZE);
+ rt->gcBytes -= GC_ARENA_SIZE;
+
+#if CHUNKED_ARENA_ALLOCATION
+ if (js_gcArenasPerChunk == 1) {
+#endif
+ DestroyGCChunk(ARENA_INFO_TO_START(a));
+#if CHUNKED_ARENA_ALLOCATION
+ } else {
+ uint32 arenaIndex;
+ jsuword chunk;
+ uint32 chunkInfoIndex;
+ JSGCChunkInfo *ci;
+# ifdef DEBUG
+ jsuword firstArena;
+
+ firstArena = a->firstArena;
+ arenaIndex = a->arenaIndex;
+ memset((void *) ARENA_INFO_TO_START(a), JS_FREE_PATTERN,
+ GC_ARENA_SIZE - JS_GC_ARENA_PAD);
+ a->firstArena = firstArena;
+ a->arenaIndex = arenaIndex;
+# endif
+ arenaIndex = GET_ARENA_INDEX(a);
+ chunk = GET_ARENA_CHUNK(a, arenaIndex);
+ chunkInfoIndex = GET_CHUNK_INFO_INDEX(chunk);
+ if (chunkInfoIndex == NO_FREE_ARENAS) {
+ chunkInfoIndex = arenaIndex;
+ SET_CHUNK_INFO_INDEX(chunk, arenaIndex);
+ ci = GET_CHUNK_INFO(chunk, chunkInfoIndex);
+ a->prev = NULL;
+ ci->lastFreeArena = a;
+ ci->numFreeArenas = 1;
+ AddChunkToList(rt, ci);
+ } else {
+ JS_ASSERT(chunkInfoIndex != arenaIndex);
+ ci = GET_CHUNK_INFO(chunk, chunkInfoIndex);
+ JS_ASSERT(ci->numFreeArenas != 0);
+ JS_ASSERT(ci->lastFreeArena);
+ JS_ASSERT(a != ci->lastFreeArena);
+ if (ci->numFreeArenas == js_gcArenasPerChunk - 1) {
+ RemoveChunkFromList(rt, ci);
+ DestroyGCChunk(chunk);
+ } else {
+ ++ci->numFreeArenas;
+ a->prev = ci->lastFreeArena;
+ ci->lastFreeArena = a;
+ }
+ }
+ }
+# endif
+ }
+}
+
+static void
+InitGCArenaLists(JSRuntime *rt)
+{
+ uintN i, thingSize;
+ JSGCArenaList *arenaList;
+
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i];
+ thingSize = GC_FREELIST_NBYTES(i);
+ JS_ASSERT((size_t)(uint16)thingSize == thingSize);
+ arenaList->last = NULL;
+ arenaList->lastCount = (uint16) THINGS_PER_ARENA(thingSize);
+ arenaList->thingSize = (uint16) thingSize;
+ arenaList->freeList = NULL;
+ }
+ rt->gcDoubleArenaList.first = NULL;
+ rt->gcDoubleArenaList.nextDoubleFlags = DOUBLE_BITMAP_SENTINEL;
+}
+
+static void
+FinishGCArenaLists(JSRuntime *rt)
+{
+ uintN i;
+ JSGCArenaList *arenaList;
+
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i];
+ DestroyGCArenas(rt, arenaList->last);
+ arenaList->last = NULL;
+ arenaList->lastCount = THINGS_PER_ARENA(arenaList->thingSize);
+ arenaList->freeList = NULL;
+ }
+ DestroyGCArenas(rt, rt->gcDoubleArenaList.first);
+ rt->gcDoubleArenaList.first = NULL;
+ rt->gcDoubleArenaList.nextDoubleFlags = DOUBLE_BITMAP_SENTINEL;
+
+ rt->gcBytes = 0;
+ JS_ASSERT(rt->gcChunkList == 0);
+}
+
+/*
+ * This function must not be called when thing is jsdouble.
+ */
+static uint8 *
+GetGCThingFlags(void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index;
+
+ a = THING_TO_ARENA(thing);
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ return THING_FLAGP(a, index);
+}
+
+/*
+ * This function returns null when thing is jsdouble.
+ */
+static uint8 *
+GetGCThingFlagsOrNull(void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index;
+
+ a = THING_TO_ARENA(thing);
+ if (!a->list)
+ return NULL;
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ return THING_FLAGP(a, index);
+}
+
+intN
+js_GetExternalStringGCType(JSString *str)
+{
+ uintN type;
+
+ type = (uintN) *GetGCThingFlags(str) & GCF_TYPEMASK;
+ JS_ASSERT(type == GCX_STRING || type >= GCX_EXTERNAL_STRING);
+ return (type == GCX_STRING) ? -1 : (intN) (type - GCX_EXTERNAL_STRING);
+}
+
+static uint32
+MapGCFlagsToTraceKind(uintN flags)
+{
+ uint32 type;
+
+ type = flags & GCF_TYPEMASK;
+ JS_ASSERT(type != GCX_DOUBLE);
+ JS_ASSERT(type < GCX_NTYPES);
+ return (type < GCX_EXTERNAL_STRING) ? type : JSTRACE_STRING;
+}
+
+JS_FRIEND_API(uint32)
+js_GetGCThingTraceKind(void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index;
+
+ a = THING_TO_ARENA(thing);
+ if (!a->list)
+ return JSTRACE_DOUBLE;
+
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ return MapGCFlagsToTraceKind(*THING_FLAGP(a, index));
+}
+
+JSRuntime*
+js_GetGCStringRuntime(JSString *str)
+{
+ JSGCArenaList *list;
+
+ list = THING_TO_ARENA(str)->list;
+
+ JS_ASSERT(list->thingSize == sizeof(JSGCThing));
+ JS_ASSERT(GC_FREELIST_INDEX(sizeof(JSGCThing)) == 0);
+
+ return (JSRuntime *)((uint8 *)list - offsetof(JSRuntime, gcArenaList));
+}
+
+JSBool
+js_IsAboutToBeFinalized(JSContext *cx, void *thing)
+{
+ JSGCArenaInfo *a;
+ uint32 index, flags;
+
+ a = THING_TO_ARENA(thing);
+ if (!a->list) {
+ /*
+ * Check if arena has no marked doubles. In that case the bitmap with
+ * the mark flags contains all garbage as it is initialized only when
+ * marking the first double in the arena.
+ */
+ if (!a->u.hasMarkedDoubles)
+ return JS_TRUE;
+ index = DOUBLE_THING_TO_INDEX(thing);
+ return !IsMarkedDouble(a, index);
+ }
+ index = THING_TO_INDEX(thing, a->list->thingSize);
+ flags = *THING_FLAGP(a, index);
+ return !(flags & (GCF_MARK | GCF_LOCK | GCF_FINAL));
+}
+
+/* This is compatible with JSDHashEntryStub. */
+typedef struct JSGCRootHashEntry {
+ JSDHashEntryHdr hdr;
+ void *root;
+ const char *name;
+} JSGCRootHashEntry;
+
+/* Initial size of the gcRootsHash table (SWAG, small enough to amortize). */
+#define GC_ROOTS_SIZE 256
+
+#if CHUNKED_ARENA_ALLOCATION
+
+/*
+ * For a CPU with extremely large pages using them for GC things wastes
+ * too much memory.
+ */
+# define GC_ARENAS_PER_CPU_PAGE_LIMIT JS_BIT(18 - GC_ARENA_SHIFT)
+
+JS_STATIC_ASSERT(GC_ARENAS_PER_CPU_PAGE_LIMIT <= NO_FREE_ARENAS);
+
+#endif
+
+JSBool
+js_InitGC(JSRuntime *rt, uint32 maxbytes)
+{
+#if JS_GC_USE_MMAP
+ if (js_gcArenasPerChunk == 0) {
+ size_t cpuPageSize, arenasPerPage;
+# if defined(XP_WIN)
+ SYSTEM_INFO si;
+
+ GetSystemInfo(&si);
+ cpuPageSize = si.dwPageSize;
+
+# elif defined(XP_UNIX) || defined(XP_BEOS)
+ cpuPageSize = (size_t) sysconf(_SC_PAGESIZE);
+# else
+# error "Not implemented"
+# endif
+ /* cpuPageSize is a power of 2. */
+ JS_ASSERT((cpuPageSize & (cpuPageSize - 1)) == 0);
+ arenasPerPage = cpuPageSize >> GC_ARENA_SHIFT;
+#ifdef DEBUG
+ if (arenasPerPage == 0) {
+ fprintf(stderr,
+"JS engine warning: the size of the CPU page, %u bytes, is too low to use\n"
+"paged allocation for the garbage collector. Please report this.\n",
+ (unsigned) cpuPageSize);
+ }
+#endif
+ if (arenasPerPage - 1 <= (size_t) (GC_ARENAS_PER_CPU_PAGE_LIMIT - 1)) {
+ /*
+ * Use at least 4 GC arenas per paged allocation chunk to minimize
+ * the overhead of mmap/VirtualAlloc.
+ */
+ js_gcUseMmap = JS_TRUE;
+ js_gcArenasPerChunk = JS_MAX((uint32) arenasPerPage, 4);
+ } else {
+ js_gcUseMmap = JS_FALSE;
+ js_gcArenasPerChunk = 7;
+ }
+ }
+ JS_ASSERT(1 <= js_gcArenasPerChunk &&
+ js_gcArenasPerChunk <= NO_FREE_ARENAS);
+#endif
+
+ InitGCArenaLists(rt);
+ if (!JS_DHashTableInit(&rt->gcRootsHash, JS_DHashGetStubOps(), NULL,
+ sizeof(JSGCRootHashEntry), GC_ROOTS_SIZE)) {
+ rt->gcRootsHash.ops = NULL;
+ return JS_FALSE;
+ }
+ rt->gcLocksHash = NULL; /* create lazily */
+
+ /*
+ * Separate gcMaxMallocBytes from gcMaxBytes but initialize to maxbytes
+ * for default backward API compatibility.
+ */
+ rt->gcMaxBytes = rt->gcMaxMallocBytes = maxbytes;
+ rt->gcEmptyArenaPoolLifespan = 30000;
+
+ METER(memset(&rt->gcStats, 0, sizeof rt->gcStats));
+ return JS_TRUE;
+}
+
+#ifdef JS_GCMETER
+
+static void
+UpdateArenaStats(JSGCArenaStats *st, uint32 nlivearenas, uint32 nkilledArenas,
+ uint32 nthings)
+{
+ size_t narenas;
+
+ narenas = nlivearenas + nkilledArenas;
+ JS_ASSERT(narenas >= st->livearenas);
+
+ st->newarenas = narenas - st->livearenas;
+ st->narenas = narenas;
+ st->livearenas = nlivearenas;
+ if (st->maxarenas < narenas)
+ st->maxarenas = narenas;
+ st->totalarenas += narenas;
+
+ st->nthings = nthings;
+ if (st->maxthings < nthings)
+ st->maxthings = nthings;
+ st->totalthings += nthings;
+}
+
+JS_FRIEND_API(void)
+js_DumpGCStats(JSRuntime *rt, FILE *fp)
+{
+ int i;
+ size_t sumArenas, sumTotalArenas;
+ size_t sumThings, sumMaxThings;
+ size_t sumThingSize, sumTotalThingSize;
+ size_t sumArenaCapacity, sumTotalArenaCapacity;
+ JSGCArenaStats *st;
+ size_t thingSize, thingsPerArena;
+ size_t sumAlloc, sumLocalAlloc, sumFail, sumRetry;
+
+ fprintf(fp, "\nGC allocation statistics:\n");
+
+#define UL(x) ((unsigned long)(x))
+#define ULSTAT(x) UL(rt->gcStats.x)
+#define PERCENT(x,y) (100.0 * (double) (x) / (double) (y))
+
+ sumArenas = 0;
+ sumTotalArenas = 0;
+ sumThings = 0;
+ sumMaxThings = 0;
+ sumThingSize = 0;
+ sumTotalThingSize = 0;
+ sumArenaCapacity = 0;
+ sumTotalArenaCapacity = 0;
+ sumAlloc = 0;
+ sumLocalAlloc = 0;
+ sumFail = 0;
+ sumRetry = 0;
+ for (i = -1; i < (int) GC_NUM_FREELISTS; i++) {
+ if (i == -1) {
+ thingSize = sizeof(jsdouble);
+ thingsPerArena = DOUBLES_PER_ARENA;
+ st = &rt->gcStats.doubleArenaStats;
+ fprintf(fp,
+ "Arena list for double values (%lu doubles per arena):",
+ UL(thingsPerArena));
+ } else {
+ thingSize = rt->gcArenaList[i].thingSize;
+ thingsPerArena = THINGS_PER_ARENA(thingSize);
+ st = &rt->gcStats.arenaStats[i];
+ fprintf(fp,
+ "Arena list %d (thing size %lu, %lu things per arena):",
+ i, UL(GC_FREELIST_NBYTES(i)), UL(thingsPerArena));
+ }
+ if (st->maxarenas == 0) {
+ fputs(" NEVER USED\n", fp);
+ continue;
+ }
+ putc('\n', fp);
+ fprintf(fp, " arenas before GC: %lu\n", UL(st->narenas));
+ fprintf(fp, " new arenas before GC: %lu (%.1f%%)\n",
+ UL(st->newarenas), PERCENT(st->newarenas, st->narenas));
+ fprintf(fp, " arenas after GC: %lu (%.1f%%)\n",
+ UL(st->livearenas), PERCENT(st->livearenas, st->narenas));
+ fprintf(fp, " max arenas: %lu\n", UL(st->maxarenas));
+ fprintf(fp, " things: %lu\n", UL(st->nthings));
+ fprintf(fp, " GC cell utilization: %.1f%%\n",
+ PERCENT(st->nthings, thingsPerArena * st->narenas));
+ fprintf(fp, " average cell utilization: %.1f%%\n",
+ PERCENT(st->totalthings, thingsPerArena * st->totalarenas));
+ fprintf(fp, " max things: %lu\n", UL(st->maxthings));
+ fprintf(fp, " alloc attempts: %lu\n", UL(st->alloc));
+ fprintf(fp, " alloc without locks: %1u (%.1f%%)\n",
+ UL(st->localalloc), PERCENT(st->localalloc, st->alloc));
+ sumArenas += st->narenas;
+ sumTotalArenas += st->totalarenas;
+ sumThings += st->nthings;
+ sumMaxThings += st->maxthings;
+ sumThingSize += thingSize * st->nthings;
+ sumTotalThingSize += thingSize * st->totalthings;
+ sumArenaCapacity += thingSize * thingsPerArena * st->narenas;
+ sumTotalArenaCapacity += thingSize * thingsPerArena * st->totalarenas;
+ sumAlloc += st->alloc;
+ sumLocalAlloc += st->localalloc;
+ sumFail += st->fail;
+ sumRetry += st->retry;
+ }
+ fprintf(fp, "TOTAL STATS:\n");
+ fprintf(fp, " bytes allocated: %lu\n", UL(rt->gcBytes));
+ fprintf(fp, " total GC arenas: %lu\n", UL(sumArenas));
+ fprintf(fp, " total GC things: %lu\n", UL(sumThings));
+ fprintf(fp, " max total GC things: %lu\n", UL(sumMaxThings));
+ fprintf(fp, " GC cell utilization: %.1f%%\n",
+ PERCENT(sumThingSize, sumArenaCapacity));
+ fprintf(fp, " average cell utilization: %.1f%%\n",
+ PERCENT(sumTotalThingSize, sumTotalArenaCapacity));
+ fprintf(fp, "allocation retries after GC: %lu\n", UL(sumRetry));
+ fprintf(fp, " alloc attempts: %lu\n", UL(sumAlloc));
+ fprintf(fp, " alloc without locks: %1u (%.1f%%)\n",
+ UL(sumLocalAlloc), PERCENT(sumLocalAlloc, sumAlloc));
+ fprintf(fp, " allocation failures: %lu\n", UL(sumFail));
+ fprintf(fp, " things born locked: %lu\n", ULSTAT(lockborn));
+ fprintf(fp, " valid lock calls: %lu\n", ULSTAT(lock));
+ fprintf(fp, " valid unlock calls: %lu\n", ULSTAT(unlock));
+ fprintf(fp, " mark recursion depth: %lu\n", ULSTAT(depth));
+ fprintf(fp, " maximum mark recursion: %lu\n", ULSTAT(maxdepth));
+ fprintf(fp, " mark C recursion depth: %lu\n", ULSTAT(cdepth));
+ fprintf(fp, " maximum mark C recursion: %lu\n", ULSTAT(maxcdepth));
+ fprintf(fp, " delayed tracing calls: %lu\n", ULSTAT(untraced));
+#ifdef DEBUG
+ fprintf(fp, " max trace later count: %lu\n", ULSTAT(maxuntraced));
+#endif
+ fprintf(fp, " maximum GC nesting level: %lu\n", ULSTAT(maxlevel));
+ fprintf(fp, "potentially useful GC calls: %lu\n", ULSTAT(poke));
+ fprintf(fp, " thing arenas freed so far: %lu\n", ULSTAT(afree));
+ fprintf(fp, " stack segments scanned: %lu\n", ULSTAT(stackseg));
+ fprintf(fp, "stack segment slots scanned: %lu\n", ULSTAT(segslots));
+ fprintf(fp, "reachable closeable objects: %lu\n", ULSTAT(nclose));
+ fprintf(fp, " max reachable closeable: %lu\n", ULSTAT(maxnclose));
+ fprintf(fp, " scheduled close hooks: %lu\n", ULSTAT(closelater));
+ fprintf(fp, " max scheduled close hooks: %lu\n", ULSTAT(maxcloselater));
+
+#undef UL
+#undef ULSTAT
+#undef PERCENT
+
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(fp);
+#endif
+}
+#endif
+
+#ifdef DEBUG
+static void
+CheckLeakedRoots(JSRuntime *rt);
+#endif
+
+#ifdef JS_THREADSAFE
+static void
+TrimGCFreeListsPool(JSRuntime *rt, uintN keepCount);
+#endif
+
+void
+js_FinishGC(JSRuntime *rt)
+{
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(stdout);
+#endif
+#ifdef JS_GCMETER
+ js_DumpGCStats(rt, stdout);
+#endif
+
+ FreePtrTable(&rt->gcIteratorTable, &iteratorTableInfo);
+#ifdef JS_THREADSAFE
+ TrimGCFreeListsPool(rt, 0);
+ JS_ASSERT(!rt->gcFreeListsPool);
+#endif
+ FinishGCArenaLists(rt);
+
+ if (rt->gcRootsHash.ops) {
+#ifdef DEBUG
+ CheckLeakedRoots(rt);
+#endif
+ JS_DHashTableFinish(&rt->gcRootsHash);
+ rt->gcRootsHash.ops = NULL;
+ }
+ if (rt->gcLocksHash) {
+ JS_DHashTableDestroy(rt->gcLocksHash);
+ rt->gcLocksHash = NULL;
+ }
+}
+
+JSBool
+js_AddRoot(JSContext *cx, void *rp, const char *name)
+{
+ JSBool ok = js_AddRootRT(cx->runtime, rp, name);
+ if (!ok)
+ JS_ReportOutOfMemory(cx);
+ return ok;
+}
+
+JSBool
+js_AddRootRT(JSRuntime *rt, void *rp, const char *name)
+{
+ JSBool ok;
+ JSGCRootHashEntry *rhe;
+
+ /*
+ * Due to the long-standing, but now removed, use of rt->gcLock across the
+ * bulk of js_GC, API users have come to depend on JS_AddRoot etc. locking
+ * properly with a racing GC, without calling JS_AddRoot from a request.
+ * We have to preserve API compatibility here, now that we avoid holding
+ * rt->gcLock across the mark phase (including the root hashtable mark).
+ *
+ * If the GC is running and we're called on another thread, wait for this
+ * GC activation to finish. We can safely wait here (in the case where we
+ * are called within a request on another thread's context) without fear
+ * of deadlock because the GC doesn't set rt->gcRunning until after it has
+ * waited for all active requests to end.
+ */
+ JS_LOCK_GC(rt);
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0);
+ if (rt->gcRunning && rt->gcThread->id != js_CurrentThreadId()) {
+ do {
+ JS_AWAIT_GC_DONE(rt);
+ } while (rt->gcLevel > 0);
+ }
+#endif
+ rhe = (JSGCRootHashEntry *)
+ JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_ADD);
+ if (rhe) {
+ rhe->root = rp;
+ rhe->name = name;
+ ok = JS_TRUE;
+ } else {
+ ok = JS_FALSE;
+ }
+ JS_UNLOCK_GC(rt);
+ return ok;
+}
+
+JSBool
+js_RemoveRoot(JSRuntime *rt, void *rp)
+{
+ /*
+ * Due to the JS_RemoveRootRT API, we may be called outside of a request.
+ * Same synchronization drill as above in js_AddRoot.
+ */
+ JS_LOCK_GC(rt);
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->gcRunning || rt->gcLevel > 0);
+ if (rt->gcRunning && rt->gcThread->id != js_CurrentThreadId()) {
+ do {
+ JS_AWAIT_GC_DONE(rt);
+ } while (rt->gcLevel > 0);
+ }
+#endif
+ (void) JS_DHashTableOperate(&rt->gcRootsHash, rp, JS_DHASH_REMOVE);
+ rt->gcPoke = JS_TRUE;
+ JS_UNLOCK_GC(rt);
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+static JSDHashOperator
+js_root_printer(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 i, void *arg)
+{
+ uint32 *leakedroots = (uint32 *)arg;
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+
+ (*leakedroots)++;
+ fprintf(stderr,
+ "JS engine warning: leaking GC root \'%s\' at %p\n",
+ rhe->name ? (char *)rhe->name : "", rhe->root);
+
+ return JS_DHASH_NEXT;
+}
+
+static void
+CheckLeakedRoots(JSRuntime *rt)
+{
+ uint32 leakedroots = 0;
+
+ /* Warn (but don't assert) debug builds of any remaining roots. */
+ JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer,
+ &leakedroots);
+ if (leakedroots > 0) {
+ if (leakedroots == 1) {
+ fprintf(stderr,
+"JS engine warning: 1 GC root remains after destroying the JSRuntime at %p.\n"
+" This root may point to freed memory. Objects reachable\n"
+" through it have not been finalized.\n",
+ (void *) rt);
+ } else {
+ fprintf(stderr,
+"JS engine warning: %lu GC roots remain after destroying the JSRuntime at %p.\n"
+" These roots may point to freed memory. Objects reachable\n"
+" through them have not been finalized.\n",
+ (unsigned long) leakedroots, (void *) rt);
+ }
+ }
+}
+
+typedef struct NamedRootDumpArgs {
+ void (*dump)(const char *name, void *rp, void *data);
+ void *data;
+} NamedRootDumpArgs;
+
+static JSDHashOperator
+js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg)
+{
+ NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+
+ if (rhe->name)
+ args->dump(rhe->name, rhe->root, args->data);
+ return JS_DHASH_NEXT;
+}
+
+JS_BEGIN_EXTERN_C
+void
+js_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data)
+{
+ NamedRootDumpArgs args;
+
+ args.dump = dump;
+ args.data = data;
+ JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);
+}
+JS_END_EXTERN_C
+
+#endif /* DEBUG */
+
+typedef struct GCRootMapArgs {
+ JSGCRootMapFun map;
+ void *data;
+} GCRootMapArgs;
+
+static JSDHashOperator
+js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg)
+{
+ GCRootMapArgs *args = (GCRootMapArgs *) arg;
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+ intN mapflags;
+ int op;
+
+ mapflags = args->map(rhe->root, rhe->name, args->data);
+
+#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT && \
+ JS_MAP_GCROOT_STOP == JS_DHASH_STOP && \
+ JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE
+ op = (JSDHashOperator)mapflags;
+#else
+ op = JS_DHASH_NEXT;
+ if (mapflags & JS_MAP_GCROOT_STOP)
+ op |= JS_DHASH_STOP;
+ if (mapflags & JS_MAP_GCROOT_REMOVE)
+ op |= JS_DHASH_REMOVE;
+#endif
+
+ return (JSDHashOperator) op;
+}
+
+uint32
+js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data)
+{
+ GCRootMapArgs args;
+ uint32 rv;
+
+ args.map = map;
+ args.data = data;
+ JS_LOCK_GC(rt);
+ rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);
+ JS_UNLOCK_GC(rt);
+ return rv;
+}
+
+JSBool
+js_RegisterCloseableIterator(JSContext *cx, JSObject *obj)
+{
+ JSRuntime *rt;
+ JSBool ok;
+
+ rt = cx->runtime;
+ JS_ASSERT(!rt->gcRunning);
+
+ JS_LOCK_GC(rt);
+ ok = AddToPtrTable(cx, &rt->gcIteratorTable, &iteratorTableInfo, obj);
+ JS_UNLOCK_GC(rt);
+ return ok;
+}
+
+static void
+CloseNativeIterators(JSContext *cx)
+{
+ JSRuntime *rt;
+ size_t count, newCount, i;
+ void **array;
+ JSObject *obj;
+
+ rt = cx->runtime;
+ count = rt->gcIteratorTable.count;
+ array = rt->gcIteratorTable.array;
+
+ newCount = 0;
+ for (i = 0; i != count; ++i) {
+ obj = (JSObject *)array[i];
+ if (js_IsAboutToBeFinalized(cx, obj))
+ js_CloseNativeIterator(cx, obj);
+ else
+ array[newCount++] = obj;
+ }
+ ShrinkPtrTable(&rt->gcIteratorTable, &iteratorTableInfo, newCount);
+}
+
+#if defined(DEBUG_brendan) || defined(DEBUG_timeless)
+#define DEBUG_gchist
+#endif
+
+#ifdef DEBUG_gchist
+#define NGCHIST 64
+
+static struct GCHist {
+ JSBool lastDitch;
+ JSGCThing *freeList;
+} gchist[NGCHIST];
+
+unsigned gchpos = 0;
+#endif
+
+#ifdef JS_THREADSAFE
+
+const JSGCFreeListSet js_GCEmptyFreeListSet = {
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, NULL
+};
+
+static void
+TrimGCFreeListsPool(JSRuntime *rt, uintN keepCount)
+{
+ JSGCFreeListSet **cursor, *freeLists, *link;
+
+ cursor = &rt->gcFreeListsPool;
+ while (keepCount != 0) {
+ --keepCount;
+ freeLists = *cursor;
+ if (!freeLists)
+ return;
+ memset(freeLists->array, 0, sizeof freeLists->array);
+ cursor = &freeLists->link;
+ }
+ freeLists = *cursor;
+ if (freeLists) {
+ *cursor = NULL;
+ do {
+ link = freeLists->link;
+ free(freeLists);
+ } while ((freeLists = link) != NULL);
+ }
+}
+
+void
+js_RevokeGCLocalFreeLists(JSContext *cx)
+{
+ JS_ASSERT(!cx->gcLocalFreeLists->link);
+ if (cx->gcLocalFreeLists != &js_GCEmptyFreeListSet) {
+ cx->gcLocalFreeLists->link = cx->runtime->gcFreeListsPool;
+ cx->runtime->gcFreeListsPool = cx->gcLocalFreeLists;
+ cx->gcLocalFreeLists = (JSGCFreeListSet *) &js_GCEmptyFreeListSet;
+ }
+}
+
+static JSGCFreeListSet *
+EnsureLocalFreeList(JSContext *cx)
+{
+ JSGCFreeListSet *freeLists;
+
+ freeLists = cx->gcLocalFreeLists;
+ if (freeLists != &js_GCEmptyFreeListSet) {
+ JS_ASSERT(freeLists);
+ return freeLists;
+ }
+
+ freeLists = cx->runtime->gcFreeListsPool;
+ if (freeLists) {
+ cx->runtime->gcFreeListsPool = freeLists->link;
+ freeLists->link = NULL;
+ } else {
+ /* JS_malloc is not used as the caller reports out-of-memory itself. */
+ freeLists = (JSGCFreeListSet *) calloc(1, sizeof *freeLists);
+ if (!freeLists)
+ return NULL;
+ }
+ cx->gcLocalFreeLists = freeLists;
+ return freeLists;
+}
+
+#endif
+
+void *
+js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
+{
+ JSRuntime *rt;
+ uintN flindex;
+ JSBool doGC;
+ JSGCThing *thing;
+ uint8 *flagp;
+ JSGCArenaList *arenaList;
+ JSGCArenaInfo *a;
+ uintN thingsLimit;
+ JSLocalRootStack *lrs;
+#ifdef JS_GCMETER
+ JSGCArenaStats *astats;
+#endif
+#ifdef JS_THREADSAFE
+ JSBool gcLocked;
+ uintN localMallocBytes;
+ JSGCFreeListSet *freeLists;
+ JSGCThing **lastptr;
+ JSGCThing *tmpthing;
+ uint8 *tmpflagp;
+ uintN maxFreeThings; /* max to take from the global free list */
+#endif
+
+ JS_ASSERT((flags & GCF_TYPEMASK) != GCX_DOUBLE);
+ rt = cx->runtime;
+ nbytes = JS_ROUNDUP(nbytes, sizeof(JSGCThing));
+ flindex = GC_FREELIST_INDEX(nbytes);
+
+ /* Updates of metering counters here may not be thread-safe. */
+ METER(astats = &cx->runtime->gcStats.arenaStats[flindex]);
+ METER(astats->alloc++);
+
+#ifdef JS_THREADSAFE
+ gcLocked = JS_FALSE;
+ JS_ASSERT(cx->thread);
+ freeLists = cx->gcLocalFreeLists;
+ thing = freeLists->array[flindex];
+ localMallocBytes = cx->thread->gcMallocBytes;
+ if (thing && rt->gcMaxMallocBytes - rt->gcMallocBytes > localMallocBytes) {
+ flagp = thing->flagp;
+ freeLists->array[flindex] = thing->next;
+ METER(astats->localalloc++);
+ goto success;
+ }
+
+ JS_LOCK_GC(rt);
+ gcLocked = JS_TRUE;
+
+ /* Transfer thread-local counter to global one. */
+ if (localMallocBytes != 0) {
+ cx->thread->gcMallocBytes = 0;
+ if (rt->gcMaxMallocBytes - rt->gcMallocBytes < localMallocBytes)
+ rt->gcMallocBytes = rt->gcMaxMallocBytes;
+ else
+ rt->gcMallocBytes += localMallocBytes;
+ }
+#endif
+ JS_ASSERT(!rt->gcRunning);
+ if (rt->gcRunning) {
+ METER(rt->gcStats.finalfail++);
+ JS_UNLOCK_GC(rt);
+ return NULL;
+ }
+
+ doGC = (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke);
+#ifdef JS_GC_ZEAL
+ doGC = doGC || rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke);
+#endif
+
+ arenaList = &rt->gcArenaList[flindex];
+ for (;;) {
+ if (doGC && !JS_ON_TRACE(cx)) {
+ /*
+ * Keep rt->gcLock across the call into js_GC so we don't starve
+ * and lose to racing threads who deplete the heap just after
+ * js_GC has replenished it (or has synchronized with a racing
+ * GC that collected a bunch of garbage). This unfair scheduling
+ * can happen on certain operating systems. For the gory details,
+ * see bug 162779 at https://bugzilla.mozilla.org/.
+ */
+ js_GC(cx, GC_LAST_DITCH);
+ METER(astats->retry++);
+ }
+
+ /* Try to get thing from the free list. */
+ thing = arenaList->freeList;
+ if (thing) {
+ arenaList->freeList = thing->next;
+ flagp = thing->flagp;
+ JS_ASSERT(*flagp & GCF_FINAL);
+
+#ifdef JS_THREADSAFE
+ /*
+ * Refill the local free list by taking several things from the
+ * global free list unless we are still at rt->gcMaxMallocBytes
+ * barrier or the free list is already populated. The former
+ * happens when GC is canceled due to !gcCallback(cx, JSGC_BEGIN)
+ * or no gcPoke. The latter is caused via allocating new things
+ * in gcCallback(cx, JSGC_END).
+ */
+ if (rt->gcMallocBytes >= rt->gcMaxMallocBytes)
+ break;
+
+ freeLists = EnsureLocalFreeList(cx);
+ if (!freeLists)
+ goto fail;
+ if (freeLists->array[flindex])
+ break;
+
+ tmpthing = arenaList->freeList;
+ if (tmpthing) {
+ maxFreeThings = MAX_THREAD_LOCAL_THINGS;
+ do {
+ if (!tmpthing->next)
+ break;
+ tmpthing = tmpthing->next;
+ } while (--maxFreeThings != 0);
+
+ freeLists->array[flindex] = arenaList->freeList;
+ arenaList->freeList = tmpthing->next;
+ tmpthing->next = NULL;
+ }
+#endif
+ break;
+ }
+
+ /*
+ * Try to allocate things from the last arena. If it is fully used,
+ * check if we can allocate a new one and, if we cannot, consider
+ * doing a "last ditch" GC unless already tried.
+ */
+ thingsLimit = THINGS_PER_ARENA(nbytes);
+ if (arenaList->lastCount != thingsLimit) {
+ JS_ASSERT(arenaList->lastCount < thingsLimit);
+ a = arenaList->last;
+ } else {
+ a = NewGCArena(rt);
+ if (!a) {
+ if (doGC || JS_ON_TRACE(cx))
+ goto fail;
+ doGC = JS_TRUE;
+ continue;
+ }
+ a->list = arenaList;
+ a->prev = arenaList->last;
+ a->prevUntracedPage = 0;
+ a->u.untracedThings = 0;
+ arenaList->last = a;
+ arenaList->lastCount = 0;
+ }
+
+ flagp = THING_FLAGP(a, arenaList->lastCount);
+ thing = FLAGP_TO_THING(flagp, nbytes);
+ arenaList->lastCount++;
+
+#ifdef JS_THREADSAFE
+ /*
+ * Refill the local free list by taking free things from the last
+ * arena. Prefer to order free things by ascending address in the
+ * (unscientific) hope of better cache locality.
+ */
+ if (rt->gcMallocBytes >= rt->gcMaxMallocBytes)
+ break;
+
+ freeLists = EnsureLocalFreeList(cx);
+ if (!freeLists)
+ goto fail;
+ if (freeLists->array[flindex])
+ break;
+ lastptr = &freeLists->array[flindex];
+ maxFreeThings = thingsLimit - arenaList->lastCount;
+ if (maxFreeThings > MAX_THREAD_LOCAL_THINGS)
+ maxFreeThings = MAX_THREAD_LOCAL_THINGS;
+ while (maxFreeThings != 0) {
+ --maxFreeThings;
+
+ tmpflagp = THING_FLAGP(a, arenaList->lastCount);
+ tmpthing = FLAGP_TO_THING(tmpflagp, nbytes);
+ arenaList->lastCount++;
+ tmpthing->flagp = tmpflagp;
+ *tmpflagp = GCF_FINAL; /* signifying that thing is free */
+
+ *lastptr = tmpthing;
+ lastptr = &tmpthing->next;
+ }
+ *lastptr = NULL;
+#endif
+ break;
+ }
+
+ /* We successfully allocated the thing. */
+#ifdef JS_THREADSAFE
+ success:
+#endif
+ lrs = cx->localRootStack;
+ if (lrs) {
+ /*
+ * If we're in a local root scope, don't set newborn[type] at all, to
+ * avoid entraining garbage from it for an unbounded amount of time
+ * on this context. A caller will leave the local root scope and pop
+ * this reference, allowing thing to be GC'd if it has no other refs.
+ * See JS_EnterLocalRootScope and related APIs.
+ */
+ if (js_PushLocalRoot(cx, lrs, (jsval) thing) < 0) {
+ /*
+ * When we fail for a thing allocated through the tail of the last
+ * arena, thing's flag byte is not initialized. So to prevent GC
+ * accessing the uninitialized flags during the finalization, we
+ * always mark the thing as final. See bug 337407.
+ */
+ *flagp = GCF_FINAL;
+ goto fail;
+ }
+ } else {
+ /*
+ * No local root scope, so we're stuck with the old, fragile model of
+ * depending on a pigeon-hole newborn per type per context.
+ */
+ cx->weakRoots.newborn[flags & GCF_TYPEMASK] = thing;
+ }
+
+ /* We can't fail now, so update flags. */
+ *flagp = (uint8)flags;
+
+#ifdef DEBUG_gchist
+ gchist[gchpos].lastDitch = doGC;
+ gchist[gchpos].freeList = rt->gcArenaList[flindex].freeList;
+ if (++gchpos == NGCHIST)
+ gchpos = 0;
+#endif
+
+ /* This is not thread-safe for thread-local allocations. */
+ METER_IF(flags & GCF_LOCK, rt->gcStats.lockborn++);
+
+#ifdef JS_THREADSAFE
+ if (gcLocked)
+ JS_UNLOCK_GC(rt);
+#endif
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION);
+ return thing;
+
+fail:
+#ifdef JS_THREADSAFE
+ if (gcLocked)
+ JS_UNLOCK_GC(rt);
+#endif
+ METER(astats->fail++);
+ if (!JS_ON_TRACE(cx))
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+static JSGCDoubleCell *
+RefillDoubleFreeList(JSContext *cx)
+{
+ JSRuntime *rt;
+ jsbitmap *doubleFlags, usedBits;
+ JSBool didGC = JS_FALSE;
+ JSGCArenaInfo *a;
+ uintN bit, index;
+ JSGCDoubleCell *cell, *list, *lastcell;
+
+ JS_ASSERT(!cx->doubleFreeList);
+
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+
+ JS_ASSERT(!rt->gcRunning);
+ if (rt->gcRunning) {
+ METER(rt->gcStats.finalfail++);
+ JS_UNLOCK_GC(rt);
+ return NULL;
+ }
+
+ if (rt->gcMallocBytes >= rt->gcMaxMallocBytes && rt->gcPoke
+#ifdef JS_GC_ZEAL
+ && (rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke))
+#endif
+ ) {
+ goto do_gc;
+ }
+
+ /*
+ * Loop until we find a flag bitmap byte with unset bits indicating free
+ * double cells, then set all bits as used and put the cells to the free
+ * list for the current context.
+ */
+ doubleFlags = rt->gcDoubleArenaList.nextDoubleFlags;
+ for (;;) {
+ if (((jsuword) doubleFlags & GC_ARENA_MASK) ==
+ ARENA_INFO_OFFSET) {
+ if (doubleFlags == DOUBLE_BITMAP_SENTINEL ||
+ !((JSGCArenaInfo *) doubleFlags)->prev) {
+ a = NewGCArena(rt);
+ if (!a) {
+ do_gc:
+ if (didGC || JS_ON_TRACE(cx)) {
+ METER(rt->gcStats.doubleArenaStats.fail++);
+ JS_UNLOCK_GC(rt);
+ if (!JS_ON_TRACE(cx))
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ js_GC(cx, GC_LAST_DITCH);
+ METER(rt->gcStats.doubleArenaStats.retry++);
+ doubleFlags = rt->gcDoubleArenaList.nextDoubleFlags;
+ didGC = JS_TRUE;
+ continue;
+ }
+ a->list = NULL;
+ a->prev = NULL;
+ if (doubleFlags == DOUBLE_BITMAP_SENTINEL) {
+ JS_ASSERT(!rt->gcDoubleArenaList.first);
+ rt->gcDoubleArenaList.first = a;
+ } else {
+ JS_ASSERT(rt->gcDoubleArenaList.first);
+ ((JSGCArenaInfo *) doubleFlags)->prev = a;
+ }
+ ClearDoubleArenaFlags(a);
+ doubleFlags = DOUBLE_ARENA_BITMAP(a);
+ break;
+ }
+ doubleFlags =
+ DOUBLE_ARENA_BITMAP(((JSGCArenaInfo *) doubleFlags)->prev);
+ }
+
+ /*
+ * When doubleFlags points the last bitmap's word in the arena, its
+ * high bits corresponds to non-existing cells. ClearDoubleArenaFlags
+ * sets such bits to 1. Thus even for this last word its bit is unset
+ * iff the corresponding cell exists and free.
+ */
+ if (*doubleFlags != (jsbitmap) -1)
+ break;
+ ++doubleFlags;
+ }
+
+ rt->gcDoubleArenaList.nextDoubleFlags = doubleFlags + 1;
+ usedBits = *doubleFlags;
+ JS_ASSERT(usedBits != (jsbitmap) -1);
+ *doubleFlags = (jsbitmap) -1;
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * Find the index corresponding to the first bit in *doubleFlags. The last
+ * bit will have "index + JS_BITS_PER_WORD - 1".
+ */
+ index = ((uintN) ((jsuword) doubleFlags & GC_ARENA_MASK) -
+ DOUBLES_ARENA_BITMAP_OFFSET) * JS_BITS_PER_BYTE;
+ cell = (JSGCDoubleCell *) ((jsuword) doubleFlags & ~GC_ARENA_MASK) + index;
+
+ if (usedBits == 0) {
+ /* The common case when all doubles from *doubleFlags are free. */
+ JS_ASSERT(index + JS_BITS_PER_WORD <= DOUBLES_PER_ARENA);
+ list = cell;
+ for (lastcell = cell + JS_BITS_PER_WORD - 1; cell != lastcell; ++cell)
+ cell->link = cell + 1;
+ lastcell->link = NULL;
+ } else {
+ /*
+ * Assemble the free list from free cells from *doubleFlags starting
+ * from the tail. In the loop
+ *
+ * index + bit >= DOUBLES_PER_ARENA
+ *
+ * when bit is one of the unused bits. We do not check for such bits
+ * explicitly as they must be set and the "if" check filters them out.
+ */
+ JS_ASSERT(index + JS_BITS_PER_WORD <=
+ DOUBLES_PER_ARENA + UNUSED_DOUBLE_BITMAP_BITS);
+ bit = JS_BITS_PER_WORD;
+ cell += bit;
+ list = NULL;
+ do {
+ --bit;
+ --cell;
+ if (!(((jsbitmap) 1 << bit) & usedBits)) {
+ JS_ASSERT(index + bit < DOUBLES_PER_ARENA);
+ JS_ASSERT_IF(index + bit == DOUBLES_PER_ARENA - 1, !list);
+ cell->link = list;
+ list = cell;
+ }
+ } while (bit != 0);
+ }
+ JS_ASSERT(list);
+ JS_COUNT_OPERATION(cx, JSOW_ALLOCATION * JS_BITS_PER_WORD);
+
+ /*
+ * We delegate assigning cx->doubleFreeList to js_NewDoubleInRootedValue as
+ * it immediately consumes the head of the list.
+ */
+ return list;
+}
+
+JSBool
+js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
+{
+#ifdef JS_GCMETER
+ JSGCArenaStats *astats;
+#endif
+ JSGCDoubleCell *cell;
+
+ /* Updates of metering counters here are not thread-safe. */
+ METER(astats = &cx->runtime->gcStats.doubleArenaStats);
+ METER(astats->alloc++);
+ cell = cx->doubleFreeList;
+ if (!cell) {
+ cell = RefillDoubleFreeList(cx);
+ if (!cell) {
+ METER(astats->fail++);
+ return JS_FALSE;
+ }
+ } else {
+ METER(astats->localalloc++);
+ }
+ cx->doubleFreeList = cell->link;
+ cell->number = d;
+ *vp = DOUBLE_TO_JSVAL(&cell->number);
+ return JS_TRUE;
+}
+
+jsdouble *
+js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d)
+{
+ jsval v;
+ jsdouble *dp;
+
+ if (!js_NewDoubleInRootedValue(cx, d, &v))
+ return NULL;
+
+ JS_ASSERT(JSVAL_IS_DOUBLE(v));
+ dp = JSVAL_TO_DOUBLE(v);
+ if (cx->localRootStack) {
+ if (js_PushLocalRoot(cx, cx->localRootStack, v) < 0)
+ return NULL;
+ } else {
+ cx->weakRoots.newborn[GCX_DOUBLE] = dp;
+ }
+ return dp;
+}
+
+JSBool
+js_AddAsGCBytes(JSContext *cx, size_t sz)
+{
+ JSRuntime *rt;
+
+ rt = cx->runtime;
+ if (rt->gcBytes >= rt->gcMaxBytes ||
+ sz > (size_t) (rt->gcMaxBytes - rt->gcBytes)
+#ifdef JS_GC_ZEAL
+ || rt->gcZeal >= 2 || (rt->gcZeal >= 1 && rt->gcPoke)
+#endif
+ ) {
+ if (JS_ON_TRACE(cx)) {
+ JS_UNLOCK_GC(rt);
+ return JS_FALSE;
+ }
+ js_GC(cx, GC_LAST_DITCH);
+ if (rt->gcBytes >= rt->gcMaxBytes ||
+ sz > (size_t) (rt->gcMaxBytes - rt->gcBytes)) {
+ JS_UNLOCK_GC(rt);
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ }
+ rt->gcBytes += (uint32) sz;
+ return JS_TRUE;
+}
+
+void
+js_RemoveAsGCBytes(JSRuntime *rt, size_t sz)
+{
+ JS_ASSERT((size_t) rt->gcBytes >= sz);
+ rt->gcBytes -= (uint32) sz;
+}
+
+/*
+ * Shallow GC-things can be locked just by setting the GCF_LOCK bit, because
+ * they have no descendants to mark during the GC. Currently the optimization
+ * is only used for non-dependant strings.
+ */
+#define GC_THING_IS_SHALLOW(flagp, thing) \
+ ((flagp) && \
+ ((*(flagp) & GCF_TYPEMASK) >= GCX_EXTERNAL_STRING || \
+ ((*(flagp) & GCF_TYPEMASK) == GCX_STRING && \
+ !JSSTRING_IS_DEPENDENT((JSString *) (thing)))))
+
+/* This is compatible with JSDHashEntryStub. */
+typedef struct JSGCLockHashEntry {
+ JSDHashEntryHdr hdr;
+ const void *thing;
+ uint32 count;
+} JSGCLockHashEntry;
+
+JSBool
+js_LockGCThingRT(JSRuntime *rt, void *thing)
+{
+ JSBool shallow, ok;
+ uint8 *flagp;
+ JSGCLockHashEntry *lhe;
+
+ if (!thing)
+ return JS_TRUE;
+
+ flagp = GetGCThingFlagsOrNull(thing);
+ JS_LOCK_GC(rt);
+ shallow = GC_THING_IS_SHALLOW(flagp, thing);
+
+ /*
+ * Avoid adding a rt->gcLocksHash entry for shallow things until someone
+ * nests a lock.
+ */
+ if (shallow && !(*flagp & GCF_LOCK)) {
+ *flagp |= GCF_LOCK;
+ METER(rt->gcStats.lock++);
+ ok = JS_TRUE;
+ goto out;
+ }
+
+ if (!rt->gcLocksHash) {
+ rt->gcLocksHash = JS_NewDHashTable(JS_DHashGetStubOps(), NULL,
+ sizeof(JSGCLockHashEntry),
+ GC_ROOTS_SIZE);
+ if (!rt->gcLocksHash) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+
+ lhe = (JSGCLockHashEntry *)
+ JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_ADD);
+ if (!lhe) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ if (!lhe->thing) {
+ lhe->thing = thing;
+ lhe->count = 1;
+ } else {
+ JS_ASSERT(lhe->count >= 1);
+ lhe->count++;
+ }
+
+ METER(rt->gcStats.lock++);
+ ok = JS_TRUE;
+ out:
+ JS_UNLOCK_GC(rt);
+ return ok;
+}
+
+JSBool
+js_UnlockGCThingRT(JSRuntime *rt, void *thing)
+{
+ uint8 *flagp;
+ JSBool shallow;
+ JSGCLockHashEntry *lhe;
+
+ if (!thing)
+ return JS_TRUE;
+
+ flagp = GetGCThingFlagsOrNull(thing);
+ JS_LOCK_GC(rt);
+ shallow = GC_THING_IS_SHALLOW(flagp, thing);
+
+ if (shallow && !(*flagp & GCF_LOCK))
+ goto out;
+ if (!rt->gcLocksHash ||
+ (lhe = (JSGCLockHashEntry *)
+ JS_DHashTableOperate(rt->gcLocksHash, thing,
+ JS_DHASH_LOOKUP),
+ JS_DHASH_ENTRY_IS_FREE(&lhe->hdr))) {
+ /* Shallow entry is not in the hash -> clear its lock bit. */
+ if (shallow)
+ *flagp &= ~GCF_LOCK;
+ else
+ goto out;
+ } else {
+ if (--lhe->count != 0)
+ goto out;
+ JS_DHashTableOperate(rt->gcLocksHash, thing, JS_DHASH_REMOVE);
+ }
+
+ rt->gcPoke = JS_TRUE;
+ METER(rt->gcStats.unlock++);
+ out:
+ JS_UNLOCK_GC(rt);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void)
+JS_TraceChildren(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSObject *obj;
+ size_t nslots, i;
+ jsval v;
+ JSString *str;
+
+ switch (kind) {
+ case JSTRACE_OBJECT:
+ /* If obj has no map, it must be a newborn. */
+ obj = (JSObject *) thing;
+ if (!obj->map)
+ break;
+ if (obj->map->ops->trace) {
+ obj->map->ops->trace(trc, obj);
+ } else {
+ nslots = STOBJ_NSLOTS(obj);
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_INDEX(trc, "slot", i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v),
+ JSVAL_TRACE_KIND(v));
+ }
+ }
+ }
+ break;
+
+ case JSTRACE_STRING:
+ str = (JSString *)thing;
+ if (JSSTRING_IS_DEPENDENT(str))
+ JS_CALL_STRING_TRACER(trc, JSSTRDEP_BASE(str), "base");
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSTRACE_XML:
+ js_TraceXML(trc, (JSXML *)thing);
+ break;
+#endif
+ }
+}
+
+/*
+ * Number of things covered by a single bit of JSGCArenaInfo.u.untracedThings.
+ */
+#define THINGS_PER_UNTRACED_BIT(thingSize) \
+ JS_HOWMANY(THINGS_PER_ARENA(thingSize), JS_BITS_PER_WORD)
+
+static void
+DelayTracingChildren(JSRuntime *rt, uint8 *flagp)
+{
+ JSGCArenaInfo *a;
+ uint32 untracedBitIndex;
+ jsuword bit;
+
+ /*
+ * Things with children to be traced later are marked with
+ * GCF_MARK | GCF_FINAL flags.
+ */
+ JS_ASSERT((*flagp & (GCF_MARK | GCF_FINAL)) == GCF_MARK);
+ *flagp |= GCF_FINAL;
+
+ METER(rt->gcStats.untraced++);
+#ifdef DEBUG
+ ++rt->gcTraceLaterCount;
+ METER_UPDATE_MAX(rt->gcStats.maxuntraced, rt->gcTraceLaterCount);
+#endif
+
+ a = FLAGP_TO_ARENA(flagp);
+ untracedBitIndex = FLAGP_TO_INDEX(flagp) /
+ THINGS_PER_UNTRACED_BIT(a->list->thingSize);
+ JS_ASSERT(untracedBitIndex < JS_BITS_PER_WORD);
+ bit = (jsuword)1 << untracedBitIndex;
+ if (a->u.untracedThings != 0) {
+ JS_ASSERT(rt->gcUntracedArenaStackTop);
+ if (a->u.untracedThings & bit) {
+ /* bit already covers things with children to trace later. */
+ return;
+ }
+ a->u.untracedThings |= bit;
+ } else {
+ /*
+ * The thing is the first thing with not yet traced children in the
+ * whole arena, so push the arena on the stack of arenas with things
+ * to be traced later unless the arena has already been pushed. We
+ * detect that through checking prevUntracedPage as the field is 0
+ * only for not yet pushed arenas. To ensure that
+ * prevUntracedPage != 0
+ * even when the stack contains one element, we make prevUntracedPage
+ * for the arena at the bottom to point to itself.
+ *
+ * See comments in TraceDelayedChildren.
+ */
+ a->u.untracedThings = bit;
+ if (a->prevUntracedPage == 0) {
+ if (!rt->gcUntracedArenaStackTop) {
+ /* Stack was empty, mark the arena as the bottom element. */
+ a->prevUntracedPage = ARENA_INFO_TO_PAGE(a);
+ } else {
+ JS_ASSERT(rt->gcUntracedArenaStackTop->prevUntracedPage != 0);
+ a->prevUntracedPage =
+ ARENA_INFO_TO_PAGE(rt->gcUntracedArenaStackTop);
+ }
+ rt->gcUntracedArenaStackTop = a;
+ }
+ }
+ JS_ASSERT(rt->gcUntracedArenaStackTop);
+}
+
+static void
+TraceDelayedChildren(JSTracer *trc)
+{
+ JSRuntime *rt;
+ JSGCArenaInfo *a, *aprev;
+ uint32 thingSize;
+ uint32 thingsPerUntracedBit;
+ uint32 untracedBitIndex, thingIndex, indexLimit, endIndex;
+ JSGCThing *thing;
+ uint8 *flagp;
+
+ rt = trc->context->runtime;
+ a = rt->gcUntracedArenaStackTop;
+ if (!a) {
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+ return;
+ }
+
+ for (;;) {
+ /*
+ * The following assert verifies that the current arena belongs to the
+ * untraced stack, since DelayTracingChildren ensures that even for
+ * stack's bottom prevUntracedPage != 0 but rather points to itself.
+ */
+ JS_ASSERT(a->prevUntracedPage != 0);
+ JS_ASSERT(rt->gcUntracedArenaStackTop->prevUntracedPage != 0);
+ thingSize = a->list->thingSize;
+ indexLimit = (a == a->list->last)
+ ? a->list->lastCount
+ : THINGS_PER_ARENA(thingSize);
+ thingsPerUntracedBit = THINGS_PER_UNTRACED_BIT(thingSize);
+
+ /*
+ * We cannot use do-while loop here as a->u.untracedThings can be zero
+ * before the loop as a leftover from the previous iterations. See
+ * comments after the loop.
+ */
+ while (a->u.untracedThings != 0) {
+ untracedBitIndex = JS_FLOOR_LOG2W(a->u.untracedThings);
+ a->u.untracedThings &= ~((jsuword)1 << untracedBitIndex);
+ thingIndex = untracedBitIndex * thingsPerUntracedBit;
+ endIndex = thingIndex + thingsPerUntracedBit;
+
+ /*
+ * endIndex can go beyond the last allocated thing as the real
+ * limit can be "inside" the bit.
+ */
+ if (endIndex > indexLimit)
+ endIndex = indexLimit;
+ JS_ASSERT(thingIndex < indexLimit);
+
+ do {
+ /*
+ * Skip free or already traced things that share the bit
+ * with untraced ones.
+ */
+ flagp = THING_FLAGP(a, thingIndex);
+ if ((*flagp & (GCF_MARK|GCF_FINAL)) != (GCF_MARK|GCF_FINAL))
+ continue;
+ *flagp &= ~GCF_FINAL;
+#ifdef DEBUG
+ JS_ASSERT(rt->gcTraceLaterCount != 0);
+ --rt->gcTraceLaterCount;
+#endif
+ thing = FLAGP_TO_THING(flagp, thingSize);
+ JS_TraceChildren(trc, thing, MapGCFlagsToTraceKind(*flagp));
+ } while (++thingIndex != endIndex);
+ }
+
+ /*
+ * We finished tracing of all things in the the arena but we can only
+ * pop it from the stack if the arena is the stack's top.
+ *
+ * When JS_TraceChildren from the above calls JS_CallTracer that in
+ * turn on low C stack calls DelayTracingChildren and the latter
+ * pushes new arenas to the untraced stack, we have to skip popping
+ * of this arena until it becomes the top of the stack again.
+ */
+ if (a == rt->gcUntracedArenaStackTop) {
+ aprev = ARENA_PAGE_TO_INFO(a->prevUntracedPage);
+ a->prevUntracedPage = 0;
+ if (a == aprev) {
+ /*
+ * prevUntracedPage points to itself and we reached the
+ * bottom of the stack.
+ */
+ break;
+ }
+ rt->gcUntracedArenaStackTop = a = aprev;
+ } else {
+ a = rt->gcUntracedArenaStackTop;
+ }
+ }
+ JS_ASSERT(rt->gcUntracedArenaStackTop);
+ JS_ASSERT(rt->gcUntracedArenaStackTop->prevUntracedPage == 0);
+ rt->gcUntracedArenaStackTop = NULL;
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+}
+
+JS_PUBLIC_API(void)
+JS_CallTracer(JSTracer *trc, void *thing, uint32 kind)
+{
+ JSContext *cx;
+ JSRuntime *rt;
+ JSGCArenaInfo *a;
+ uintN index;
+ uint8 *flagp;
+
+ JS_ASSERT(thing);
+ JS_ASSERT(JS_IS_VALID_TRACE_KIND(kind));
+ JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
+
+ if (!IS_GC_MARKING_TRACER(trc)) {
+ trc->callback(trc, thing, kind);
+ goto out;
+ }
+
+ cx = trc->context;
+ rt = cx->runtime;
+ JS_ASSERT(rt->gcMarkingTracer == trc);
+ JS_ASSERT(rt->gcLevel > 0);
+
+ /*
+ * Optimize for string and double as their size is known and their tracing
+ * is not recursive.
+ */
+ switch (kind) {
+ case JSTRACE_DOUBLE:
+ a = THING_TO_ARENA(thing);
+ JS_ASSERT(!a->list);
+ if (!a->u.hasMarkedDoubles) {
+ ClearDoubleArenaFlags(a);
+ a->u.hasMarkedDoubles = JS_TRUE;
+ }
+ index = DOUBLE_THING_TO_INDEX(thing);
+ JS_SET_BIT(DOUBLE_ARENA_BITMAP(a), index);
+ goto out;
+
+ case JSTRACE_STRING:
+ for (;;) {
+ flagp = THING_TO_FLAGP(thing, sizeof(JSGCThing));
+ JS_ASSERT((*flagp & GCF_FINAL) == 0);
+ JS_ASSERT(kind == MapGCFlagsToTraceKind(*flagp));
+ if (!JSSTRING_IS_DEPENDENT((JSString *) thing)) {
+ *flagp |= GCF_MARK;
+ goto out;
+ }
+ if (*flagp & GCF_MARK)
+ goto out;
+ *flagp |= GCF_MARK;
+ thing = JSSTRDEP_BASE((JSString *) thing);
+ }
+ /* NOTREACHED */
+ }
+
+ flagp = GetGCThingFlags(thing);
+ JS_ASSERT(kind == MapGCFlagsToTraceKind(*flagp));
+ if (*flagp & GCF_MARK)
+ goto out;
+
+ /*
+ * We check for non-final flag only if mark is unset as
+ * DelayTracingChildren uses the flag. See comments in the function.
+ */
+ JS_ASSERT(*flagp != GCF_FINAL);
+ *flagp |= GCF_MARK;
+ if (!cx->insideGCMarkCallback) {
+ /*
+ * With JS_GC_ASSUME_LOW_C_STACK defined the mark phase of GC always
+ * uses the non-recursive code that otherwise would be called only on
+ * a low C stack condition.
+ */
+#ifdef JS_GC_ASSUME_LOW_C_STACK
+# define RECURSION_TOO_DEEP() JS_TRUE
+#else
+ int stackDummy;
+# define RECURSION_TOO_DEEP() (!JS_CHECK_STACK_SIZE(cx, stackDummy))
+#endif
+ if (RECURSION_TOO_DEEP())
+ DelayTracingChildren(rt, flagp);
+ else
+ JS_TraceChildren(trc, thing, kind);
+ } else {
+ /*
+ * For API compatibility we allow for the callback to assume that
+ * after it calls JS_MarkGCThing for the last time, the callback can
+ * start to finalize its own objects that are only referenced by
+ * unmarked GC things.
+ *
+ * Since we do not know which call from inside the callback is the
+ * last, we ensure that children of all marked things are traced and
+ * call TraceDelayedChildren(trc) after tracing the thing.
+ *
+ * As TraceDelayedChildren unconditionally invokes JS_TraceChildren
+ * for the things with untraced children, calling DelayTracingChildren
+ * is useless here. Hence we always trace thing's children even with a
+ * low native stack.
+ */
+ cx->insideGCMarkCallback = JS_FALSE;
+ JS_TraceChildren(trc, thing, kind);
+ TraceDelayedChildren(trc);
+ cx->insideGCMarkCallback = JS_TRUE;
+ }
+
+ out:
+#ifdef DEBUG
+ trc->debugPrinter = NULL;
+ trc->debugPrintArg = NULL;
+#endif
+ return; /* to avoid out: right_curl when DEBUG is not defined */
+}
+
+void
+js_CallValueTracerIfGCThing(JSTracer *trc, jsval v)
+{
+ void *thing;
+ uint32 kind;
+
+ if (JSVAL_IS_DOUBLE(v) || JSVAL_IS_STRING(v)) {
+ thing = JSVAL_TO_TRACEABLE(v);
+ kind = JSVAL_TRACE_KIND(v);
+ JS_ASSERT(kind == js_GetGCThingTraceKind(JSVAL_TO_GCTHING(v)));
+ } else if (JSVAL_IS_OBJECT(v) && v != JSVAL_NULL) {
+ /* v can be an arbitrary GC thing reinterpreted as an object. */
+ thing = JSVAL_TO_OBJECT(v);
+ kind = js_GetGCThingTraceKind(thing);
+ } else {
+ return;
+ }
+ JS_CallTracer(trc, thing, kind);
+}
+
+static JSDHashOperator
+gc_root_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
+ void *arg)
+{
+ JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;
+ JSTracer *trc = (JSTracer *)arg;
+ jsval *rp = (jsval *)rhe->root;
+ jsval v = *rp;
+
+ /* Ignore null object and scalar values. */
+ if (!JSVAL_IS_NULL(v) && JSVAL_IS_GCTHING(v)) {
+#ifdef DEBUG
+ JSBool root_points_to_gcArenaList = JS_FALSE;
+ jsuword thing = (jsuword) JSVAL_TO_GCTHING(v);
+ JSRuntime *rt;
+ uintN i;
+ JSGCArenaList *arenaList;
+ uint32 thingSize;
+ JSGCArenaInfo *a;
+ size_t limit;
+
+ rt = trc->context->runtime;
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i];
+ thingSize = arenaList->thingSize;
+ limit = (size_t) arenaList->lastCount * thingSize;
+ for (a = arenaList->last; a; a = a->prev) {
+ if (thing - ARENA_INFO_TO_START(a) < limit) {
+ root_points_to_gcArenaList = JS_TRUE;
+ break;
+ }
+ limit = (size_t) THINGS_PER_ARENA(thingSize) * thingSize;
+ }
+ }
+ if (!root_points_to_gcArenaList) {
+ for (a = rt->gcDoubleArenaList.first; a; a = a->prev) {
+ if (thing - ARENA_INFO_TO_START(a) <
+ DOUBLES_PER_ARENA * sizeof(jsdouble)) {
+ root_points_to_gcArenaList = JS_TRUE;
+ break;
+ }
+ }
+ }
+ if (!root_points_to_gcArenaList && rhe->name) {
+ fprintf(stderr,
+"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n"
+"invalid jsval. This is usually caused by a missing call to JS_RemoveRoot.\n"
+"The root's name is \"%s\".\n",
+ rhe->name);
+ }
+ JS_ASSERT(root_points_to_gcArenaList);
+#endif
+ JS_SET_TRACING_NAME(trc, rhe->name ? rhe->name : "root");
+ js_CallValueTracerIfGCThing(trc, v);
+ }
+
+ return JS_DHASH_NEXT;
+}
+
+static JSDHashOperator
+gc_lock_traversal(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num,
+ void *arg)
+{
+ JSGCLockHashEntry *lhe = (JSGCLockHashEntry *)hdr;
+ void *thing = (void *)lhe->thing;
+ JSTracer *trc = (JSTracer *)arg;
+ uint32 traceKind;
+
+ JS_ASSERT(lhe->count >= 1);
+ traceKind = js_GetGCThingTraceKind(thing);
+ JS_CALL_TRACER(trc, thing, traceKind, "locked object");
+ return JS_DHASH_NEXT;
+}
+
+#define TRACE_JSVALS(trc, len, vec, name) \
+ JS_BEGIN_MACRO \
+ jsval _v, *_vp, *_end; \
+ \
+ for (_vp = vec, _end = _vp + len; _vp < _end; _vp++) { \
+ _v = *_vp; \
+ if (JSVAL_IS_TRACEABLE(_v)) { \
+ JS_SET_TRACING_INDEX(trc, name, _vp - (vec)); \
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(_v), \
+ JSVAL_TRACE_KIND(_v)); \
+ } \
+ } \
+ JS_END_MACRO
+
+void
+js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
+{
+ uintN nslots, minargs, skip;
+
+ if (fp->callobj)
+ JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call");
+ if (fp->argsobj)
+ JS_CALL_OBJECT_TRACER(trc, fp->argsobj, "arguments");
+ if (fp->varobj)
+ JS_CALL_OBJECT_TRACER(trc, fp->varobj, "variables");
+ if (fp->script) {
+ js_TraceScript(trc, fp->script);
+ if (fp->regs) {
+ /*
+ * Don't mark what has not been pushed yet, or what has been
+ * popped already.
+ */
+ nslots = (uintN) (fp->regs->sp - fp->slots);
+ TRACE_JSVALS(trc, nslots, fp->slots, "slot");
+ }
+ } else {
+ JS_ASSERT(!fp->slots);
+ JS_ASSERT(!fp->regs);
+ }
+
+ /* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
+ JS_ASSERT(JSVAL_IS_OBJECT((jsval)fp->thisp) ||
+ (fp->fun && JSFUN_THISP_FLAGS(fp->fun->flags)));
+ JS_CALL_VALUE_TRACER(trc, (jsval)fp->thisp, "this");
+
+ if (fp->callee)
+ JS_CALL_OBJECT_TRACER(trc, fp->callee, "callee");
+
+ if (fp->argv) {
+ nslots = fp->argc;
+ skip = 0;
+ if (fp->fun) {
+ minargs = FUN_MINARGS(fp->fun);
+ if (minargs > nslots)
+ nslots = minargs;
+ if (!FUN_INTERPRETED(fp->fun)) {
+ JS_ASSERT(!(fp->fun->flags & JSFUN_FAST_NATIVE));
+ nslots += fp->fun->u.n.extra;
+ }
+ if (fp->fun->flags & JSFRAME_ROOTED_ARGV)
+ skip = 2 + fp->argc;
+ }
+ TRACE_JSVALS(trc, 2 + nslots - skip, fp->argv - 2 + skip, "operand");
+ }
+
+ JS_CALL_VALUE_TRACER(trc, fp->rval, "rval");
+ if (fp->scopeChain)
+ JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain");
+ if (fp->sharpArray)
+ JS_CALL_OBJECT_TRACER(trc, fp->sharpArray, "sharp array");
+
+ if (fp->xmlNamespace)
+ JS_CALL_OBJECT_TRACER(trc, fp->xmlNamespace, "xmlNamespace");
+}
+
+static void
+TraceWeakRoots(JSTracer *trc, JSWeakRoots *wr)
+{
+ uint32 i;
+ void *thing;
+
+#ifdef DEBUG
+ static const char *weakRootNames[JSTRACE_LIMIT] = {
+ "newborn object",
+ "newborn double",
+ "newborn string",
+ "newborn xml"
+ };
+#endif
+
+ for (i = 0; i != JSTRACE_LIMIT; i++) {
+ thing = wr->newborn[i];
+ if (thing)
+ JS_CALL_TRACER(trc, thing, i, weakRootNames[i]);
+ }
+ JS_ASSERT(i == GCX_EXTERNAL_STRING);
+ for (; i != GCX_NTYPES; ++i) {
+ thing = wr->newborn[i];
+ if (thing) {
+ JS_SET_TRACING_INDEX(trc, "newborn external string",
+ i - GCX_EXTERNAL_STRING);
+ JS_CallTracer(trc, thing, JSTRACE_STRING);
+ }
+ }
+
+ JS_CALL_VALUE_TRACER(trc, wr->lastAtom, "lastAtom");
+ JS_SET_TRACING_NAME(trc, "lastInternalResult");
+ js_CallValueTracerIfGCThing(trc, wr->lastInternalResult);
+}
+
+JS_FRIEND_API(void)
+js_TraceContext(JSTracer *trc, JSContext *acx)
+{
+ JSStackFrame *fp, *nextChain;
+ JSStackHeader *sh;
+ JSTempValueRooter *tvr;
+
+ if (IS_GC_MARKING_TRACER(trc)) {
+
+#define FREE_OLD_ARENAS(pool) \
+ JS_BEGIN_MACRO \
+ int64 _age; \
+ JSArena * _a = (pool).current; \
+ if (_a == (pool).first.next && \
+ _a->avail == _a->base + sizeof(int64)) { \
+ _age = JS_Now() - *(int64 *) _a->base; \
+ if (_age > (int64) acx->runtime->gcEmptyArenaPoolLifespan * \
+ 1000) \
+ JS_FreeArenaPool(&(pool)); \
+ } \
+ JS_END_MACRO
+
+#ifdef JS_THREADSAFE
+ js_RevokeGCLocalFreeLists(acx);
+#endif
+
+ /*
+ * Release the stackPool's arenas if the stackPool has existed for
+ * longer than the limit specified by gcEmptyArenaPoolLifespan.
+ */
+ FREE_OLD_ARENAS(acx->stackPool);
+
+ /*
+ * Release the regexpPool's arenas based on the same criterion as for
+ * the stackPool.
+ */
+ FREE_OLD_ARENAS(acx->regexpPool);
+
+ /*
+ * Clear the double free list to release all the pre-allocated doubles.
+ */
+ acx->doubleFreeList = NULL;
+ }
+
+ /*
+ * Iterate frame chain and dormant chains.
+ *
+ * (NB: see comment on this whole "dormant" thing in js_Execute.)
+ */
+ fp = acx->fp;
+ nextChain = acx->dormantFrameChain;
+ if (!fp)
+ goto next_chain;
+
+ /* The top frame must not be dormant. */
+ JS_ASSERT(!fp->dormantNext);
+ for (;;) {
+ do {
+ js_TraceStackFrame(trc, fp);
+ } while ((fp = fp->down) != NULL);
+
+ next_chain:
+ if (!nextChain)
+ break;
+ fp = nextChain;
+ nextChain = nextChain->dormantNext;
+ }
+
+ /* Mark other roots-by-definition in acx. */
+ if (acx->globalObject)
+ JS_CALL_OBJECT_TRACER(trc, acx->globalObject, "global object");
+ TraceWeakRoots(trc, &acx->weakRoots);
+ if (acx->throwing) {
+ JS_CALL_VALUE_TRACER(trc, acx->exception, "exception");
+ } else {
+ /* Avoid keeping GC-ed junk stored in JSContext.exception. */
+ acx->exception = JSVAL_NULL;
+ }
+#if JS_HAS_LVALUE_RETURN
+ if (acx->rval2set)
+ JS_CALL_VALUE_TRACER(trc, acx->rval2, "rval2");
+#endif
+
+ for (sh = acx->stackHeaders; sh; sh = sh->down) {
+ METER(trc->context->runtime->gcStats.stackseg++);
+ METER(trc->context->runtime->gcStats.segslots += sh->nslots);
+ TRACE_JSVALS(trc, sh->nslots, JS_STACK_SEGMENT(sh), "stack");
+ }
+
+ if (acx->localRootStack)
+ js_TraceLocalRoots(trc, acx->localRootStack);
+
+ for (tvr = acx->tempValueRooters; tvr; tvr = tvr->down) {
+ switch (tvr->count) {
+ case JSTVU_SINGLE:
+ JS_SET_TRACING_NAME(trc, "tvr->u.value");
+ js_CallValueTracerIfGCThing(trc, tvr->u.value);
+ break;
+ case JSTVU_TRACE:
+ tvr->u.trace(trc, tvr);
+ break;
+ case JSTVU_SPROP:
+ TRACE_SCOPE_PROPERTY(trc, tvr->u.sprop);
+ break;
+ case JSTVU_WEAK_ROOTS:
+ TraceWeakRoots(trc, tvr->u.weakRoots);
+ break;
+ case JSTVU_PARSE_CONTEXT:
+ js_TraceParseContext(trc, tvr->u.parseContext);
+ break;
+ case JSTVU_SCRIPT:
+ js_TraceScript(trc, tvr->u.script);
+ break;
+ default:
+ JS_ASSERT(tvr->count >= 0);
+ TRACE_JSVALS(trc, tvr->count, tvr->u.array, "tvr->u.array");
+ }
+ }
+
+ if (acx->sharpObjectMap.depth > 0)
+ js_TraceSharpMap(trc, &acx->sharpObjectMap);
+}
+
+void
+js_TraceTraceMonitor(JSTracer *trc, JSTraceMonitor *tm)
+{
+ if (IS_GC_MARKING_TRACER(trc)) {
+ tm->recoveryDoublePoolPtr = tm->recoveryDoublePool;
+ /* Make sure the global shape changes and will force a flush
+ of the code cache. */
+ tm->globalShape = -1;
+ }
+}
+
+void
+js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
+{
+ JSRuntime *rt = trc->context->runtime;
+ JSContext *iter, *acx;
+
+ JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_traversal, trc);
+ if (rt->gcLocksHash)
+ JS_DHashTableEnumerate(rt->gcLocksHash, gc_lock_traversal, trc);
+ js_TraceAtomState(trc, allAtoms);
+ js_TraceNativeEnumerators(trc);
+ js_TraceRuntimeNumberState(trc);
+
+ iter = NULL;
+ while ((acx = js_ContextIterator(rt, JS_TRUE, &iter)) != NULL)
+ js_TraceContext(trc, acx);
+
+ if (rt->gcExtraRootsTraceOp)
+ rt->gcExtraRootsTraceOp(trc, rt->gcExtraRootsData);
+
+#ifdef JS_THREADSAFE
+ /* Trace the loop table(s) which can contain pointers to code objects. */
+ while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
+ if (!acx->thread)
+ continue;
+ js_TraceTraceMonitor(trc, &acx->thread->traceMonitor);
+ }
+#else
+ js_TraceTraceMonitor(trc, &rt->traceMonitor);
+#endif
+}
+
+static void
+ProcessSetSlotRequest(JSContext *cx, JSSetSlotRequest *ssr)
+{
+ JSObject *obj, *pobj;
+ uint32 slot;
+
+ obj = ssr->obj;
+ pobj = ssr->pobj;
+ slot = ssr->slot;
+
+ while (pobj) {
+ pobj = js_GetWrappedObject(cx, pobj);
+ if (pobj == obj) {
+ ssr->errnum = JSMSG_CYCLIC_VALUE;
+ return;
+ }
+ pobj = JSVAL_TO_OBJECT(STOBJ_GET_SLOT(pobj, slot));
+ }
+
+ pobj = ssr->pobj;
+
+ if (slot == JSSLOT_PROTO && OBJ_IS_NATIVE(obj)) {
+ JSScope *scope, *newscope;
+ JSObject *oldproto;
+
+ /* Check to see whether obj shares its prototype's scope. */
+ scope = OBJ_SCOPE(obj);
+ oldproto = STOBJ_GET_PROTO(obj);
+ if (oldproto && OBJ_SCOPE(oldproto) == scope) {
+ /* Either obj needs a new empty scope, or it should share pobj's. */
+ if (!pobj ||
+ !OBJ_IS_NATIVE(pobj) ||
+ OBJ_GET_CLASS(cx, pobj) != STOBJ_GET_CLASS(oldproto)) {
+ /*
+ * With no proto and no scope of its own, obj is truly empty.
+ *
+ * If pobj is not native, obj needs its own empty scope -- it
+ * should not continue to share oldproto's scope once oldproto
+ * is not on obj's prototype chain. That would put properties
+ * from oldproto's scope ahead of properties defined by pobj,
+ * in lookup order.
+ *
+ * If pobj's class differs from oldproto's, we may need a new
+ * scope to handle differences in private and reserved slots,
+ * so we suboptimally but safely make one.
+ */
+ if (!js_GetMutableScope(cx, obj)) {
+ ssr->errnum = JSMSG_OUT_OF_MEMORY;
+ return;
+ }
+ } else if (OBJ_SCOPE(pobj) != scope) {
+ newscope = (JSScope *) js_HoldObjectMap(cx, pobj->map);
+ obj->map = &newscope->map;
+ js_DropObjectMap(cx, &scope->map, obj);
+ JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
+ }
+ }
+
+ /*
+ * Regenerate property cache shape ids for all of the scopes along the
+ * old prototype chain, in case any property cache entries were filled
+ * by looking up starting from obj.
+ */
+ while (oldproto && OBJ_IS_NATIVE(oldproto)) {
+ scope = OBJ_SCOPE(oldproto);
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ oldproto = STOBJ_GET_PROTO(scope->object);
+ }
+ }
+
+ /* Finally, do the deed. */
+ STOBJ_SET_SLOT(obj, slot, OBJECT_TO_JSVAL(pobj));
+}
+
+static void
+DestroyScriptsToGC(JSContext *cx, JSScript **listp)
+{
+ JSScript *script;
+
+ while ((script = *listp) != NULL) {
+ *listp = script->u.nextToGC;
+ script->u.nextToGC = NULL;
+ js_DestroyScript(cx, script);
+ }
+}
+
+/*
+ * The gckind flag bit GC_LOCK_HELD indicates a call from js_NewGCThing with
+ * rt->gcLock already held, so the lock should be kept on return.
+ */
+void
+js_GC(JSContext *cx, JSGCInvocationKind gckind)
+{
+ JSRuntime *rt;
+ JSBool keepAtoms;
+ JSGCCallback callback;
+ uintN i, type;
+ JSTracer trc;
+ uint32 thingSize, indexLimit;
+ JSGCArenaInfo *a, **ap, *emptyArenas;
+ uint8 flags, *flagp;
+ JSGCThing *thing, *freeList;
+ JSGCArenaList *arenaList;
+ JSBool allClear;
+#ifdef JS_THREADSAFE
+ uint32 requestDebit;
+ JSContext *acx, *iter;
+#endif
+#ifdef JS_GCMETER
+ uint32 nlivearenas, nkilledarenas, nthings;
+#endif
+
+ JS_ASSERT_IF(gckind == GC_LAST_DITCH, !JS_ON_TRACE(cx));
+ rt = cx->runtime;
+#ifdef JS_THREADSAFE
+ /* Avoid deadlock. */
+ JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt));
+#endif
+
+ if (gckind & GC_KEEP_ATOMS) {
+ /*
+ * The set slot request and last ditch GC kinds preserve all atoms and
+ * weak roots.
+ */
+ keepAtoms = JS_TRUE;
+ } else {
+ /* Keep atoms when a suspended compile is running on another context. */
+ keepAtoms = (rt->gcKeepAtoms != 0);
+ JS_CLEAR_WEAK_ROOTS(&cx->weakRoots);
+ }
+
+ /*
+ * Don't collect garbage if the runtime isn't up, and cx is not the last
+ * context in the runtime. The last context must force a GC, and nothing
+ * should suppress that final collection or there may be shutdown leaks,
+ * or runtime bloat until the next context is created.
+ */
+ if (rt->state != JSRTS_UP && gckind != GC_LAST_CONTEXT)
+ return;
+
+ restart_at_beginning:
+ /*
+ * Let the API user decide to defer a GC if it wants to (unless this
+ * is the last context). Invoke the callback regardless. Sample the
+ * callback in case we are freely racing with a JS_SetGCCallback{,RT} on
+ * another thread.
+ */
+ if (gckind != GC_SET_SLOT_REQUEST && (callback = rt->gcCallback)) {
+ JSBool ok;
+
+ if (gckind & GC_LOCK_HELD)
+ JS_UNLOCK_GC(rt);
+ ok = callback(cx, JSGC_BEGIN);
+ if (gckind & GC_LOCK_HELD)
+ JS_LOCK_GC(rt);
+ if (!ok && gckind != GC_LAST_CONTEXT) {
+ /*
+ * It's possible that we've looped back to this code from the 'goto
+ * restart_at_beginning' below in the GC_SET_SLOT_REQUEST code and
+ * that rt->gcLevel is now 0. Don't return without notifying!
+ */
+ if (rt->gcLevel == 0 && (gckind & GC_LOCK_HELD))
+ JS_NOTIFY_GC_DONE(rt);
+ return;
+ }
+ }
+
+ /* Lock out other GC allocator and collector invocations. */
+ if (!(gckind & GC_LOCK_HELD))
+ JS_LOCK_GC(rt);
+
+ METER(rt->gcStats.poke++);
+ rt->gcPoke = JS_FALSE;
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(cx->thread->id == js_CurrentThreadId());
+
+ /* Bump gcLevel and return rather than nest on this thread. */
+ if (rt->gcThread == cx->thread) {
+ JS_ASSERT(rt->gcLevel > 0);
+ rt->gcLevel++;
+ METER_UPDATE_MAX(rt->gcStats.maxlevel, rt->gcLevel);
+ if (!(gckind & GC_LOCK_HELD))
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+
+ /*
+ * If we're in one or more requests (possibly on more than one context)
+ * running on the current thread, indicate, temporarily, that all these
+ * requests are inactive. If cx->thread is NULL, then cx is not using
+ * the request model, and does not contribute to rt->requestCount.
+ */
+ requestDebit = 0;
+ if (cx->thread) {
+ JSCList *head, *link;
+
+ /*
+ * Check all contexts on cx->thread->contextList for active requests,
+ * counting each such context against requestDebit.
+ */
+ head = &cx->thread->contextList;
+ for (link = head->next; link != head; link = link->next) {
+ acx = CX_FROM_THREAD_LINKS(link);
+ JS_ASSERT(acx->thread == cx->thread);
+ if (acx->requestDepth)
+ requestDebit++;
+ }
+ } else {
+ /*
+ * We assert, but check anyway, in case someone is misusing the API.
+ * Avoiding the loop over all of rt's contexts is a win in the event
+ * that the GC runs only on request-less contexts with null threads,
+ * in a special thread such as might be used by the UI/DOM/Layout
+ * "mozilla" or "main" thread in Mozilla-the-browser.
+ */
+ JS_ASSERT(cx->requestDepth == 0);
+ if (cx->requestDepth)
+ requestDebit = 1;
+ }
+ if (requestDebit) {
+ JS_ASSERT(requestDebit <= rt->requestCount);
+ rt->requestCount -= requestDebit;
+ if (rt->requestCount == 0)
+ JS_NOTIFY_REQUEST_DONE(rt);
+ }
+
+ /* If another thread is already in GC, don't attempt GC; wait instead. */
+ if (rt->gcLevel > 0) {
+ /* Bump gcLevel to restart the current GC, so it finds new garbage. */
+ rt->gcLevel++;
+ METER_UPDATE_MAX(rt->gcStats.maxlevel, rt->gcLevel);
+
+ /* Wait for the other thread to finish, then resume our request. */
+ while (rt->gcLevel > 0)
+ JS_AWAIT_GC_DONE(rt);
+ if (requestDebit)
+ rt->requestCount += requestDebit;
+ if (!(gckind & GC_LOCK_HELD))
+ JS_UNLOCK_GC(rt);
+ return;
+ }
+
+ /* No other thread is in GC, so indicate that we're now in GC. */
+ rt->gcLevel = 1;
+ rt->gcThread = cx->thread;
+
+ /* Wait for all other requests to finish. */
+ while (rt->requestCount > 0)
+ JS_AWAIT_REQUEST_DONE(rt);
+
+#else /* !JS_THREADSAFE */
+
+ /* Bump gcLevel and return rather than nest; the outer gc will restart. */
+ rt->gcLevel++;
+ METER_UPDATE_MAX(rt->gcStats.maxlevel, rt->gcLevel);
+ if (rt->gcLevel > 1)
+ return;
+
+#endif /* !JS_THREADSAFE */
+
+ /*
+ * Set rt->gcRunning here within the GC lock, and after waiting for any
+ * active requests to end, so that new requests that try to JS_AddRoot,
+ * JS_RemoveRoot, or JS_RemoveRootRT block in JS_BeginRequest waiting for
+ * rt->gcLevel to drop to zero, while request-less calls to the *Root*
+ * APIs block in js_AddRoot or js_RemoveRoot (see above in this file),
+ * waiting for GC to finish.
+ */
+ rt->gcRunning = JS_TRUE;
+
+ if (gckind == GC_SET_SLOT_REQUEST) {
+ JSSetSlotRequest *ssr;
+
+ while ((ssr = rt->setSlotRequests) != NULL) {
+ rt->setSlotRequests = ssr->next;
+ JS_UNLOCK_GC(rt);
+ ssr->next = NULL;
+ ProcessSetSlotRequest(cx, ssr);
+ JS_LOCK_GC(rt);
+ }
+
+ /*
+ * We assume here that killing links to parent and prototype objects
+ * does not create garbage (such objects typically are long-lived and
+ * widely shared, e.g. global objects, Function.prototype, etc.). We
+ * collect garbage only if a racing thread attempted GC and is waiting
+ * for us to finish (gcLevel > 1) or if someone already poked us.
+ */
+ if (rt->gcLevel == 1 && !rt->gcPoke)
+ goto done_running;
+
+ rt->gcLevel = 0;
+ rt->gcPoke = JS_FALSE;
+ rt->gcRunning = JS_FALSE;
+#ifdef JS_THREADSAFE
+ rt->gcThread = NULL;
+ rt->requestCount += requestDebit;
+#endif
+ gckind = GC_LOCK_HELD;
+ goto restart_at_beginning;
+ }
+
+ JS_UNLOCK_GC(rt);
+
+#ifdef JS_TRACER
+ if (JS_ON_TRACE(cx))
+ goto out;
+#endif
+
+ /* Reset malloc counter. */
+ rt->gcMallocBytes = 0;
+
+#ifdef JS_DUMP_SCOPE_METERS
+ { extern void js_DumpScopeMeters(JSRuntime *rt);
+ js_DumpScopeMeters(rt);
+ }
+#endif
+
+ /* Clear property and JIT oracle caches (only for cx->thread if JS_THREADSAFE). */
+ js_FlushPropertyCache(cx);
+#ifdef JS_TRACER
+ js_FlushJITOracle(cx);
+#endif
+
+ /* Destroy eval'ed scripts. */
+ DestroyScriptsToGC(cx, &JS_SCRIPTS_TO_GC(cx));
+
+#ifdef JS_THREADSAFE
+ /*
+ * Clear thread-based caches. To avoid redundant clearing we unroll the
+ * current thread's step.
+ *
+ * In case a JSScript wrapped within an object was finalized, we null
+ * acx->thread->gsnCache.script and finish the cache's hashtable. Note
+ * that js_DestroyScript, called from script_finalize, will have already
+ * cleared cx->thread->gsnCache above during finalization, so we don't
+ * have to here.
+ */
+ iter = NULL;
+ while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
+ if (!acx->thread || acx->thread == cx->thread)
+ continue;
+ GSN_CACHE_CLEAR(&acx->thread->gsnCache);
+ js_FlushPropertyCache(acx);
+#ifdef JS_TRACER
+ js_FlushJITOracle(acx);
+#endif
+ DestroyScriptsToGC(cx, &acx->thread->scriptsToGC);
+ }
+#else
+ /* The thread-unsafe case just has to clear the runtime's GSN cache. */
+ GSN_CACHE_CLEAR(&rt->gsnCache);
+#endif
+
+ restart:
+ rt->gcNumber++;
+ JS_ASSERT(!rt->gcUntracedArenaStackTop);
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+
+ /* Reset the property cache's type id generator so we can compress ids. */
+ rt->shapeGen = 0;
+
+ /*
+ * Mark phase.
+ */
+ JS_TRACER_INIT(&trc, cx, NULL);
+ rt->gcMarkingTracer = &trc;
+ JS_ASSERT(IS_GC_MARKING_TRACER(&trc));
+
+ for (a = rt->gcDoubleArenaList.first; a; a = a->prev)
+ a->u.hasMarkedDoubles = JS_FALSE;
+
+ js_TraceRuntime(&trc, keepAtoms);
+ js_MarkScriptFilenames(rt, keepAtoms);
+
+ /*
+ * Mark children of things that caused too deep recursion during the above
+ * tracing.
+ */
+ TraceDelayedChildren(&trc);
+
+ JS_ASSERT(!cx->insideGCMarkCallback);
+ if (rt->gcCallback) {
+ cx->insideGCMarkCallback = JS_TRUE;
+ (void) rt->gcCallback(cx, JSGC_MARK_END);
+ JS_ASSERT(cx->insideGCMarkCallback);
+ cx->insideGCMarkCallback = JS_FALSE;
+ }
+ JS_ASSERT(rt->gcTraceLaterCount == 0);
+
+ rt->gcMarkingTracer = NULL;
+
+ /*
+ * Sweep phase.
+ *
+ * Finalize as we sweep, outside of rt->gcLock but with rt->gcRunning set
+ * so that any attempt to allocate a GC-thing from a finalizer will fail,
+ * rather than nest badly and leave the unmarked newborn to be swept.
+ *
+ * We first sweep atom state so we can use js_IsAboutToBeFinalized on
+ * JSString or jsdouble held in a hashtable to check if the hashtable
+ * entry can be freed. Note that even after the entry is freed, JSObject
+ * finalizers can continue to access the corresponding jsdouble* and
+ * JSString* assuming that they are unique. This works since the
+ * atomization API must not be called during GC.
+ */
+ js_SweepAtomState(cx);
+
+ /* Finalize iterator states before the objects they iterate over. */
+ CloseNativeIterators(cx);
+
+ /* Finalize watch points associated with unreachable objects. */
+ js_SweepWatchPoints(cx);
+
+#ifdef DEBUG
+ /* Save the pre-sweep count of scope-mapped properties. */
+ rt->liveScopePropsPreSweep = rt->liveScopeProps;
+#endif
+
+ /*
+ * Here we need to ensure that JSObject instances are finalized before GC-
+ * allocated JSString and jsdouble instances so object's finalizer can
+ * access them even if they will be freed. For that we simply finalize the
+ * list containing JSObject first since the static assert at the beginning
+ * of the file guarantees that JSString and jsdouble instances are
+ * allocated from a different list.
+ */
+ emptyArenas = NULL;
+ for (i = 0; i < GC_NUM_FREELISTS; i++) {
+ arenaList = &rt->gcArenaList[i == 0
+ ? GC_FREELIST_INDEX(sizeof(JSObject))
+ : i == GC_FREELIST_INDEX(sizeof(JSObject))
+ ? 0
+ : i];
+ ap = &arenaList->last;
+ if (!(a = *ap))
+ continue;
+
+ JS_ASSERT(arenaList->lastCount > 0);
+ arenaList->freeList = NULL;
+ freeList = NULL;
+ thingSize = arenaList->thingSize;
+ indexLimit = THINGS_PER_ARENA(thingSize);
+ flagp = THING_FLAGP(a, arenaList->lastCount - 1);
+ METER((nlivearenas = 0, nkilledarenas = 0, nthings = 0));
+ for (;;) {
+ JS_ASSERT(a->prevUntracedPage == 0);
+ JS_ASSERT(a->u.untracedThings == 0);
+ allClear = JS_TRUE;
+ do {
+ flags = *flagp;
+ if (flags & (GCF_MARK | GCF_LOCK)) {
+ *flagp &= ~GCF_MARK;
+ allClear = JS_FALSE;
+ METER(nthings++);
+ } else {
+ thing = FLAGP_TO_THING(flagp, thingSize);
+ if (!(flags & GCF_FINAL)) {
+ /*
+ * Call the finalizer with GCF_FINAL ORed into flags.
+ */
+ *flagp = (uint8)(flags | GCF_FINAL);
+ type = flags & GCF_TYPEMASK;
+ switch (type) {
+ case GCX_OBJECT:
+ js_FinalizeObject(cx, (JSObject *) thing);
+ break;
+ case GCX_DOUBLE:
+ /* Do nothing. */
+ break;
+#if JS_HAS_XML_SUPPORT
+ case GCX_XML:
+ js_FinalizeXML(cx, (JSXML *) thing);
+ break;
+#endif
+ default:
+ JS_ASSERT(type == GCX_STRING ||
+ type - GCX_EXTERNAL_STRING <
+ GCX_NTYPES - GCX_EXTERNAL_STRING);
+ js_FinalizeStringRT(rt, (JSString *) thing,
+ (intN) (type -
+ GCX_EXTERNAL_STRING),
+ cx);
+ break;
+ }
+#ifdef DEBUG
+ memset(thing, JS_FREE_PATTERN, thingSize);
+#endif
+ }
+ thing->flagp = flagp;
+ thing->next = freeList;
+ freeList = thing;
+ }
+ } while (++flagp != THING_FLAGS_END(a));
+
+ if (allClear) {
+ /*
+ * Forget just assembled free list head for the arena and
+ * add the arena itself to the destroy list.
+ */
+ freeList = arenaList->freeList;
+ if (a == arenaList->last)
+ arenaList->lastCount = (uint16) indexLimit;
+ *ap = a->prev;
+ a->prev = emptyArenas;
+ emptyArenas = a;
+ METER(nkilledarenas++);
+ } else {
+ arenaList->freeList = freeList;
+ ap = &a->prev;
+ METER(nlivearenas++);
+ }
+ if (!(a = *ap))
+ break;
+ flagp = THING_FLAGP(a, indexLimit - 1);
+ }
+
+ /*
+ * We use arenaList - &rt->gcArenaList[0], not i, as the stat index
+ * due to the enumeration reorder at the beginning of the loop.
+ */
+ METER(UpdateArenaStats(&rt->gcStats.arenaStats[arenaList -
+ &rt->gcArenaList[0]],
+ nlivearenas, nkilledarenas, nthings));
+ }
+
+#ifdef JS_THREADSAFE
+ /*
+ * Release all but two free list sets to avoid allocating a new set in
+ * js_NewGCThing.
+ */
+ TrimGCFreeListsPool(rt, 2);
+#endif
+
+ ap = &rt->gcDoubleArenaList.first;
+ METER((nlivearenas = 0, nkilledarenas = 0, nthings = 0));
+ while ((a = *ap) != NULL) {
+ if (!a->u.hasMarkedDoubles) {
+ /* No marked double values in the arena. */
+ *ap = a->prev;
+ a->prev = emptyArenas;
+ emptyArenas = a;
+ METER(nkilledarenas++);
+ } else {
+ ap = &a->prev;
+#ifdef JS_GCMETER
+ for (i = 0; i != DOUBLES_PER_ARENA; ++i) {
+ if (IsMarkedDouble(a, index))
+ METER(nthings++);
+ }
+ METER(nlivearenas++);
+#endif
+ }
+ }
+ METER(UpdateArenaStats(&rt->gcStats.doubleArenaStats,
+ nlivearenas, nkilledarenas, nthings));
+ rt->gcDoubleArenaList.nextDoubleFlags =
+ rt->gcDoubleArenaList.first
+ ? DOUBLE_ARENA_BITMAP(rt->gcDoubleArenaList.first)
+ : DOUBLE_BITMAP_SENTINEL;
+
+ /*
+ * Sweep the runtime's property tree after finalizing objects, in case any
+ * had watchpoints referencing tree nodes.
+ */
+ js_SweepScopeProperties(cx);
+
+ /*
+ * Sweep script filenames after sweeping functions in the generic loop
+ * above. In this way when a scripted function's finalizer destroys the
+ * script and calls rt->destroyScriptHook, the hook can still access the
+ * script's filename. See bug 323267.
+ */
+ js_SweepScriptFilenames(rt);
+
+ /*
+ * Destroy arenas after we finished the sweeping sofinalizers can safely
+ * use js_IsAboutToBeFinalized().
+ */
+ DestroyGCArenas(rt, emptyArenas);
+
+ if (rt->gcCallback)
+ (void) rt->gcCallback(cx, JSGC_FINALIZE_END);
+#ifdef DEBUG_srcnotesize
+ { extern void DumpSrcNoteSizeHist();
+ DumpSrcNoteSizeHist();
+ printf("GC HEAP SIZE %lu\n", (unsigned long)rt->gcBytes);
+ }
+#endif
+
+#ifdef JS_SCOPE_DEPTH_METER
+ { static FILE *fp;
+ if (!fp)
+ fp = fopen("/tmp/scopedepth.stats", "w");
+
+ if (fp) {
+ JS_DumpBasicStats(&rt->protoLookupDepthStats, "proto-lookup depth", fp);
+ JS_DumpBasicStats(&rt->scopeSearchDepthStats, "scope-search depth", fp);
+ JS_DumpBasicStats(&rt->hostenvScopeDepthStats, "hostenv scope depth", fp);
+ JS_DumpBasicStats(&rt->lexicalScopeDepthStats, "lexical scope depth", fp);
+
+ putc('\n', fp);
+ fflush(fp);
+ }
+ }
+#endif /* JS_SCOPE_DEPTH_METER */
+
+#ifdef JS_DUMP_LOOP_STATS
+ { static FILE *lsfp;
+ if (!lsfp)
+ lsfp = fopen("/tmp/loopstats", "w");
+ if (lsfp) {
+ JS_DumpBasicStats(&rt->loopStats, "loops", lsfp);
+ fflush(lsfp);
+ }
+ }
+#endif /* JS_DUMP_LOOP_STATS */
+
+#ifdef JS_TRACER
+out:
+#endif
+ JS_LOCK_GC(rt);
+
+ /*
+ * We want to restart GC if js_GC was called recursively or if any of the
+ * finalizers called js_RemoveRoot or js_UnlockGCThingRT.
+ */
+ if (rt->gcLevel > 1 || rt->gcPoke) {
+ rt->gcLevel = 1;
+ rt->gcPoke = JS_FALSE;
+ JS_UNLOCK_GC(rt);
+ goto restart;
+ }
+
+ if (rt->shapeGen >= SHAPE_OVERFLOW_BIT - 1) {
+ /*
+ * FIXME bug 440834: The shape id space has overflowed. Currently we
+ * cope badly with this. Every call to js_GenerateShape does GC, and
+ * we never re-enable the property cache.
+ */
+ js_DisablePropertyCache(cx);
+#ifdef JS_THREADSAFE
+ iter = NULL;
+ while ((acx = js_ContextIterator(rt, JS_FALSE, &iter)) != NULL) {
+ if (!acx->thread || acx->thread == cx->thread)
+ continue;
+ js_DisablePropertyCache(acx);
+ }
+#endif
+ }
+
+ rt->gcLastBytes = rt->gcBytes;
+ done_running:
+ rt->gcLevel = 0;
+ rt->gcRunning = JS_FALSE;
+
+#ifdef JS_THREADSAFE
+ /* If we were invoked during a request, pay back the temporary debit. */
+ if (requestDebit)
+ rt->requestCount += requestDebit;
+ rt->gcThread = NULL;
+ JS_NOTIFY_GC_DONE(rt);
+
+ /*
+ * Unlock unless we have GC_LOCK_HELD which requires locked GC on return.
+ */
+ if (!(gckind & GC_LOCK_HELD))
+ JS_UNLOCK_GC(rt);
+#endif
+
+ /*
+ * Execute JSGC_END callback outside the lock. Again, sample the callback
+ * pointer in case it changes, since we are outside of the GC vs. requests
+ * interlock mechanism here.
+ */
+ if (gckind != GC_SET_SLOT_REQUEST && (callback = rt->gcCallback)) {
+ JSWeakRoots savedWeakRoots;
+ JSTempValueRooter tvr;
+
+ if (gckind & GC_KEEP_ATOMS) {
+ /*
+ * We allow JSGC_END implementation to force a full GC or allocate
+ * new GC things. Thus we must protect the weak roots from garbage
+ * collection and overwrites.
+ */
+ savedWeakRoots = cx->weakRoots;
+ JS_PUSH_TEMP_ROOT_WEAK_COPY(cx, &savedWeakRoots, &tvr);
+ JS_KEEP_ATOMS(rt);
+ JS_UNLOCK_GC(rt);
+ }
+
+ (void) callback(cx, JSGC_END);
+
+ if (gckind & GC_KEEP_ATOMS) {
+ JS_LOCK_GC(rt);
+ JS_UNKEEP_ATOMS(rt);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ } else if (gckind == GC_LAST_CONTEXT && rt->gcPoke) {
+ /*
+ * On shutdown iterate until JSGC_END callback stops creating
+ * garbage.
+ */
+ goto restart_at_beginning;
+ }
+ }
+}
+
+void
+js_UpdateMallocCounter(JSContext *cx, size_t nbytes)
+{
+ uint32 *pbytes, bytes;
+
+#ifdef JS_THREADSAFE
+ pbytes = &cx->thread->gcMallocBytes;
+#else
+ pbytes = &cx->runtime->gcMallocBytes;
+#endif
+ bytes = *pbytes;
+ *pbytes = ((uint32)-1 - bytes <= nbytes) ? (uint32)-1 : bytes + nbytes;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsgc.h b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.h
new file mode 100644
index 0000000..a0634b2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsgc.h
@@ -0,0 +1,427 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsgc_h___
+#define jsgc_h___
+/*
+ * JS Garbage Collector.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsdhash.h"
+#include "jsbit.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+JS_STATIC_ASSERT(JSTRACE_STRING == 2);
+
+#define JSTRACE_XML 3
+
+/*
+ * One past the maximum trace kind.
+ */
+#define JSTRACE_LIMIT 4
+
+/*
+ * We use the trace kinds as the types for all GC things except external
+ * strings.
+ */
+#define GCX_OBJECT JSTRACE_OBJECT /* JSObject */
+#define GCX_DOUBLE JSTRACE_DOUBLE /* jsdouble */
+#define GCX_STRING JSTRACE_STRING /* JSString */
+#define GCX_XML JSTRACE_XML /* JSXML */
+#define GCX_EXTERNAL_STRING JSTRACE_LIMIT /* JSString with external
+ chars */
+/*
+ * The number of defined GC types.
+ */
+#define GCX_NTYPES (GCX_EXTERNAL_STRING + 8)
+
+/*
+ * The maximum limit for the number of GC types.
+ */
+#define GCX_LIMIT_LOG2 4 /* type index bits */
+#define GCX_LIMIT JS_BIT(GCX_LIMIT_LOG2)
+
+JS_STATIC_ASSERT(GCX_NTYPES <= GCX_LIMIT);
+
+/* GC flag definitions, must fit in 8 bits (type index goes in the low bits). */
+#define GCF_TYPEMASK JS_BITMASK(GCX_LIMIT_LOG2)
+#define GCF_MARK JS_BIT(GCX_LIMIT_LOG2)
+#define GCF_FINAL JS_BIT(GCX_LIMIT_LOG2 + 1)
+#define GCF_LOCKSHIFT (GCX_LIMIT_LOG2 + 2) /* lock bit shift */
+#define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
+
+/*
+ * Get the type of the external string or -1 if the string was not created
+ * with JS_NewExternalString.
+ */
+extern intN
+js_GetExternalStringGCType(JSString *str);
+
+extern JS_FRIEND_API(uint32)
+js_GetGCThingTraceKind(void *thing);
+
+/*
+ * The sole purpose of the function is to preserve public API compatibility
+ * in JS_GetStringBytes which takes only single JSString* argument.
+ */
+JSRuntime*
+js_GetGCStringRuntime(JSString *str);
+
+#if 1
+/*
+ * Since we're forcing a GC from JS_GC anyway, don't bother wasting cycles
+ * loading oldval. XXX remove implied force, fix jsinterp.c's "second arg
+ * ignored", etc.
+ */
+#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JS_TRUE)
+#else
+#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
+#endif
+
+/*
+ * Write barrier macro monitoring property update from oldval to newval in
+ * scope->object.
+ *
+ * Since oldval is used only for the branded scope case, and the oldval actual
+ * argument expression is typically not used otherwise by callers, performance
+ * benefits if oldval is *not* evaluated into a callsite temporary variable,
+ * and instead passed to GC_WRITE_BARRIER for conditional evaluation (we rely
+ * on modern compilers to do a good CSE job). Yay, C macros.
+ */
+#define GC_WRITE_BARRIER(cx,scope,oldval,newval) \
+ JS_BEGIN_MACRO \
+ if (SCOPE_IS_BRANDED(scope) && \
+ (oldval) != (newval) && \
+ (VALUE_IS_FUNCTION(cx,oldval) || VALUE_IS_FUNCTION(cx,newval))) { \
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope); \
+ } \
+ GC_POKE(cx, oldval); \
+ JS_END_MACRO
+
+extern JSBool
+js_InitGC(JSRuntime *rt, uint32 maxbytes);
+
+extern void
+js_FinishGC(JSRuntime *rt);
+
+extern intN
+js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
+ JSStringFinalizeOp newop);
+
+extern JSBool
+js_AddRoot(JSContext *cx, void *rp, const char *name);
+
+extern JSBool
+js_AddRootRT(JSRuntime *rt, void *rp, const char *name);
+
+extern JSBool
+js_RemoveRoot(JSRuntime *rt, void *rp);
+
+#ifdef DEBUG
+extern void
+js_DumpNamedRoots(JSRuntime *rt,
+ void (*dump)(const char *name, void *rp, void *data),
+ void *data);
+#endif
+
+extern uint32
+js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data);
+
+/* Table of pointers with count valid members. */
+typedef struct JSPtrTable {
+ size_t count;
+ void **array;
+} JSPtrTable;
+
+extern JSBool
+js_RegisterCloseableIterator(JSContext *cx, JSObject *obj);
+
+/*
+ * The private JSGCThing struct, which describes a gcFreeList element.
+ */
+struct JSGCThing {
+ JSGCThing *next;
+ uint8 *flagp;
+};
+
+#define GC_NBYTES_MAX (10 * sizeof(JSGCThing))
+#define GC_NUM_FREELISTS (GC_NBYTES_MAX / sizeof(JSGCThing))
+#define GC_FREELIST_NBYTES(i) (((i) + 1) * sizeof(JSGCThing))
+#define GC_FREELIST_INDEX(n) (((n) / sizeof(JSGCThing)) - 1)
+
+/*
+ * Allocates a new GC thing of the given size. After a successful allocation
+ * the caller must fully initialize the thing before calling any function that
+ * can potentially trigger GC. This will ensure that GC tracing never sees junk
+ * values stored in the partially initialized thing.
+ */
+extern void *
+js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
+
+/*
+ * Allocate a new double jsval and store the result in *vp. vp must be a root.
+ * The function does not copy the result into any weak root.
+ */
+extern JSBool
+js_NewDoubleInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
+
+/*
+ * Return a pointer to a new GC-allocated and weakly-rooted jsdouble number,
+ * or null when the allocation fails.
+ */
+extern jsdouble *
+js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
+
+extern JSBool
+js_LockGCThingRT(JSRuntime *rt, void *thing);
+
+extern JSBool
+js_UnlockGCThingRT(JSRuntime *rt, void *thing);
+
+extern JSBool
+js_IsAboutToBeFinalized(JSContext *cx, void *thing);
+
+/*
+ * Macro to test if a traversal is the marking phase of GC to avoid exposing
+ * ScriptFilenameEntry to traversal implementations.
+ */
+#define IS_GC_MARKING_TRACER(trc) ((trc)->callback == NULL)
+
+#if JS_HAS_XML_SUPPORT
+# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) < JSTRACE_LIMIT)
+#else
+# define JS_IS_VALID_TRACE_KIND(kind) ((uint32)(kind) <= JSTRACE_STRING)
+#endif
+
+/*
+ * JS_IS_VALID_TRACE_KIND assumes that JSTRACE_STRING is the last non-xml
+ * trace kind when JS_HAS_XML_SUPPORT is false.
+ */
+JS_STATIC_ASSERT(JSTRACE_STRING + 1 == JSTRACE_XML);
+
+/*
+ * Trace jsval when JSVAL_IS_OBJECT(v) can be an arbitrary GC thing casted as
+ * JSVAL_OBJECT and js_GetGCThingTraceKind has to be used to find the real
+ * type behind v.
+ */
+extern void
+js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
+
+extern void
+js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
+
+extern void
+js_TraceRuntime(JSTracer *trc, JSBool allAtoms);
+
+extern JS_FRIEND_API(void)
+js_TraceContext(JSTracer *trc, JSContext *acx);
+
+/*
+ * Kinds of js_GC invocation.
+ */
+typedef enum JSGCInvocationKind {
+ /* Normal invocation. */
+ GC_NORMAL = 0,
+
+ /*
+ * Called from js_DestroyContext for last JSContext in a JSRuntime, when
+ * it is imperative that rt->gcPoke gets cleared early in js_GC.
+ */
+ GC_LAST_CONTEXT = 1,
+
+ /*
+ * Flag bit telling js_GC that the caller has already acquired rt->gcLock.
+ * Currently, this flag is set for the invocation kinds that also preserve
+ * atoms and weak roots, so we don't need another bit for GC_KEEP_ATOMS.
+ */
+ GC_LOCK_HELD = 0x10,
+ GC_KEEP_ATOMS = GC_LOCK_HELD,
+
+ /*
+ * Called from js_SetProtoOrParent with a request to set an object's proto
+ * or parent slot inserted on rt->setSlotRequests.
+ */
+ GC_SET_SLOT_REQUEST = GC_LOCK_HELD | 1,
+
+ /*
+ * Called from js_NewGCThing as a last-ditch GC attempt. See comments in
+ * jsgc.c just before js_GC's definition for details.
+ */
+ GC_LAST_DITCH = GC_LOCK_HELD | 2
+} JSGCInvocationKind;
+
+extern void
+js_GC(JSContext *cx, JSGCInvocationKind gckind);
+
+/* Call this after succesful malloc of memory for GC-related things. */
+extern void
+js_UpdateMallocCounter(JSContext *cx, size_t nbytes);
+
+typedef struct JSGCArenaInfo JSGCArenaInfo;
+typedef struct JSGCArenaList JSGCArenaList;
+typedef struct JSGCChunkInfo JSGCChunkInfo;
+
+struct JSGCArenaList {
+ JSGCArenaInfo *last; /* last allocated GC arena */
+ uint16 lastCount; /* number of allocated things in the last
+ arena */
+ uint16 thingSize; /* size of things to allocate on this list
+ */
+ JSGCThing *freeList; /* list of free GC things */
+};
+
+typedef union JSGCDoubleCell JSGCDoubleCell;
+
+union JSGCDoubleCell {
+ double number;
+ JSGCDoubleCell *link;
+};
+
+JS_STATIC_ASSERT(sizeof(JSGCDoubleCell) == sizeof(double));
+
+typedef struct JSGCDoubleArenaList {
+ JSGCArenaInfo *first; /* first allocated GC arena */
+ jsbitmap *nextDoubleFlags; /* bitmask with flags to check for free
+ things */
+} JSGCDoubleArenaList;
+
+typedef struct JSGCFreeListSet JSGCFreeListSet;
+
+struct JSGCFreeListSet {
+ JSGCThing *array[GC_NUM_FREELISTS];
+ JSGCFreeListSet *link;
+};
+
+extern const JSGCFreeListSet js_GCEmptyFreeListSet;
+
+extern void
+js_RevokeGCLocalFreeLists(JSContext *cx);
+
+struct JSWeakRoots {
+ /* Most recently created things by type, members of the GC's root set. */
+ void *newborn[GCX_NTYPES];
+
+ /* Atom root for the last-looked-up atom on this context. */
+ jsval lastAtom;
+
+ /* Root for the result of the most recent js_InternalInvoke call. */
+ jsval lastInternalResult;
+};
+
+JS_STATIC_ASSERT(JSVAL_NULL == 0);
+#define JS_CLEAR_WEAK_ROOTS(wr) (memset((wr), 0, sizeof(JSWeakRoots)))
+
+/*
+ * Increase runtime->gcBytes by sz bytes to account for an allocation outside
+ * the GC that will be freed only after the GC is run. The function may run
+ * the last ditch GC to ensure that gcBytes does not exceed gcMaxBytes. It will
+ * fail if the latter is not possible.
+ *
+ * This function requires that runtime->gcLock is held on entry. On successful
+ * return the lock is still held and on failure it will be released with
+ * the error reported.
+ */
+extern JSBool
+js_AddAsGCBytes(JSContext *cx, size_t sz);
+
+extern void
+js_RemoveAsGCBytes(JSRuntime* rt, size_t sz);
+
+#ifdef DEBUG_notme
+#define JS_GCMETER 1
+#endif
+
+#ifdef JS_GCMETER
+
+typedef struct JSGCArenaStats {
+ uint32 alloc; /* allocation attempts */
+ uint32 localalloc; /* allocations from local lists */
+ uint32 retry; /* allocation retries after running the GC */
+ uint32 fail; /* allocation failures */
+ uint32 nthings; /* live GC things */
+ uint32 maxthings; /* maximum of live GC cells */
+ double totalthings; /* live GC things the GC scanned so far */
+ uint32 narenas; /* number of arena in list before the GC */
+ uint32 newarenas; /* new arenas allocated before the last GC */
+ uint32 livearenas; /* number of live arenas after the last GC */
+ uint32 maxarenas; /* maximum of allocated arenas */
+ uint32 totalarenas; /* total number of arenas with live things that
+ GC scanned so far */
+} JSGCArenaStats;
+
+typedef struct JSGCStats {
+ uint32 finalfail; /* finalizer calls allocator failures */
+ uint32 lockborn; /* things born locked */
+ uint32 lock; /* valid lock calls */
+ uint32 unlock; /* valid unlock calls */
+ uint32 depth; /* mark tail recursion depth */
+ uint32 maxdepth; /* maximum mark tail recursion depth */
+ uint32 cdepth; /* mark recursion depth of C functions */
+ uint32 maxcdepth; /* maximum mark recursion depth of C functions */
+ uint32 untraced; /* number of times tracing of GC thing's children were
+ delayed due to a low C stack */
+#ifdef DEBUG
+ uint32 maxuntraced;/* maximum number of things with children to trace
+ later */
+#endif
+ uint32 maxlevel; /* maximum GC nesting (indirect recursion) level */
+ uint32 poke; /* number of potentially useful GC calls */
+ uint32 afree; /* thing arenas freed so far */
+ uint32 stackseg; /* total extraordinary stack segments scanned */
+ uint32 segslots; /* total stack segment jsval slots scanned */
+ uint32 nclose; /* number of objects with close hooks */
+ uint32 maxnclose; /* max number of objects with close hooks */
+ uint32 closelater; /* number of close hooks scheduled to run */
+ uint32 maxcloselater; /* max number of close hooks scheduled to run */
+
+ JSGCArenaStats arenaStats[GC_NUM_FREELISTS];
+ JSGCArenaStats doubleArenaStats;
+} JSGCStats;
+
+extern JS_FRIEND_API(void)
+js_DumpGCStats(JSRuntime *rt, FILE *fp);
+
+#endif /* JS_GCMETER */
+
+JS_END_EXTERN_C
+
+#endif /* jsgc_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp
new file mode 100644
index 0000000..5fe5f78
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jshash.cpp
@@ -0,0 +1,476 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR hash table package.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+
+/* Compute the number of buckets in ht */
+#define NBUCKETS(ht) JS_BIT(JS_HASH_BITS - (ht)->shift)
+
+/* The smallest table has 16 buckets */
+#define MINBUCKETSLOG2 4
+#define MINBUCKETS JS_BIT(MINBUCKETSLOG2)
+
+/* Compute the maximum entries given n buckets that we will tolerate, ~90% */
+#define OVERLOADED(n) ((n) - ((n) >> 3))
+
+/* Compute the number of entries below which we shrink the table by half */
+#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0)
+
+/*
+** Stubs for default hash allocator ops.
+*/
+static void *
+DefaultAllocTable(void *pool, size_t size)
+{
+ return malloc(size);
+}
+
+static void
+DefaultFreeTable(void *pool, void *item)
+{
+ free(item);
+}
+
+static JSHashEntry *
+DefaultAllocEntry(void *pool, const void *key)
+{
+ return (JSHashEntry*) malloc(sizeof(JSHashEntry));
+}
+
+static void
+DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
+{
+ if (flag == HT_FREE_ENTRY)
+ free(he);
+}
+
+static JSHashAllocOps defaultHashAllocOps = {
+ DefaultAllocTable, DefaultFreeTable,
+ DefaultAllocEntry, DefaultFreeEntry
+};
+
+JS_PUBLIC_API(JSHashTable *)
+JS_NewHashTable(uint32 n, JSHashFunction keyHash,
+ JSHashComparator keyCompare, JSHashComparator valueCompare,
+ JSHashAllocOps *allocOps, void *allocPriv)
+{
+ JSHashTable *ht;
+ size_t nb;
+
+ if (n <= MINBUCKETS) {
+ n = MINBUCKETSLOG2;
+ } else {
+ n = JS_CeilingLog2(n);
+ if ((int32)n < 0)
+ return NULL;
+ }
+
+ if (!allocOps) allocOps = &defaultHashAllocOps;
+
+ ht = (JSHashTable*) allocOps->allocTable(allocPriv, sizeof *ht);
+ if (!ht)
+ return NULL;
+ memset(ht, 0, sizeof *ht);
+ ht->shift = JS_HASH_BITS - n;
+ n = JS_BIT(n);
+ nb = n * sizeof(JSHashEntry *);
+ ht->buckets = (JSHashEntry**) allocOps->allocTable(allocPriv, nb);
+ if (!ht->buckets) {
+ allocOps->freeTable(allocPriv, ht);
+ return NULL;
+ }
+ memset(ht->buckets, 0, nb);
+
+ ht->keyHash = keyHash;
+ ht->keyCompare = keyCompare;
+ ht->valueCompare = valueCompare;
+ ht->allocOps = allocOps;
+ ht->allocPriv = allocPriv;
+ return ht;
+}
+
+JS_PUBLIC_API(void)
+JS_HashTableDestroy(JSHashTable *ht)
+{
+ uint32 i, n;
+ JSHashEntry *he, **hep;
+ JSHashAllocOps *allocOps = ht->allocOps;
+ void *allocPriv = ht->allocPriv;
+
+ n = NBUCKETS(ht);
+ for (i = 0; i < n; i++) {
+ hep = &ht->buckets[i];
+ while ((he = *hep) != NULL) {
+ *hep = he->next;
+ allocOps->freeEntry(allocPriv, he, HT_FREE_ENTRY);
+ }
+ }
+#ifdef DEBUG
+ memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]);
+#endif
+ allocOps->freeTable(allocPriv, ht->buckets);
+#ifdef DEBUG
+ memset(ht, 0xDB, sizeof *ht);
+#endif
+ allocOps->freeTable(allocPriv, ht);
+}
+
+/*
+ * Multiplicative hash, from Knuth 6.4.
+ */
+#define BUCKET_HEAD(ht, keyHash) \
+ (&(ht)->buckets[((keyHash) * JS_GOLDEN_RATIO) >> (ht)->shift])
+
+JS_PUBLIC_API(JSHashEntry **)
+JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key)
+{
+ JSHashEntry *he, **hep, **hep0;
+
+#ifdef JS_HASHMETER
+ ht->nlookups++;
+#endif
+ hep = hep0 = BUCKET_HEAD(ht, keyHash);
+ while ((he = *hep) != NULL) {
+ if (he->keyHash == keyHash && ht->keyCompare(key, he->key)) {
+ /* Move to front of chain if not already there */
+ if (hep != hep0) {
+ *hep = he->next;
+ he->next = *hep0;
+ *hep0 = he;
+ }
+ return hep0;
+ }
+ hep = &he->next;
+#ifdef JS_HASHMETER
+ ht->nsteps++;
+#endif
+ }
+ return hep;
+}
+
+static JSBool
+Resize(JSHashTable *ht, uint32 newshift)
+{
+ size_t nb, nentries, i;
+ JSHashEntry **oldbuckets, *he, *next, **hep;
+#ifdef DEBUG
+ size_t nold = NBUCKETS(ht);
+#endif
+
+ JS_ASSERT(newshift < JS_HASH_BITS);
+
+ nb = (size_t)1 << (JS_HASH_BITS - newshift);
+
+ /* Integer overflow protection. */
+ if (nb > (size_t)-1 / sizeof(JSHashEntry*))
+ return JS_FALSE;
+ nb *= sizeof(JSHashEntry*);
+
+ oldbuckets = ht->buckets;
+ ht->buckets = (JSHashEntry**)ht->allocOps->allocTable(ht->allocPriv, nb);
+ if (!ht->buckets) {
+ ht->buckets = oldbuckets;
+ return JS_FALSE;
+ }
+ memset(ht->buckets, 0, nb);
+
+ ht->shift = newshift;
+ nentries = ht->nentries;
+
+ for (i = 0; nentries != 0; i++) {
+ for (he = oldbuckets[i]; he; he = next) {
+ JS_ASSERT(nentries != 0);
+ --nentries;
+ next = he->next;
+ hep = BUCKET_HEAD(ht, he->keyHash);
+
+ /*
+ * Since he comes from the old table, it must be unique and we
+ * simply add it to the head of bucket chain without chain lookup.
+ */
+ he->next = *hep;
+ *hep = he;
+ }
+ }
+#ifdef DEBUG
+ memset(oldbuckets, 0xDB, nold * sizeof oldbuckets[0]);
+#endif
+ ht->allocOps->freeTable(ht->allocPriv, oldbuckets);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep,
+ JSHashNumber keyHash, const void *key, void *value)
+{
+ uint32 n;
+ JSHashEntry *he;
+
+ /* Grow the table if it is overloaded */
+ n = NBUCKETS(ht);
+ if (ht->nentries >= OVERLOADED(n)) {
+ if (!Resize(ht, ht->shift - 1))
+ return NULL;
+#ifdef JS_HASHMETER
+ ht->ngrows++;
+#endif
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ }
+
+ /* Make a new key value entry */
+ he = ht->allocOps->allocEntry(ht->allocPriv, key);
+ if (!he)
+ return NULL;
+ he->keyHash = keyHash;
+ he->key = key;
+ he->value = value;
+ he->next = *hep;
+ *hep = he;
+ ht->nentries++;
+ return he;
+}
+
+JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
+{
+ JSHashNumber keyHash;
+ JSHashEntry *he, **hep;
+
+ keyHash = ht->keyHash(key);
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != NULL) {
+ /* Hit; see if values match */
+ if (ht->valueCompare(he->value, value)) {
+ /* key,value pair is already present in table */
+ return he;
+ }
+ if (he->value)
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_VALUE);
+ he->value = value;
+ return he;
+ }
+ return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
+}
+
+JS_PUBLIC_API(void)
+JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he)
+{
+ uint32 n;
+
+ *hep = he->next;
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
+
+ /* Shrink table if it's underloaded */
+ n = NBUCKETS(ht);
+ if (--ht->nentries < UNDERLOADED(n)) {
+ Resize(ht, ht->shift + 1);
+#ifdef JS_HASHMETER
+ ht->nshrinks++;
+#endif
+ }
+}
+
+JS_PUBLIC_API(JSBool)
+JS_HashTableRemove(JSHashTable *ht, const void *key)
+{
+ JSHashNumber keyHash;
+ JSHashEntry *he, **hep;
+
+ keyHash = ht->keyHash(key);
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) == NULL)
+ return JS_FALSE;
+
+ /* Hit; remove element */
+ JS_HashTableRawRemove(ht, hep, he);
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(void *)
+JS_HashTableLookup(JSHashTable *ht, const void *key)
+{
+ JSHashNumber keyHash;
+ JSHashEntry *he, **hep;
+
+ keyHash = ht->keyHash(key);
+ hep = JS_HashTableRawLookup(ht, keyHash, key);
+ if ((he = *hep) != NULL) {
+ return he->value;
+ }
+ return NULL;
+}
+
+/*
+** Iterate over the entries in the hash table calling func for each
+** entry found. Stop if "f" says to (return value & JS_ENUMERATE_STOP).
+** Return a count of the number of elements scanned.
+*/
+JS_PUBLIC_API(int)
+JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg)
+{
+ JSHashEntry *he, **hep, **bucket;
+ uint32 nlimit, n, nbuckets, newlog2;
+ int rv;
+
+ nlimit = ht->nentries;
+ n = 0;
+ for (bucket = ht->buckets; n != nlimit; ++bucket) {
+ hep = bucket;
+ while ((he = *hep) != NULL) {
+ JS_ASSERT(n < nlimit);
+ rv = f(he, n, arg);
+ n++;
+ if (rv & HT_ENUMERATE_REMOVE) {
+ *hep = he->next;
+ ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_ENTRY);
+ --ht->nentries;
+ } else {
+ hep = &he->next;
+ }
+ if (rv & HT_ENUMERATE_STOP) {
+ goto out;
+ }
+ }
+ }
+
+out:
+ /* Shrink table if removal of entries made it underloaded */
+ if (ht->nentries != nlimit) {
+ JS_ASSERT(ht->nentries < nlimit);
+ nbuckets = NBUCKETS(ht);
+ if (MINBUCKETS < nbuckets && ht->nentries < UNDERLOADED(nbuckets)) {
+ newlog2 = JS_CeilingLog2(ht->nentries);
+ if (newlog2 < MINBUCKETSLOG2)
+ newlog2 = MINBUCKETSLOG2;
+
+ /* Check that we really shrink the table. */
+ JS_ASSERT(JS_HASH_BITS - ht->shift > newlog2);
+ Resize(ht, JS_HASH_BITS - newlog2);
+ }
+ }
+ return (int)n;
+}
+
+#ifdef JS_HASHMETER
+#include <stdio.h>
+
+JS_PUBLIC_API(void)
+JS_HashTableDumpMeter(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
+{
+ double sqsum, mean, sigma;
+ uint32 nchains, nbuckets;
+ uint32 i, n, maxChain, maxChainLen;
+ JSHashEntry *he;
+
+ sqsum = 0;
+ nchains = 0;
+ maxChain = maxChainLen = 0;
+ nbuckets = NBUCKETS(ht);
+ for (i = 0; i < nbuckets; i++) {
+ he = ht->buckets[i];
+ if (!he)
+ continue;
+ nchains++;
+ for (n = 0; he; he = he->next)
+ n++;
+ sqsum += n * n;
+ if (n > maxChainLen) {
+ maxChainLen = n;
+ maxChain = i;
+ }
+ }
+
+ mean = JS_MeanAndStdDev(nchains, ht->nentries, sqsum, &sigma);
+
+ fprintf(fp, "\nHash table statistics:\n");
+ fprintf(fp, " number of lookups: %u\n", ht->nlookups);
+ fprintf(fp, " number of entries: %u\n", ht->nentries);
+ fprintf(fp, " number of grows: %u\n", ht->ngrows);
+ fprintf(fp, " number of shrinks: %u\n", ht->nshrinks);
+ fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps
+ / ht->nlookups);
+ fprintf(fp, "mean hash chain length: %g\n", mean);
+ fprintf(fp, " standard deviation: %g\n", sigma);
+ fprintf(fp, " max hash chain length: %u\n", maxChainLen);
+ fprintf(fp, " max hash chain: [%u]\n", maxChain);
+
+ for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++)
+ if (dump(he, i, fp) != HT_ENUMERATE_NEXT)
+ break;
+}
+#endif /* JS_HASHMETER */
+
+JS_PUBLIC_API(int)
+JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp)
+{
+ int count;
+
+ count = JS_HashTableEnumerateEntries(ht, dump, fp);
+#ifdef JS_HASHMETER
+ JS_HashTableDumpMeter(ht, dump, fp);
+#endif
+ return count;
+}
+
+JS_PUBLIC_API(JSHashNumber)
+JS_HashString(const void *key)
+{
+ JSHashNumber h;
+ const unsigned char *s;
+
+ h = 0;
+ for (s = (const unsigned char *)key; *s; s++)
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
+ return h;
+}
+
+JS_PUBLIC_API(int)
+JS_CompareValues(const void *v1, const void *v2)
+{
+ return v1 == v2;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jshash.h b/tools/node_modules/expresso/deps/jscoverage/js/jshash.h
new file mode 100644
index 0000000..defc193
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jshash.h
@@ -0,0 +1,151 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jshash_h___
+#define jshash_h___
+/*
+ * API to portable hash table code.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include "jstypes.h"
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef uint32 JSHashNumber;
+typedef struct JSHashEntry JSHashEntry;
+typedef struct JSHashTable JSHashTable;
+
+#define JS_HASH_BITS 32
+#define JS_GOLDEN_RATIO 0x9E3779B9U
+
+typedef JSHashNumber (* JSHashFunction)(const void *key);
+typedef intN (* JSHashComparator)(const void *v1, const void *v2);
+typedef intN (* JSHashEnumerator)(JSHashEntry *he, intN i, void *arg);
+
+/* Flag bits in JSHashEnumerator's return value */
+#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
+#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
+#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
+
+typedef struct JSHashAllocOps {
+ void * (*allocTable)(void *pool, size_t size);
+ void (*freeTable)(void *pool, void *item);
+ JSHashEntry * (*allocEntry)(void *pool, const void *key);
+ void (*freeEntry)(void *pool, JSHashEntry *he, uintN flag);
+} JSHashAllocOps;
+
+#define HT_FREE_VALUE 0 /* just free the entry's value */
+#define HT_FREE_ENTRY 1 /* free value and entire entry */
+
+struct JSHashEntry {
+ JSHashEntry *next; /* hash chain linkage */
+ JSHashNumber keyHash; /* key hash function result */
+ const void *key; /* ptr to opaque key */
+ void *value; /* ptr to opaque value */
+};
+
+struct JSHashTable {
+ JSHashEntry **buckets; /* vector of hash buckets */
+ uint32 nentries; /* number of entries in table */
+ uint32 shift; /* multiplicative hash shift */
+ JSHashFunction keyHash; /* key hash function */
+ JSHashComparator keyCompare; /* key comparison function */
+ JSHashComparator valueCompare; /* value comparison function */
+ JSHashAllocOps *allocOps; /* allocation operations */
+ void *allocPriv; /* allocation private data */
+#ifdef JS_HASHMETER
+ uint32 nlookups; /* total number of lookups */
+ uint32 nsteps; /* number of hash chains traversed */
+ uint32 ngrows; /* number of table expansions */
+ uint32 nshrinks; /* number of table contractions */
+#endif
+};
+
+/*
+ * Create a new hash table.
+ * If allocOps is null, use default allocator ops built on top of malloc().
+ */
+extern JS_PUBLIC_API(JSHashTable *)
+JS_NewHashTable(uint32 n, JSHashFunction keyHash,
+ JSHashComparator keyCompare, JSHashComparator valueCompare,
+ JSHashAllocOps *allocOps, void *allocPriv);
+
+extern JS_PUBLIC_API(void)
+JS_HashTableDestroy(JSHashTable *ht);
+
+/* Low level access methods */
+extern JS_PUBLIC_API(JSHashEntry **)
+JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key);
+
+extern JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep, JSHashNumber keyHash,
+ const void *key, void *value);
+
+extern JS_PUBLIC_API(void)
+JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he);
+
+/* Higher level access methods */
+extern JS_PUBLIC_API(JSHashEntry *)
+JS_HashTableAdd(JSHashTable *ht, const void *key, void *value);
+
+extern JS_PUBLIC_API(JSBool)
+JS_HashTableRemove(JSHashTable *ht, const void *key);
+
+extern JS_PUBLIC_API(intN)
+JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg);
+
+extern JS_PUBLIC_API(void *)
+JS_HashTableLookup(JSHashTable *ht, const void *key);
+
+extern JS_PUBLIC_API(intN)
+JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp);
+
+/* General-purpose C string hash function. */
+extern JS_PUBLIC_API(JSHashNumber)
+JS_HashString(const void *key);
+
+/* Stub function just returns v1 == v2 */
+extern JS_PUBLIC_API(intN)
+JS_CompareValues(const void *v1, const void *v2);
+
+JS_END_EXTERN_C
+
+#endif /* jshash_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsify.pl b/tools/node_modules/expresso/deps/jscoverage/js/jsify.pl
new file mode 100644
index 0000000..0ce2186
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsify.pl
@@ -0,0 +1,483 @@
+#!/usr/local/bin/perl
+
+# This script modifies C code to use the hijacked NSPR routines that are
+# now baked into the JavaScript engine rather than using the NSPR
+# routines that they were based on, i.e. types like PRArenaPool are changed
+# to JSArenaPool.
+#
+# This script was used in 9/98 to facilitate the incorporation of some NSPR
+# code into the JS engine so as to minimize dependency on NSPR.
+#
+
+# Command-line: jsify.pl [options] [filename]*
+#
+# Options:
+# -r Reverse direction of transformation, i.e. JS ==> NSPR2
+# -outdir Directory in which to place output files
+
+
+# NSPR2 symbols that will be modified to JS symbols, e.g.
+# PRArena <==> JSArena
+
+@NSPR_symbols = (
+"PRArena",
+"PRArenaPool",
+"PRArenaStats",
+"PR_ARENAMETER",
+"PR_ARENA_",
+"PR_ARENA_ALIGN",
+"PR_ARENA_ALLOCATE",
+"PR_ARENA_CONST_ALIGN_MASK",
+"PR_ARENA_DEFAULT_ALIGN",
+"PR_ARENA_DESTROY",
+"PR_ARENA_GROW",
+"PR_ARENA_MARK",
+"PR_ARENA_RELEASE",
+
+"PR_smprintf",
+"PR_smprintf_free",
+"PR_snprintf",
+"PR_sprintf_append",
+"PR_sscanf",
+"PR_sxprintf",
+"PR_vsmprintf",
+"PR_vsnprintf",
+"PR_vsprintf_append",
+"PR_vsxprintf",
+
+"PRCList",
+"PRCListStr",
+"PRCLists",
+
+"PRDestroyEventProc",
+"PREvent",
+"PREventFunProc",
+"PREventQueue",
+"PRHandleEventProc",
+"PR_PostEvent",
+"PR_PostSynchronousEvent",
+"PR_ProcessPendingEvents",
+"PR_CreateEventQueue",
+"PR_DequeueEvent",
+"PR_DestroyEvent",
+"PR_DestroyEventQueue",
+"PR_EventAvailable",
+"PR_EventLoop",
+"PR_GetEvent",
+"PR_GetEventOwner",
+"PR_GetEventQueueMonitor",
+"PR_GetEventQueueSelectFD",
+"PR_GetMainEventQueue",
+"PR_HandleEvent",
+"PR_InitEvent",
+"PR_ENTER_EVENT_QUEUE_MONITOR",
+"PR_EXIT_EVENT_QUEUE_MONITOR",
+"PR_MapEvents",
+"PR_RevokeEvents",
+
+"PR_cnvtf",
+"PR_dtoa",
+"PR_strtod",
+
+"PRFileDesc",
+
+"PR_HASH_BITS",
+"PR_GOLDEN_RATIO",
+"PRHashAllocOps",
+"PRHashComparator",
+"PRHashEntry",
+"PRHashEnumerator",
+"PRHashFunction",
+"PRHashNumber",
+"PRHashTable",
+"PR_HashString",
+"PR_HashTableAdd",
+"PR_HashTableDestroy",
+"PR_HashTableDump",
+"PR_HashTableEnumerateEntries",
+"PR_HashTableLookup",
+"PR_HashTableRawAdd",
+"PR_HashTableRawLookup",
+"PR_HashTableRawRemove",
+"PR_HashTableRemove",
+
+"PRBool",
+"PRFloat64",
+"PRInt16",
+"PRInt32",
+"PRInt64",
+"PRInt8",
+"PRIntn",
+"PRUint16",
+"PRUint32",
+"PRUint64",
+"PRUint8",
+"PRUintn",
+"PRPtrDiff",
+"PRPtrdiff",
+"PRUptrdiff",
+"PRUword",
+"PRWord",
+"PRPackedBool",
+"PRSize",
+"PRStatus",
+"pruword",
+"prword",
+"prword_t",
+
+"PR_ALIGN_OF_DOUBLE",
+"PR_ALIGN_OF_FLOAT",
+"PR_ALIGN_OF_INT",
+"PR_ALIGN_OF_INT64",
+"PR_ALIGN_OF_LONG",
+"PR_ALIGN_OF_POINTER",
+"PR_ALIGN_OF_SHORT",
+"PR_ALIGN_OF_WORD",
+"PR_BITS_PER_BYTE",
+"PR_BITS_PER_BYTE_LOG2",
+"PR_BITS_PER_DOUBLE",
+"PR_BITS_PER_DOUBLE_LOG2",
+"PR_BITS_PER_FLOAT",
+"PR_BITS_PER_FLOAT_LOG2",
+"PR_BITS_PER_INT",
+"PR_BITS_PER_INT64",
+"PR_BITS_PER_INT64_LOG2",
+"PR_BITS_PER_INT_LOG2",
+"PR_BITS_PER_LONG",
+"PR_BITS_PER_LONG_LOG2",
+"PR_BITS_PER_SHORT",
+"PR_BITS_PER_SHORT_LOG2",
+"PR_BITS_PER_WORD",
+"PR_BITS_PER_WORD_LOG2",
+"PR_BYTES_PER_BYTE",
+"PR_BYTES_PER_DOUBLE",
+"PR_BYTES_PER_DWORD",
+"PR_BYTES_PER_DWORD_LOG2",
+"PR_BYTES_PER_FLOAT",
+"PR_BYTES_PER_INT",
+"PR_BYTES_PER_INT64",
+"PR_BYTES_PER_LONG",
+"PR_BYTES_PER_SHORT",
+"PR_BYTES_PER_WORD",
+"PR_BYTES_PER_WORD_LOG2",
+
+"PRSegment",
+"PRSegmentAccess",
+"PRStuffFunc",
+"PRThread",
+
+"PR_APPEND_LINK",
+
+"PR_ASSERT",
+
+"PR_ATOMIC_DWORD_LOAD",
+"PR_ATOMIC_DWORD_STORE",
+
+"PR_Abort",
+
+"PR_ArenaAllocate",
+"PR_ArenaCountAllocation",
+"PR_ArenaCountGrowth",
+"PR_ArenaCountInplaceGrowth",
+"PR_ArenaCountRelease",
+"PR_ArenaCountRetract",
+"PR_ArenaFinish",
+"PR_ArenaGrow",
+"PR_ArenaRelease",
+"PR_CompactArenaPool",
+"PR_DumpArenaStats",
+"PR_FinishArenaPool",
+"PR_FreeArenaPool",
+"PR_InitArenaPool",
+
+"PR_Assert",
+
+"PR_AttachThread",
+
+"PR_BEGIN_EXTERN_C",
+"PR_BEGIN_MACRO",
+
+"PR_BIT",
+"PR_BITMASK",
+
+"PR_BUFFER_OVERFLOW_ERROR",
+
+"PR_CALLBACK",
+"PR_CALLBACK_DECL",
+"PR_CALLOC",
+"PR_CEILING_LOG2",
+"PR_CLEAR_ARENA",
+"PR_CLEAR_BIT",
+"PR_CLEAR_UNUSED",
+"PR_CLIST_IS_EMPTY",
+"PR_COUNT_ARENA",
+"PR_CURRENT_THREAD",
+
+"PR_GetSegmentAccess",
+"PR_GetSegmentSize",
+"PR_GetSegmentVaddr",
+"PR_GrowSegment",
+"PR_DestroySegment",
+"PR_MapSegment",
+"PR_NewSegment",
+"PR_Segment",
+"PR_Seg",
+"PR_SEGMENT_NONE",
+"PR_SEGMENT_RDONLY",
+"PR_SEGMENT_RDWR",
+
+"PR_Calloc",
+"PR_CeilingLog2",
+"PR_CompareStrings",
+"PR_CompareValues",
+"PR_DELETE",
+"PR_END_EXTERN_C",
+"PR_END_MACRO",
+"PR_ENUMERATE_STOP",
+"PR_FAILURE",
+"PR_FALSE",
+"PR_FLOOR_LOG2",
+"PR_FREEIF",
+"PR_FREE_PATTERN",
+"PR_FloorLog2",
+"PR_FormatTime",
+"PR_Free",
+
+"PR_GetEnv",
+"PR_GetError",
+"PR_INIT_ARENA_POOL",
+"PR_INIT_CLIST",
+"PR_INIT_STATIC_CLIST",
+"PR_INLINE",
+"PR_INSERT_AFTER",
+"PR_INSERT_BEFORE",
+"PR_INSERT_LINK",
+"PR_INT32",
+"PR_INTERVAL_NO_TIMEOUT",
+"PR_INTERVAL_NO_WAIT",
+"PR_Init",
+"PR_LIST_HEAD",
+"PR_LIST_TAIL",
+"PR_LOG",
+"PR_LOGGING",
+"PR_LOG_ALWAYS",
+"PR_LOG_BEGIN",
+"PR_LOG_DEBUG",
+"PR_LOG_DEFINE",
+"PR_LOG_END",
+"PR_LOG_ERROR",
+"PR_LOG_MAX",
+"PR_LOG_MIN",
+"PR_LOG_NONE",
+"PR_LOG_NOTICE",
+"PR_LOG_TEST",
+"PR_LOG_WARN",
+"PR_LOG_WARNING",
+"PR_LogFlush",
+"PR_LogPrint",
+"PR_MALLOC",
+"PR_MAX",
+"PR_MD_calloc",
+"PR_MD_free",
+"PR_MD_malloc",
+"PR_MD_realloc",
+"PR_MIN",
+"PR_Malloc",
+"PR_NEW",
+"PR_NEWZAP",
+"PR_NEXT_LINK",
+"PR_NOT_REACHED",
+"PR_NewCondVar",
+"PR_NewHashTable",
+"PR_NewLogModule",
+"PR_PREV_LINK",
+"PR_PUBLIC_API",
+"PR_PUBLIC_DATA",
+"PR_RANGE_ERROR",
+"PR_REALLOC",
+"PR_REMOVE_AND_INIT_LINK",
+"PR_REMOVE_LINK",
+"PR_ROUNDUP",
+"PR_Realloc",
+
+"PR_SET_BIT",
+"PR_STATIC_CALLBACK",
+"PR_SUCCESS",
+"PR_SetError",
+"PR_SetLogBuffering",
+"PR_SetLogFile",
+
+"PR_TEST_BIT",
+"PR_TRUE",
+"PR_UINT32",
+"PR_UPTRDIFF",
+
+"prarena_h___",
+"prbit_h___",
+"prclist_h___",
+"prdtoa_h___",
+"prlog_h___",
+"prlong_h___",
+"prmacos_h___",
+"prmem_h___",
+"prprf_h___",
+"prtypes_h___",
+
+"prarena",
+"prbit",
+"prbitmap_t",
+"prclist",
+"prcpucfg",
+"prdtoa",
+"prhash",
+"plhash",
+"prlong",
+"prmacos",
+"prmem",
+"prosdep",
+"protypes",
+"prprf",
+"prtypes"
+);
+
+while ($ARGV[0] =~ /^-/) {
+ if ($ARGV[0] eq "-r") {
+ shift;
+ $reverse_conversion = 1;
+ } elsif ($ARGV[0] eq "-outdir") {
+ shift;
+ $outdir = shift;
+ }
+}
+
+# Given an NSPR symbol compute the JS equivalent or
+# vice-versa
+sub subst {
+ local ($replacement);
+ local ($sym) = @_;
+
+ $replacement = substr($sym,0,2) eq "pr" ? "js" : "JS";
+ $replacement .= substr($sym, 2);
+ return $replacement;
+}
+
+# Build the regular expression that will convert between the NSPR
+# types and the JS types
+if ($reverse_conversion) {
+ die "Not implemented yet";
+} else {
+ foreach $sym (@NSPR_symbols) {
+ $regexp .= $sym . "|"
+ }
+ # Get rid of the last "!"
+ chop $regexp;
+
+ # Replace PR* with JS* and replace pr* with js*
+ $regexp = 's/(^|\\W)(' . $regexp . ')/$1 . &subst($2)/eg';
+# print $regexp;
+}
+
+# Pre-compile a little subroutine to perform the regexp substitution
+# between NSPR types and JS types
+eval('sub convert_from_NSPR {($line) = @_; $line =~ ' . $regexp . ';}');
+
+sub convert_mallocs {
+ ($line) = @_;
+ $line =~ s/PR_MALLOC/malloc/g;
+ $line =~ s/PR_REALLOC/realloc/g;
+ $line =~ s/PR_FREE/free/g;
+ return $line;
+}
+
+sub convert_includes {
+ ($line) = @_;
+ if ($line !~ /include/) {
+ return $line;
+ }
+
+ if ($line =~ /prlog\.h/) {
+ $line = '#include "jsutil.h"'. " /* Added by JSIFY */\n";
+ } elsif ($line =~ /plhash\.h/) {
+ $line = '#include "jshash.h"'. " /* Added by JSIFY */\n";
+ } elsif ($line =~ /plarena\.h/) {
+ $line = '#include "jsarena.h"'. " /* Added by JSIFY */\n";
+ } elsif ($line =~ /prmem\.h/) {
+ $line = "";
+ } elsif ($line =~ /jsmsg\.def/) {
+ $line = '#include "js.msg"' . "\n";
+ } elsif ($line =~ /shellmsg\.def/) {
+ $line = '#include "jsshell.msg"' . "\n";
+ } elsif ($line =~ /jsopcode\.def/) {
+ $line = '#include "jsopcode.tbl"' . "\n";
+ }
+ return $line;
+}
+
+sub convert_declarations {
+ ($line) = @_;
+ $line =~ s/PR_EXTERN/JS_EXTERN_API/g;
+ $line =~ s/PR_IMPLEMENT_DATA/JS_EXPORT_DATA/g;
+ $line =~ s/PR_IMPLEMENT/JS_EXPORT_API/g;
+ $line =~ s/PR_IMPORT/JS_IMPORT/g;
+ $line =~ s/PR_PUBLIC_API/JS_EXPORT_API/g;
+ $line =~ s/PR_PUBLIC_DATA/JS_EXPORT_DATA/g;
+ return $line;
+}
+
+sub convert_long_long_macros {
+ ($line) = @_;
+ $line =~ s/\b(LL_)/JSLL_/g;
+ return $line;
+}
+
+sub convert_asserts {
+ ($line) = @_;
+ $line =~ s/\bPR_ASSERT/JS_ASSERT/g;
+ return $line;
+}
+
+while ($#ARGV >= 0) {
+ $infile = shift;
+
+ # Change filename, e.g. prtime.h to jsprtime.h, except for legacy
+ # files that start with 'prmj', like prmjtime.h.
+ $outfile = $infile;
+ if ($infile !~ /^prmj/) {
+ $outfile =~ s/^pr/js/;
+ $outfile =~ s/^pl/js/;
+ }
+
+ if ($outdir) {
+ $outfile = $outdir . '/' . $outfile;
+ }
+
+ if ($infile eq $outfile) {
+ die "Error: refuse to overwrite $outfile, use -outdir option."
+ }
+ die "Can't open $infile" if !open(INFILE, "<$infile");
+ die "Can't open $outfile for writing" if !open(OUTFILE, ">$outfile");
+
+ while (<INFILE>) {
+ $line = $_;
+
+ #Get rid of #include "prlog.h"
+ &convert_includes($line);
+
+ # Rename PR_EXTERN, PR_IMPORT, etc.
+ &convert_declarations($line);
+
+ # Convert from PR_MALLOC to malloc, etc.
+ &convert_mallocs($line);
+
+ # Convert from PR_ASSERT to JS_ASSERT
+# &convert_asserts($line);
+
+ # Convert from, e.g. PRArena to JSPRArena
+ &convert_from_NSPR($line);
+
+ # Change LL_* macros to JSLL_*
+ &convert_long_long_macros($line);
+
+ print OUTFILE $line;
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp
new file mode 100644
index 0000000..3131507
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.cpp
@@ -0,0 +1,7225 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript bytecode interpreter.
+ */
+#include "jsstddef.h"
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+#include "jstracer.h"
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+#include "jsdtracef.h"
+#endif
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#include "jsautooplen.h"
+
+/* jsinvoke_cpp___ indicates inclusion from jsinvoke.cpp. */
+#if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___
+
+uint32
+js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop)
+{
+ JSRuntime *rt;
+ uint32 shape;
+ JSTempValueRooter tvr;
+
+ rt = cx->runtime;
+ shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
+ JS_ASSERT(shape != 0);
+ if (shape & SHAPE_OVERFLOW_BIT) {
+ rt->gcPoke = JS_TRUE;
+ if (sprop)
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
+ js_GC(cx, gcLocked ? GC_LOCK_HELD : GC_NORMAL);
+ if (sprop)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);
+ JS_ASSERT(shape != 0);
+ JS_ASSERT_IF(shape & SHAPE_OVERFLOW_BIT,
+ JS_PROPERTY_CACHE(cx).disabled);
+ }
+ return shape;
+}
+
+void
+js_FillPropertyCache(JSContext *cx, JSObject *obj, jsuword kshape,
+ uintN scopeIndex, uintN protoIndex,
+ JSObject *pobj, JSScopeProperty *sprop,
+ JSPropCacheEntry **entryp)
+{
+ JSPropertyCache *cache;
+ jsbytecode *pc;
+ JSScope *scope;
+ JSOp op;
+ const JSCodeSpec *cs;
+ jsuword vword;
+ ptrdiff_t pcoff;
+ jsuword khash;
+ JSAtom *atom;
+ JSPropCacheEntry *entry;
+
+ JS_ASSERT(!cx->runtime->gcRunning);
+ cache = &JS_PROPERTY_CACHE(cx);
+ pc = cx->fp->regs->pc;
+ if (cache->disabled || (cx->fp->flags & JSFRAME_EVAL)) {
+ PCMETER(cache->disfills++);
+ *entryp = NULL;
+ return;
+ }
+
+ /*
+ * Check for fill from js_SetPropertyHelper where the setter removed sprop
+ * from pobj's scope (via unwatch or delete, e.g.).
+ */
+ scope = OBJ_SCOPE(pobj);
+ JS_ASSERT(scope->object == pobj);
+ if (!SCOPE_HAS_PROPERTY(scope, sprop)) {
+ PCMETER(cache->oddfills++);
+ *entryp = NULL;
+ return;
+ }
+
+ /*
+ * Check for overdeep scope and prototype chain. Because resolve, getter,
+ * and setter hooks can change the prototype chain using JS_SetPrototype
+ * after js_LookupPropertyWithFlags has returned the nominal protoIndex,
+ * we have to validate protoIndex if it is non-zero. If it is zero, then
+ * we know thanks to the SCOPE_HAS_PROPERTY test above, and from the fact
+ * that obj == pobj, that protoIndex is invariant.
+ *
+ * The scopeIndex can't be wrong. We require JS_SetParent calls to happen
+ * before any running script might consult a parent-linked scope chain. If
+ * this requirement is not satisfied, the fill in progress will never hit,
+ * but vcap vs. scope shape tests ensure nothing malfunctions.
+ */
+ JS_ASSERT_IF(scopeIndex == 0 && protoIndex == 0, obj == pobj);
+ if (protoIndex != 0) {
+ JSObject *tmp;
+
+ JS_ASSERT(pobj != obj);
+ protoIndex = 1;
+ tmp = obj;
+ for (;;) {
+ tmp = OBJ_GET_PROTO(cx, tmp);
+ if (!tmp) {
+ PCMETER(cache->noprotos++);
+ *entryp = NULL;
+ return;
+ }
+ if (tmp == pobj)
+ break;
+ ++protoIndex;
+ }
+ }
+ if (scopeIndex > PCVCAP_SCOPEMASK || protoIndex > PCVCAP_PROTOMASK) {
+ PCMETER(cache->longchains++);
+ *entryp = NULL;
+ return;
+ }
+
+ /*
+ * Optimize the cached vword based on our parameters and the current pc's
+ * opcode format flags.
+ */
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+
+ do {
+ /*
+ * Check for a prototype "plain old method" callee computation. What
+ * is a plain old method? It's a function-valued property with stub
+ * getter and setter, so get of a function is idempotent and set is
+ * transparent.
+ */
+ if (cs->format & JOF_CALLOP) {
+ if (SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ jsval v;
+
+ v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ /*
+ * Great, we have a function-valued prototype property
+ * where the getter is JS_PropertyStub. The type id in
+ * pobj's scope does not evolve with changes to property
+ * values, however.
+ *
+ * So here, on first cache fill for this method, we brand
+ * the scope with a new shape and set the SCOPE_BRANDED
+ * flag. Once this scope flag is set, any write that adds
+ * or deletes a function-valued plain old property in
+ * scope->object will result in shape being regenerated.
+ */
+ if (!SCOPE_IS_BRANDED(scope)) {
+ PCMETER(cache->brandfills++);
+#ifdef DEBUG_notme
+ fprintf(stderr,
+ "branding %p (%s) for funobj %p (%s), kshape %lu\n",
+ pobj, LOCKED_OBJ_GET_CLASS(pobj)->name,
+ JSVAL_TO_OBJECT(v),
+ JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx,
+ JSVAL_TO_OBJECT(v))),
+ kshape);
+#endif
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ SCOPE_SET_BRANDED(scope);
+ kshape = scope->shape;
+ }
+ vword = JSVAL_OBJECT_TO_PCVAL(v);
+ break;
+ }
+ }
+ }
+
+ /* If getting a value via a stub getter, we can cache the slot. */
+ if (!(cs->format & JOF_SET) &&
+ SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ /* Great, let's cache sprop's slot and use it on cache hit. */
+ vword = SLOT_TO_PCVAL(sprop->slot);
+ } else {
+ /* Best we can do is to cache sprop (still a nice speedup). */
+ vword = SPROP_TO_PCVAL(sprop);
+ }
+ } while (0);
+
+ /*
+ * Our caller preserved the scope shape prior to the js_GetPropertyHelper
+ * or similar call out of the interpreter. We want to cache under that
+ * shape if op is overtly mutating, to bias for the case where the mutator
+ * udpates shape predictably.
+ *
+ * Note that an apparently non-mutating op such as JSOP_NAME may still
+ * mutate the base object via, e.g., lazy standard class initialization,
+ * but that is a one-time event and we'll have to miss the old shape and
+ * re-fill under the new one.
+ */
+ if (!(cs->format & (JOF_SET | JOF_INCDEC)) && obj == pobj)
+ kshape = scope->shape;
+
+ khash = PROPERTY_CACHE_HASH_PC(pc, kshape);
+ if (obj == pobj) {
+ JS_ASSERT(kshape != 0 || scope->shape != 0);
+ JS_ASSERT(scopeIndex == 0 && protoIndex == 0);
+ JS_ASSERT(OBJ_SCOPE(obj)->object == obj);
+ } else {
+ if (op == JSOP_LENGTH) {
+ atom = cx->runtime->atomState.lengthAtom;
+ } else {
+ pcoff = (JOF_TYPE(cs->format) == JOF_SLOTATOM) ? 2 : 0;
+ GET_ATOM_FROM_BYTECODE(cx->fp->script, pc, pcoff, atom);
+ }
+ JS_ASSERT_IF(scopeIndex == 0,
+ protoIndex != 1 || OBJ_GET_PROTO(cx, obj) == pobj);
+ if (scopeIndex != 0 || protoIndex != 1) {
+ khash = PROPERTY_CACHE_HASH_ATOM(atom, obj, pobj);
+ PCMETER(if (PCVCAP_TAG(cache->table[khash].vcap) <= 1)
+ cache->pcrecycles++);
+ pc = (jsbytecode *) atom;
+ kshape = (jsuword) obj;
+ }
+ }
+
+ entry = &cache->table[khash];
+ PCMETER(if (entry != *entryp) cache->modfills++);
+ PCMETER(if (!PCVAL_IS_NULL(entry->vword)) cache->recycles++);
+ entry->kpc = pc;
+ entry->kshape = kshape;
+ entry->vcap = PCVCAP_MAKE(scope->shape, scopeIndex, protoIndex);
+ entry->vword = vword;
+ *entryp = entry;
+
+ cache->empty = JS_FALSE;
+ PCMETER(cache->fills++);
+}
+
+JSAtom *
+js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc,
+ JSObject **objp, JSObject **pobjp,
+ JSPropCacheEntry **entryp)
+{
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t pcoff;
+ JSAtom *atom;
+ JSObject *obj, *pobj, *tmp;
+ JSPropCacheEntry *entry;
+ uint32 vcap;
+
+ JS_ASSERT(uintN((cx->fp->imacpc ? cx->fp->imacpc : pc) - cx->fp->script->code)
+ < cx->fp->script->length);
+
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ if (op == JSOP_LENGTH) {
+ atom = cx->runtime->atomState.lengthAtom;
+ } else {
+ pcoff = (JOF_TYPE(cs->format) == JOF_SLOTATOM) ? 2 : 0;
+ GET_ATOM_FROM_BYTECODE(cx->fp->script, pc, pcoff, atom);
+ }
+
+ obj = *objp;
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ entry = &JS_PROPERTY_CACHE(cx).table[PROPERTY_CACHE_HASH_ATOM(atom, obj, NULL)];
+ *entryp = entry;
+ vcap = entry->vcap;
+
+ if (entry->kpc != (jsbytecode *) atom) {
+ PCMETER(JS_PROPERTY_CACHE(cx).idmisses++);
+
+#ifdef DEBUG_notme
+ entry = &JS_PROPERTY_CACHE(cx).table[PROPERTY_CACHE_HASH_PC(pc, OBJ_SHAPE(obj))];
+ fprintf(stderr,
+ "id miss for %s from %s:%u"
+ " (pc %u, kpc %u, kshape %u, shape %u)\n",
+ js_AtomToPrintableString(cx, atom),
+ cx->fp->script->filename,
+ js_PCToLineNumber(cx, cx->fp->script, pc),
+ pc - cx->fp->script->code,
+ entry->kpc - cx->fp->script->code,
+ entry->kshape,
+ OBJ_SHAPE(obj));
+ js_Disassemble1(cx, cx->fp->script, pc,
+ PTRDIFF(pc, cx->fp->script->code, jsbytecode),
+ JS_FALSE, stderr);
+#endif
+
+ return atom;
+ }
+
+ if (entry->kshape != (jsuword) obj) {
+ PCMETER(JS_PROPERTY_CACHE(cx).komisses++);
+ return atom;
+ }
+
+ pobj = obj;
+ JS_LOCK_OBJ(cx, pobj);
+
+ if (JOF_MODE(cs->format) == JOF_NAME) {
+ while (vcap & (PCVCAP_SCOPEMASK << PCVCAP_PROTOBITS)) {
+ tmp = LOCKED_OBJ_GET_PARENT(pobj);
+ if (!tmp || !OBJ_IS_NATIVE(tmp))
+ break;
+ JS_UNLOCK_OBJ(cx, pobj);
+ pobj = tmp;
+ JS_LOCK_OBJ(cx, pobj);
+ vcap -= PCVCAP_PROTOSIZE;
+ }
+
+ *objp = pobj;
+ }
+
+ while (vcap & PCVCAP_PROTOMASK) {
+ tmp = LOCKED_OBJ_GET_PROTO(pobj);
+ if (!tmp || !OBJ_IS_NATIVE(tmp))
+ break;
+ JS_UNLOCK_OBJ(cx, pobj);
+ pobj = tmp;
+ JS_LOCK_OBJ(cx, pobj);
+ --vcap;
+ }
+
+ if (PCVCAP_SHAPE(vcap) == OBJ_SHAPE(pobj)) {
+#ifdef DEBUG
+ jsid id = ATOM_TO_JSID(atom);
+
+ CHECK_FOR_STRING_INDEX(id);
+ JS_ASSERT(SCOPE_GET_PROPERTY(OBJ_SCOPE(pobj), id));
+ JS_ASSERT(OBJ_SCOPE(pobj)->object == pobj);
+#endif
+ *pobjp = pobj;
+ return NULL;
+ }
+
+ PCMETER(JS_PROPERTY_CACHE(cx).vcmisses++);
+ JS_UNLOCK_OBJ(cx, pobj);
+ return atom;
+}
+
+#ifdef DEBUG
+#define ASSERT_CACHE_IS_EMPTY(cache) \
+ JS_BEGIN_MACRO \
+ JSPropertyCache *cache_ = (cache); \
+ uintN i_; \
+ JS_ASSERT(cache_->empty); \
+ for (i_ = 0; i_ < PROPERTY_CACHE_SIZE; i_++) { \
+ JS_ASSERT(!cache_->table[i_].kpc); \
+ JS_ASSERT(!cache_->table[i_].kshape); \
+ JS_ASSERT(!cache_->table[i_].vcap); \
+ JS_ASSERT(!cache_->table[i_].vword); \
+ } \
+ JS_END_MACRO
+#else
+#define ASSERT_CACHE_IS_EMPTY(cache) ((void)0)
+#endif
+
+JS_STATIC_ASSERT(PCVAL_NULL == 0);
+
+void
+js_FlushPropertyCache(JSContext *cx)
+{
+ JSPropertyCache *cache;
+
+ cache = &JS_PROPERTY_CACHE(cx);
+ if (cache->empty) {
+ ASSERT_CACHE_IS_EMPTY(cache);
+ return;
+ }
+
+ memset(cache->table, 0, sizeof cache->table);
+ cache->empty = JS_TRUE;
+
+#ifdef JS_PROPERTY_CACHE_METERING
+ { static FILE *fp;
+ if (!fp)
+ fp = fopen("/tmp/propcache.stats", "w");
+ if (fp) {
+ fputs("Property cache stats for ", fp);
+#ifdef JS_THREADSAFE
+ fprintf(fp, "thread %lu, ", (unsigned long) cx->thread->id);
+#endif
+ fprintf(fp, "GC %u\n", cx->runtime->gcNumber);
+
+# define P(mem) fprintf(fp, "%11s %10lu\n", #mem, (unsigned long)cache->mem)
+ P(fills);
+ P(nofills);
+ P(rofills);
+ P(disfills);
+ P(oddfills);
+ P(modfills);
+ P(brandfills);
+ P(noprotos);
+ P(longchains);
+ P(recycles);
+ P(pcrecycles);
+ P(tests);
+ P(pchits);
+ P(protopchits);
+ P(initests);
+ P(inipchits);
+ P(inipcmisses);
+ P(settests);
+ P(addpchits);
+ P(setpchits);
+ P(setpcmisses);
+ P(slotchanges);
+ P(setmisses);
+ P(idmisses);
+ P(komisses);
+ P(vcmisses);
+ P(misses);
+ P(flushes);
+ P(pcpurges);
+# undef P
+
+ fprintf(fp, "hit rates: pc %g%% (proto %g%%), set %g%%, ini %g%%, full %g%%\n",
+ (100. * cache->pchits) / cache->tests,
+ (100. * cache->protopchits) / cache->tests,
+ (100. * (cache->addpchits + cache->setpchits))
+ / cache->settests,
+ (100. * cache->inipchits) / cache->initests,
+ (100. * (cache->tests - cache->misses)) / cache->tests);
+ fflush(fp);
+ }
+ }
+#endif
+
+ PCMETER(cache->flushes++);
+}
+
+void
+js_FlushPropertyCacheForScript(JSContext *cx, JSScript *script)
+{
+ JSPropertyCache *cache;
+ JSPropCacheEntry *entry;
+
+ cache = &JS_PROPERTY_CACHE(cx);
+ for (entry = cache->table; entry < cache->table + PROPERTY_CACHE_SIZE;
+ entry++) {
+ if (JS_UPTRDIFF(entry->kpc, script->code) < script->length) {
+ entry->kpc = NULL;
+ entry->kshape = 0;
+#ifdef DEBUG
+ entry->vcap = entry->vword = 0;
+#endif
+ }
+ }
+}
+
+void
+js_DisablePropertyCache(JSContext *cx)
+{
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+ ++JS_PROPERTY_CACHE(cx).disabled;
+}
+
+void
+js_EnablePropertyCache(JSContext *cx)
+{
+ --JS_PROPERTY_CACHE(cx).disabled;
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+}
+
+/*
+ * Check if the current arena has enough space to fit nslots after sp and, if
+ * so, reserve the necessary space.
+ */
+static JSBool
+AllocateAfterSP(JSContext *cx, jsval *sp, uintN nslots)
+{
+ uintN surplus;
+ jsval *sp2;
+
+ JS_ASSERT((jsval *) cx->stackPool.current->base <= sp);
+ JS_ASSERT(sp <= (jsval *) cx->stackPool.current->avail);
+ surplus = (jsval *) cx->stackPool.current->avail - sp;
+ if (nslots <= surplus)
+ return JS_TRUE;
+
+ /*
+ * No room before current->avail, check if the arena has enough space to
+ * fit the missing slots before the limit.
+ */
+ if (nslots > (size_t) ((jsval *) cx->stackPool.current->limit - sp))
+ return JS_FALSE;
+
+ JS_ARENA_ALLOCATE_CAST(sp2, jsval *, &cx->stackPool,
+ (nslots - surplus) * sizeof(jsval));
+ JS_ASSERT(sp2 == sp + surplus);
+ return JS_TRUE;
+}
+
+JS_STATIC_INTERPRET jsval *
+js_AllocRawStack(JSContext *cx, uintN nslots, void **markp)
+{
+ jsval *sp;
+
+ if (!cx->stackPool.first.next) {
+ int64 *timestamp;
+
+ JS_ARENA_ALLOCATE_CAST(timestamp, int64 *,
+ &cx->stackPool, sizeof *timestamp);
+ if (!timestamp) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ *timestamp = JS_Now();
+ }
+
+ if (markp)
+ *markp = JS_ARENA_MARK(&cx->stackPool);
+ JS_ARENA_ALLOCATE_CAST(sp, jsval *, &cx->stackPool, nslots * sizeof(jsval));
+ if (!sp)
+ js_ReportOutOfScriptQuota(cx);
+ return sp;
+}
+
+JS_STATIC_INTERPRET void
+js_FreeRawStack(JSContext *cx, void *mark)
+{
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
+}
+
+JS_FRIEND_API(jsval *)
+js_AllocStack(JSContext *cx, uintN nslots, void **markp)
+{
+ jsval *sp;
+ JSArena *a;
+ JSStackHeader *sh;
+
+ /* Callers don't check for zero nslots: we do to avoid empty segments. */
+ if (nslots == 0) {
+ *markp = NULL;
+ return (jsval *) JS_ARENA_MARK(&cx->stackPool);
+ }
+
+ /* Allocate 2 extra slots for the stack segment header we'll likely need. */
+ sp = js_AllocRawStack(cx, 2 + nslots, markp);
+ if (!sp)
+ return NULL;
+
+ /* Try to avoid another header if we can piggyback on the last segment. */
+ a = cx->stackPool.current;
+ sh = cx->stackHeaders;
+ if (sh && JS_STACK_SEGMENT(sh) + sh->nslots == sp) {
+ /* Extend the last stack segment, give back the 2 header slots. */
+ sh->nslots += nslots;
+ a->avail -= 2 * sizeof(jsval);
+ } else {
+ /*
+ * Need a new stack segment, so allocate and push a stack segment
+ * header from the 2 extra slots.
+ */
+ sh = (JSStackHeader *)sp;
+ sh->nslots = nslots;
+ sh->down = cx->stackHeaders;
+ cx->stackHeaders = sh;
+ sp += 2;
+ }
+
+ /*
+ * Store JSVAL_NULL using memset, to let compilers optimize as they see
+ * fit, in case a caller allocates and pushes GC-things one by one, which
+ * could nest a last-ditch GC that will scan this segment.
+ */
+ memset(sp, 0, nslots * sizeof(jsval));
+ return sp;
+}
+
+JS_FRIEND_API(void)
+js_FreeStack(JSContext *cx, void *mark)
+{
+ JSStackHeader *sh;
+ jsuword slotdiff;
+
+ /* Check for zero nslots allocation special case. */
+ if (!mark)
+ return;
+
+ /* We can assert because js_FreeStack always balances js_AllocStack. */
+ sh = cx->stackHeaders;
+ JS_ASSERT(sh);
+
+ /* If mark is in the current segment, reduce sh->nslots, else pop sh. */
+ slotdiff = JS_UPTRDIFF(mark, JS_STACK_SEGMENT(sh)) / sizeof(jsval);
+ if (slotdiff < (jsuword)sh->nslots)
+ sh->nslots = slotdiff;
+ else
+ cx->stackHeaders = sh->down;
+
+ /* Release the stackPool space allocated since mark was set. */
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
+}
+
+JSObject *
+js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *obj, *cursor, *clonedChild, *parent;
+ JSTempValueRooter tvr;
+
+ obj = fp->blockChain;
+ if (!obj) {
+ /*
+ * Don't force a call object for a lightweight function call, but do
+ * insist that there is a call object for a heavyweight function call.
+ */
+ JS_ASSERT(!fp->fun ||
+ !(fp->fun->flags & JSFUN_HEAVYWEIGHT) ||
+ fp->callobj);
+ JS_ASSERT(fp->scopeChain);
+ return fp->scopeChain;
+ }
+
+ /*
+ * We have one or more lexical scopes to reflect into fp->scopeChain, so
+ * make sure there's a call object at the current head of the scope chain,
+ * if this frame is a call frame.
+ */
+ if (fp->fun && !fp->callobj) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, fp->scopeChain) != &js_BlockClass ||
+ OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp);
+ if (!js_GetCallObject(cx, fp, fp->scopeChain))
+ return NULL;
+ }
+
+ /*
+ * Clone the block chain. To avoid recursive cloning we set the parent of
+ * the cloned child after we clone the parent. In the following loop when
+ * clonedChild is null it indicates the first iteration when no special GC
+ * rooting is necessary. On the second and the following iterations we
+ * have to protect cloned so far chain against the GC during cloning of
+ * the cursor object.
+ */
+ cursor = obj;
+ clonedChild = NULL;
+ for (;;) {
+ parent = OBJ_GET_PARENT(cx, cursor);
+
+ /*
+ * We pass fp->scopeChain and not null even if we override the parent
+ * slot later as null triggers useless calculations of slot's value in
+ * js_NewObject that js_CloneBlockObject calls.
+ */
+ cursor = js_CloneBlockObject(cx, cursor, fp->scopeChain, fp);
+ if (!cursor) {
+ if (clonedChild)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return NULL;
+ }
+ if (!clonedChild) {
+ /*
+ * The first iteration. Check if other follow and root obj if so
+ * to protect the whole cloned chain against GC.
+ */
+ obj = cursor;
+ if (!parent)
+ break;
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+ } else {
+ /*
+ * Avoid OBJ_SET_PARENT overhead as clonedChild cannot escape to
+ * other threads.
+ */
+ STOBJ_SET_PARENT(clonedChild, cursor);
+ if (!parent) {
+ JS_ASSERT(tvr.u.value == OBJECT_TO_JSVAL(obj));
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ break;
+ }
+ }
+ clonedChild = cursor;
+ cursor = parent;
+ }
+ fp->flags |= JSFRAME_POP_BLOCKS;
+ fp->scopeChain = obj;
+ fp->blockChain = NULL;
+ return obj;
+}
+
+JSBool
+js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp)
+{
+ jsval v;
+ JSObject *obj;
+
+ v = vp[1];
+ if (JSVAL_IS_OBJECT(v)) {
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, clasp, vp + 2))
+ return JS_FALSE;
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ }
+ *thisvp = v;
+ return JS_TRUE;
+}
+
+/*
+ * ECMA requires "the global object", but in embeddings such as the browser,
+ * which have multiple top-level objects (windows, frames, etc. in the DOM),
+ * we prefer fun's parent. An example that causes this code to run:
+ *
+ * // in window w1
+ * function f() { return this }
+ * function g() { return f }
+ *
+ * // in window w2
+ * var h = w1.g()
+ * alert(h() == w1)
+ *
+ * The alert should display "true".
+ */
+JS_STATIC_INTERPRET JSObject *
+js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv)
+{
+ JSObject *thisp;
+
+ if (JSVAL_IS_PRIMITIVE(argv[-2]) ||
+ !OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(argv[-2]))) {
+ thisp = cx->globalObject;
+ } else {
+ JSStackFrame *fp;
+ jsid id;
+ jsval v;
+ uintN attrs;
+ JSBool ok;
+ JSObject *parent;
+
+ /*
+ * Walk up the parent chain, first checking that the running script
+ * has access to the callee's parent object. Note that if lazy, the
+ * running script whose principals we want to check is the script
+ * associated with fp->down, not with fp.
+ *
+ * FIXME: 417851 -- this access check should not be required, as it
+ * imposes a performance penalty on all js_ComputeGlobalThis calls,
+ * and it represents a maintenance hazard.
+ */
+ fp = cx->fp; /* quell GCC overwarning */
+ if (lazy) {
+ JS_ASSERT(fp->argv == argv);
+ fp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = fp;
+ cx->fp = fp->down;
+ fp->down = NULL;
+ }
+ thisp = JSVAL_TO_OBJECT(argv[-2]);
+ id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
+
+ ok = OBJ_CHECK_ACCESS(cx, thisp, id, JSACC_PARENT, &v, &attrs);
+ if (lazy) {
+ cx->dormantFrameChain = fp->dormantNext;
+ fp->dormantNext = NULL;
+ fp->down = cx->fp;
+ cx->fp = fp;
+ }
+ if (!ok)
+ return NULL;
+
+ thisp = JSVAL_IS_VOID(v)
+ ? OBJ_GET_PARENT(cx, thisp)
+ : JSVAL_TO_OBJECT(v);
+ while ((parent = OBJ_GET_PARENT(cx, thisp)) != NULL)
+ thisp = parent;
+ }
+
+ OBJ_TO_OUTER_OBJECT(cx, thisp);
+ if (!thisp)
+ return NULL;
+ argv[-1] = OBJECT_TO_JSVAL(thisp);
+ return thisp;
+}
+
+static JSObject *
+ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)
+{
+ JSObject *thisp;
+
+ JS_ASSERT(!JSVAL_IS_NULL(argv[-1]));
+ if (!JSVAL_IS_OBJECT(argv[-1])) {
+ if (!js_PrimitiveToObject(cx, &argv[-1]))
+ return NULL;
+ thisp = JSVAL_TO_OBJECT(argv[-1]);
+ } else {
+ thisp = JSVAL_TO_OBJECT(argv[-1]);
+ if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass)
+ return js_ComputeGlobalThis(cx, lazy, argv);
+
+ if (thisp->map->ops->thisObject) {
+ /* Some objects (e.g., With) delegate 'this' to another object. */
+ thisp = thisp->map->ops->thisObject(cx, thisp);
+ if (!thisp)
+ return NULL;
+ }
+ OBJ_TO_OUTER_OBJECT(cx, thisp);
+ if (!thisp)
+ return NULL;
+ argv[-1] = OBJECT_TO_JSVAL(thisp);
+ }
+ return thisp;
+}
+
+JSObject *
+js_ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)
+{
+ if (JSVAL_IS_NULL(argv[-1]))
+ return js_ComputeGlobalThis(cx, lazy, argv);
+ return ComputeThis(cx, lazy, argv);
+}
+
+#if JS_HAS_NO_SUCH_METHOD
+
+#define JSSLOT_FOUND_FUNCTION JSSLOT_PRIVATE
+#define JSSLOT_SAVED_ID (JSSLOT_PRIVATE + 1)
+
+JSClass js_NoSuchMethodClass = {
+ "NoSuchMethod",
+ JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_NoSuchMethod),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+JS_BEGIN_EXTERN_C
+
+JSObject*
+js_InitNoSuchMethodClass(JSContext *cx, JSObject* obj);
+
+JS_END_EXTERN_C
+
+JSObject*
+js_InitNoSuchMethodClass(JSContext *cx, JSObject* obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_NoSuchMethodClass, NULL, 0, NULL,
+ NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+/*
+ * When JSOP_CALLPROP or JSOP_CALLELEM does not find the method property of
+ * the base object, we search for the __noSuchMethod__ method in the base.
+ * If it exists, we store the method and the property's id into an object of
+ * NoSuchMethod class and store this object into the callee's stack slot.
+ * Later, js_Invoke will recognise such an object and transfer control to
+ * NoSuchMethod that invokes the method like:
+ *
+ * this.__noSuchMethod__(id, args)
+ *
+ * where id is the name of the method that this invocation attempted to
+ * call by name, and args is an Array containing this invocation's actual
+ * parameters.
+ */
+JS_STATIC_INTERPRET JSBool
+js_OnUnknownMethod(JSContext *cx, jsval *vp)
+{
+ JSObject *obj;
+ jsid id;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
+ obj = JSVAL_TO_OBJECT(vp[1]);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+
+ MUST_FLOW_THROUGH("out");
+ id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, &tvr.u.value);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ vp[1] = OBJECT_TO_JSVAL(obj);
+ } else
+#endif
+ {
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
+ if (!ok)
+ goto out;
+ }
+ if (JSVAL_IS_PRIMITIVE(tvr.u.value)) {
+ vp[0] = tvr.u.value;
+ } else {
+#if JS_HAS_XML_SUPPORT
+ /* Extract the function name from function::name qname. */
+ if (!JSVAL_IS_PRIMITIVE(vp[0])) {
+ obj = JSVAL_TO_OBJECT(vp[0]);
+ ok = js_IsFunctionQName(cx, obj, &id);
+ if (!ok)
+ goto out;
+ if (id != 0)
+ vp[0] = ID_TO_VALUE(id);
+ }
+#endif
+ obj = js_NewObject(cx, &js_NoSuchMethodClass, NULL, NULL, 0);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ obj->fslots[JSSLOT_FOUND_FUNCTION] = tvr.u.value;
+ obj->fslots[JSSLOT_SAVED_ID] = vp[0];
+ vp[0] = OBJECT_TO_JSVAL(obj);
+ }
+ ok = JS_TRUE;
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+NoSuchMethod(JSContext *cx, uintN argc, jsval *vp, uint32 flags)
+{
+ jsval *invokevp;
+ void *mark;
+ JSBool ok;
+ JSObject *obj, *argsobj;
+
+ invokevp = js_AllocStack(cx, 2 + 2, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[0]));
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
+ obj = JSVAL_TO_OBJECT(vp[0]);
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_NoSuchMethodClass);
+
+ invokevp[0] = obj->fslots[JSSLOT_FOUND_FUNCTION];
+ invokevp[1] = vp[1];
+ invokevp[2] = obj->fslots[JSSLOT_SAVED_ID];
+ argsobj = js_NewArrayObject(cx, argc, vp + 2);
+ if (!argsobj) {
+ ok = JS_FALSE;
+ } else {
+ invokevp[3] = OBJECT_TO_JSVAL(argsobj);
+ ok = (flags & JSINVOKE_CONSTRUCT)
+ ? js_InvokeConstructor(cx, 2, JS_TRUE, invokevp)
+ : js_Invoke(cx, 2, invokevp, flags);
+ vp[0] = invokevp[0];
+ }
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+#endif /* JS_HAS_NO_SUCH_METHOD */
+
+/*
+ * We check if the function accepts a primitive value as |this|. For that we
+ * use a table that maps value's tag into the corresponding function flag.
+ */
+JS_STATIC_ASSERT(JSVAL_INT == 1);
+JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
+JS_STATIC_ASSERT(JSVAL_STRING == 4);
+JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);
+
+const uint16 js_PrimitiveTestFlags[] = {
+ JSFUN_THISP_NUMBER, /* INT */
+ JSFUN_THISP_NUMBER, /* DOUBLE */
+ JSFUN_THISP_NUMBER, /* INT */
+ JSFUN_THISP_STRING, /* STRING */
+ JSFUN_THISP_NUMBER, /* INT */
+ JSFUN_THISP_BOOLEAN, /* BOOLEAN */
+ JSFUN_THISP_NUMBER /* INT */
+};
+
+/*
+ * Find a function reference and its 'this' object implicit first parameter
+ * under argc arguments on cx's stack, and call the function. Push missing
+ * required arguments, allocate declared local variables, and pop everything
+ * when done. Then push the return value.
+ */
+JS_FRIEND_API(JSBool)
+js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
+{
+ void *mark;
+ JSStackFrame frame;
+ jsval *sp, *argv, *newvp;
+ jsval v;
+ JSObject *funobj, *parent;
+ JSBool ok;
+ JSClass *clasp;
+ JSObjectOps *ops;
+ JSNative native;
+ JSFunction *fun;
+ JSScript *script;
+ uintN nslots, i;
+ uint32 rootedArgsFlag;
+ JSInterpreterHook hook;
+ void *hookData;
+
+ /* [vp .. vp + 2 + argc) must belong to the last JS stack arena. */
+ JS_ASSERT((jsval *) cx->stackPool.current->base <= vp);
+ JS_ASSERT(vp + 2 + argc <= (jsval *) cx->stackPool.current->avail);
+
+ /*
+ * Mark the top of stack and load frequently-used registers. After this
+ * point the control should flow through label out2: to return.
+ */
+ mark = JS_ARENA_MARK(&cx->stackPool);
+ v = *vp;
+
+ if (JSVAL_IS_PRIMITIVE(v))
+ goto bad;
+
+ funobj = JSVAL_TO_OBJECT(v);
+ parent = OBJ_GET_PARENT(cx, funobj);
+ clasp = OBJ_GET_CLASS(cx, funobj);
+ if (clasp != &js_FunctionClass) {
+#if JS_HAS_NO_SUCH_METHOD
+ if (clasp == &js_NoSuchMethodClass) {
+ ok = NoSuchMethod(cx, argc, vp, flags);
+ goto out2;
+ }
+#endif
+
+ /* Function is inlined, all other classes use object ops. */
+ ops = funobj->map->ops;
+
+ /*
+ * XXX this makes no sense -- why convert to function if clasp->call?
+ * XXX better to call that hook without converting
+ * XXX the only thing that needs fixing is liveconnect
+ *
+ * Try converting to function, for closure and API compatibility.
+ * We attempt the conversion under all circumstances for 1.2, but
+ * only if there is a call op defined otherwise.
+ */
+ if ((ops == &js_ObjectOps) ? clasp->call : ops->call) {
+ ok = clasp->convert(cx, funobj, JSTYPE_FUNCTION, &v);
+ if (!ok)
+ goto out2;
+
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ /* Make vp refer to funobj to keep it available as argv[-2]. */
+ *vp = v;
+ funobj = JSVAL_TO_OBJECT(v);
+ parent = OBJ_GET_PARENT(cx, funobj);
+ goto have_fun;
+ }
+ }
+ fun = NULL;
+ script = NULL;
+ nslots = 0;
+
+ /* Try a call or construct native object op. */
+ if (flags & JSINVOKE_CONSTRUCT) {
+ if (!JSVAL_IS_OBJECT(vp[1])) {
+ ok = js_PrimitiveToObject(cx, &vp[1]);
+ if (!ok)
+ goto out2;
+ }
+ native = ops->construct;
+ } else {
+ native = ops->call;
+ }
+ if (!native)
+ goto bad;
+ } else {
+have_fun:
+ /* Get private data and set derived locals from it. */
+ fun = GET_FUNCTION_PRIVATE(cx, funobj);
+ nslots = FUN_MINARGS(fun);
+ nslots = (nslots > argc) ? nslots - argc : 0;
+ if (FUN_INTERPRETED(fun)) {
+ native = NULL;
+ script = fun->u.i.script;
+ } else {
+ native = fun->u.n.native;
+ script = NULL;
+ nslots += fun->u.n.extra;
+ }
+
+ if (JSFUN_BOUND_METHOD_TEST(fun->flags)) {
+ /* Handle bound method special case. */
+ vp[1] = OBJECT_TO_JSVAL(parent);
+ } else if (!JSVAL_IS_OBJECT(vp[1])) {
+ JS_ASSERT(!(flags & JSINVOKE_CONSTRUCT));
+ if (PRIMITIVE_THIS_TEST(fun, vp[1]))
+ goto start_call;
+ }
+ }
+
+ if (flags & JSINVOKE_CONSTRUCT) {
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
+ } else {
+ /*
+ * We must call js_ComputeThis in case we are not called from the
+ * interpreter, where a prior bytecode has computed an appropriate
+ * |this| already.
+ *
+ * But we need to compute |this| eagerly only for so-called "slow"
+ * (i.e., not fast) native functions. Fast natives must use either
+ * JS_THIS or JS_THIS_OBJECT, and scripted functions will go through
+ * the appropriate this-computing bytecode, e.g., JSOP_THIS.
+ */
+ if (native && (!fun || !(fun->flags & JSFUN_FAST_NATIVE))) {
+ if (!js_ComputeThis(cx, JS_FALSE, vp + 2)) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ flags |= JSFRAME_COMPUTED_THIS;
+ }
+ }
+
+ start_call:
+ if (native && fun && (fun->flags & JSFUN_FAST_NATIVE)) {
+#ifdef DEBUG_NOT_THROWING
+ JSBool alreadyThrowing = cx->throwing;
+#endif
+ JS_ASSERT(nslots == 0);
+#if JS_HAS_LVALUE_RETURN
+ /* Set by JS_SetCallReturnValue2, used to return reference types. */
+ cx->rval2set = JS_FALSE;
+#endif
+ ok = ((JSFastNative) native)(cx, argc, vp);
+ JS_RUNTIME_METER(cx->runtime, nativeCalls);
+#ifdef DEBUG_NOT_THROWING
+ if (ok && !alreadyThrowing)
+ ASSERT_NOT_THROWING(cx);
+#endif
+ goto out2;
+ }
+
+ argv = vp + 2;
+ sp = argv + argc;
+
+ rootedArgsFlag = JSFRAME_ROOTED_ARGV;
+ if (nslots != 0) {
+ /*
+ * The extra slots required by the function continue with argument
+ * slots. Thus, when the last stack pool arena does not have room to
+ * fit nslots right after sp and AllocateAfterSP fails, we have to copy
+ * [vp..vp+2+argc) slots and clear rootedArgsFlag to root the copy.
+ */
+ if (!AllocateAfterSP(cx, sp, nslots)) {
+ rootedArgsFlag = 0;
+ newvp = js_AllocRawStack(cx, 2 + argc + nslots, NULL);
+ if (!newvp) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ memcpy(newvp, vp, (2 + argc) * sizeof(jsval));
+ argv = newvp + 2;
+ sp = argv + argc;
+ }
+
+ /* Push void to initialize missing args. */
+ i = nslots;
+ do {
+ *sp++ = JSVAL_VOID;
+ } while (--i != 0);
+ }
+
+ /* Allocate space for local variables and stack of interpreted function. */
+ if (script && script->nslots != 0) {
+ if (!AllocateAfterSP(cx, sp, script->nslots)) {
+ /* NB: Discontinuity between argv and slots, stack slots. */
+ sp = js_AllocRawStack(cx, script->nslots, NULL);
+ if (!sp) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ }
+
+ /* Push void to initialize local variables. */
+ for (jsval *end = sp + fun->u.i.nvars; sp != end; ++sp)
+ *sp = JSVAL_VOID;
+ }
+
+ /*
+ * Initialize the frame.
+ *
+ * To set thisp we use an explicit cast and not JSVAL_TO_OBJECT, as vp[1]
+ * can be a primitive value here for those native functions specified with
+ * JSFUN_THISP_(NUMBER|STRING|BOOLEAN) flags.
+ */
+ frame.thisp = (JSObject *)vp[1];
+ frame.varobj = NULL;
+ frame.callobj = frame.argsobj = NULL;
+ frame.script = script;
+ frame.callee = funobj;
+ frame.fun = fun;
+ frame.argc = argc;
+ frame.argv = argv;
+
+ /* Default return value for a constructor is the new object. */
+ frame.rval = (flags & JSINVOKE_CONSTRUCT) ? vp[1] : JSVAL_VOID;
+ frame.down = cx->fp;
+ frame.annotation = NULL;
+ frame.scopeChain = NULL; /* set below for real, after cx->fp is set */
+ frame.regs = NULL;
+ frame.imacpc = NULL;
+ frame.slots = NULL;
+ frame.sharpDepth = 0;
+ frame.sharpArray = NULL;
+ frame.flags = flags | rootedArgsFlag;
+ frame.dormantNext = NULL;
+ frame.xmlNamespace = NULL;
+ frame.blockChain = NULL;
+
+ MUST_FLOW_THROUGH("out");
+ cx->fp = &frame;
+
+ /* Init these now in case we goto out before first hook call. */
+ hook = cx->debugHooks->callHook;
+ hookData = NULL;
+
+ /* call the hook if present */
+ if (hook && (native || script))
+ hookData = hook(cx, &frame, JS_TRUE, 0, cx->debugHooks->callHookData);
+
+ /* Call the function, either a native method or an interpreted script. */
+ if (native) {
+#ifdef DEBUG_NOT_THROWING
+ JSBool alreadyThrowing = cx->throwing;
+#endif
+
+#if JS_HAS_LVALUE_RETURN
+ /* Set by JS_SetCallReturnValue2, used to return reference types. */
+ cx->rval2set = JS_FALSE;
+#endif
+
+ /* If native, use caller varobj and scopeChain for eval. */
+ JS_ASSERT(!frame.varobj);
+ JS_ASSERT(!frame.scopeChain);
+ if (frame.down) {
+ frame.varobj = frame.down->varobj;
+ frame.scopeChain = frame.down->scopeChain;
+ }
+
+ /* But ensure that we have a scope chain. */
+ if (!frame.scopeChain)
+ frame.scopeChain = parent;
+
+ frame.displaySave = NULL;
+ ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
+ JS_RUNTIME_METER(cx->runtime, nativeCalls);
+#ifdef DEBUG_NOT_THROWING
+ if (ok && !alreadyThrowing)
+ ASSERT_NOT_THROWING(cx);
+#endif
+ } else if (script) {
+ /* Use parent scope so js_GetCallObject can find the right "Call". */
+ frame.scopeChain = parent;
+ if (JSFUN_HEAVYWEIGHT_TEST(fun->flags)) {
+ /* Scope with a call object parented by the callee's parent. */
+ if (!js_GetCallObject(cx, &frame, parent)) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ frame.slots = sp - fun->u.i.nvars;
+
+ ok = js_Interpret(cx);
+ } else {
+ /* fun might be onerror trying to report a syntax error in itself. */
+ frame.scopeChain = NULL;
+ frame.displaySave = NULL;
+ ok = JS_TRUE;
+ }
+
+out:
+ if (hookData) {
+ hook = cx->debugHooks->callHook;
+ if (hook)
+ hook(cx, &frame, JS_FALSE, &ok, hookData);
+ }
+
+ /* If frame has a call object, sync values and clear back-pointer. */
+ if (frame.callobj)
+ ok &= js_PutCallObject(cx, &frame);
+
+ /* If frame has an arguments object, sync values and clear back-pointer. */
+ if (frame.argsobj)
+ ok &= js_PutArgsObject(cx, &frame);
+
+ *vp = frame.rval;
+
+ /* Restore cx->fp now that we're done releasing frame objects. */
+ cx->fp = frame.down;
+
+out2:
+ /* Pop everything we may have allocated off the stack. */
+ JS_ARENA_RELEASE(&cx->stackPool, mark);
+ if (!ok)
+ *vp = JSVAL_NULL;
+ return ok;
+
+bad:
+ js_ReportIsNotFunction(cx, vp, flags & JSINVOKE_FUNFLAGS);
+ ok = JS_FALSE;
+ goto out2;
+}
+
+JSBool
+js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ jsval *invokevp;
+ void *mark;
+ JSBool ok;
+
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ invokevp[0] = fval;
+ invokevp[1] = OBJECT_TO_JSVAL(obj);
+ memcpy(invokevp + 2, argv, argc * sizeof *argv);
+
+ ok = js_Invoke(cx, argc, invokevp, flags);
+ if (ok) {
+ /*
+ * Store *rval in the a scoped local root if a scope is open, else in
+ * the lastInternalResult pigeon-hole GC root, solely so users of
+ * js_InternalInvoke and its direct and indirect (js_ValueToString for
+ * example) callers do not need to manage roots for local, temporary
+ * references to such results.
+ */
+ *rval = *invokevp;
+ if (JSVAL_IS_GCTHING(*rval) && *rval != JSVAL_NULL) {
+ if (cx->localRootStack) {
+ if (js_PushLocalRoot(cx, cx->localRootStack, *rval) < 0)
+ ok = JS_FALSE;
+ } else {
+ cx->weakRoots.lastInternalResult = *rval;
+ }
+ }
+ }
+
+ js_FreeStack(cx, mark);
+ return ok;
+}
+
+JSBool
+js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
+ JSAccessMode mode, uintN argc, jsval *argv, jsval *rval)
+{
+ JSSecurityCallbacks *callbacks;
+
+ /*
+ * js_InternalInvoke could result in another try to get or set the same id
+ * again, see bug 355497.
+ */
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ /*
+ * Check general (not object-ops/class-specific) access from the running
+ * script to obj.id only if id has a scripted getter or setter that we're
+ * about to invoke. If we don't check this case, nothing else will -- no
+ * other native code has the chance to check.
+ *
+ * Contrast this non-native (scripted) case with native getter and setter
+ * accesses, where the native itself must do an access check, if security
+ * policies requires it. We make a checkAccess or checkObjectAccess call
+ * back to the embedding program only in those cases where we're not going
+ * to call an embedding-defined native function, getter, setter, or class
+ * hook anyway. Where we do call such a native, there's no need for the
+ * engine to impose a separate access check callback on all embeddings --
+ * many embeddings have no security policy at all.
+ */
+ JS_ASSERT(mode == JSACC_READ || mode == JSACC_WRITE);
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks &&
+ callbacks->checkObjectAccess &&
+ VALUE_IS_FUNCTION(cx, fval) &&
+ FUN_INTERPRETED(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval))) &&
+ !callbacks->checkObjectAccess(cx, obj, ID_TO_VALUE(id), mode, &fval)) {
+ return JS_FALSE;
+ }
+
+ return js_InternalCall(cx, obj, fval, argc, argv, rval);
+}
+
+JSBool
+js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
+ JSStackFrame *down, uintN flags, jsval *result)
+{
+ JSInterpreterHook hook;
+ void *hookData, *mark;
+ JSStackFrame *oldfp, frame;
+ JSObject *obj, *tmp;
+ JSBool ok;
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_EXECUTE_START_ENABLED())
+ jsdtrace_execute_start(script);
+#endif
+
+ hook = cx->debugHooks->executeHook;
+ hookData = mark = NULL;
+ oldfp = cx->fp;
+ frame.script = script;
+ if (down) {
+ /* Propagate arg state for eval and the debugger API. */
+ frame.callobj = down->callobj;
+ frame.argsobj = down->argsobj;
+ frame.varobj = down->varobj;
+ frame.callee = down->callee;
+ frame.fun = down->fun;
+ frame.thisp = down->thisp;
+ if (down->flags & JSFRAME_COMPUTED_THIS)
+ flags |= JSFRAME_COMPUTED_THIS;
+ frame.argc = down->argc;
+ frame.argv = down->argv;
+ frame.annotation = down->annotation;
+ frame.sharpArray = down->sharpArray;
+ JS_ASSERT(script->nfixed == 0);
+ } else {
+ frame.callobj = frame.argsobj = NULL;
+ obj = chain;
+ if (cx->options & JSOPTION_VAROBJFIX) {
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = tmp;
+ }
+ frame.varobj = obj;
+ frame.callee = NULL;
+ frame.fun = NULL;
+ frame.thisp = chain;
+ frame.argc = 0;
+ frame.argv = NULL;
+ frame.annotation = NULL;
+ frame.sharpArray = NULL;
+ }
+
+ frame.imacpc = NULL;
+ if (script->nslots != 0) {
+ frame.slots = js_AllocRawStack(cx, script->nslots, &mark);
+ if (!frame.slots) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ memset(frame.slots, 0, script->nfixed * sizeof(jsval));
+ } else {
+ frame.slots = NULL;
+ }
+
+ frame.rval = JSVAL_VOID;
+ frame.down = down;
+ frame.scopeChain = chain;
+ frame.regs = NULL;
+ frame.sharpDepth = 0;
+ frame.flags = flags;
+ frame.dormantNext = NULL;
+ frame.xmlNamespace = NULL;
+ frame.blockChain = NULL;
+
+ /*
+ * Here we wrap the call to js_Interpret with code to (conditionally)
+ * save and restore the old stack frame chain into a chain of 'dormant'
+ * frame chains. Since we are replacing cx->fp, we were running into
+ * the problem that if GC was called under this frame, some of the GC
+ * things associated with the old frame chain (available here only in
+ * the C variable 'oldfp') were not rooted and were being collected.
+ *
+ * So, now we preserve the links to these 'dormant' frame chains in cx
+ * before calling js_Interpret and cleanup afterwards. The GC walks
+ * these dormant chains and marks objects in the same way that it marks
+ * objects in the primary cx->fp chain.
+ */
+ if (oldfp && oldfp != down) {
+ JS_ASSERT(!oldfp->dormantNext);
+ oldfp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = oldfp;
+ }
+
+ cx->fp = &frame;
+ if (!down) {
+ OBJ_TO_OUTER_OBJECT(cx, frame.thisp);
+ if (!frame.thisp) {
+ ok = JS_FALSE;
+ goto out2;
+ }
+ frame.flags |= JSFRAME_COMPUTED_THIS;
+ }
+
+ if (hook) {
+ hookData = hook(cx, &frame, JS_TRUE, 0,
+ cx->debugHooks->executeHookData);
+ }
+
+ ok = js_Interpret(cx);
+ if (result)
+ *result = frame.rval;
+
+ if (hookData) {
+ hook = cx->debugHooks->executeHook;
+ if (hook)
+ hook(cx, &frame, JS_FALSE, &ok, hookData);
+ }
+
+out2:
+ if (mark)
+ js_FreeRawStack(cx, mark);
+ cx->fp = oldfp;
+
+ if (oldfp && oldfp != down) {
+ JS_ASSERT(cx->dormantFrameChain == oldfp);
+ cx->dormantFrameChain = oldfp->dormantNext;
+ oldfp->dormantNext = NULL;
+ }
+
+out:
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
+ jsdtrace_execute_done(script);
+#endif
+ return ok;
+}
+
+JSBool
+js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
+ JSObject **objp, JSProperty **propp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ uintN oldAttrs, report;
+ JSBool isFunction;
+ jsval value;
+ const char *type, *name;
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (propp) {
+ *objp = obj2;
+ *propp = prop;
+ }
+ if (!prop)
+ return JS_TRUE;
+
+ /*
+ * Use prop as a speedup hint to OBJ_GET_ATTRIBUTES, but drop it on error.
+ * An assertion at label bad: will insist that it is null.
+ */
+ if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+#ifdef DEBUG
+ prop = NULL;
+#endif
+ goto bad;
+ }
+
+ /*
+ * From here, return true, or else goto bad on failure to null out params.
+ * If our caller doesn't want prop, drop it (we don't need it any longer).
+ */
+ if (!propp) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ prop = NULL;
+ }
+
+ if (attrs == JSPROP_INITIALIZER) {
+ /* Allow the new object to override properties. */
+ if (obj2 != obj)
+ return JS_TRUE;
+ report = JSREPORT_WARNING | JSREPORT_STRICT;
+ } else {
+ /* We allow redeclaring some non-readonly properties. */
+ if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {
+ /*
+ * Allow redeclaration of variables and functions, but insist that
+ * the new value is not a getter if the old value was, ditto for
+ * setters -- unless prop is impermanent (in which case anyone
+ * could delete it and redefine it, willy-nilly).
+ */
+ if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER)))
+ return JS_TRUE;
+ if ((~(oldAttrs ^ attrs) & (JSPROP_GETTER | JSPROP_SETTER)) == 0)
+ return JS_TRUE;
+ if (!(oldAttrs & JSPROP_PERMANENT))
+ return JS_TRUE;
+ }
+
+ report = JSREPORT_ERROR;
+ isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;
+ if (!isFunction) {
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &value))
+ goto bad;
+ isFunction = VALUE_IS_FUNCTION(cx, value);
+ }
+ }
+
+ type = (attrs == JSPROP_INITIALIZER)
+ ? "property"
+ : (oldAttrs & attrs & JSPROP_GETTER)
+ ? js_getter_str
+ : (oldAttrs & attrs & JSPROP_SETTER)
+ ? js_setter_str
+ : (oldAttrs & JSPROP_READONLY)
+ ? js_const_str
+ : isFunction
+ ? js_function_str
+ : js_var_str;
+ name = js_ValueToPrintableString(cx, ID_TO_VALUE(id));
+ if (!name)
+ goto bad;
+ return JS_ReportErrorFlagsAndNumber(cx, report,
+ js_GetErrorMessage, NULL,
+ JSMSG_REDECLARED_VAR,
+ type, name);
+
+bad:
+ if (propp) {
+ *objp = NULL;
+ *propp = NULL;
+ }
+ JS_ASSERT(!prop);
+ return JS_FALSE;
+}
+
+JSBool
+js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval)
+{
+ jsval ltag = JSVAL_TAG(lval), rtag = JSVAL_TAG(rval);
+ jsdouble ld, rd;
+
+ if (ltag == rtag) {
+ if (ltag == JSVAL_STRING) {
+ JSString *lstr = JSVAL_TO_STRING(lval),
+ *rstr = JSVAL_TO_STRING(rval);
+ return js_EqualStrings(lstr, rstr);
+ }
+ if (ltag == JSVAL_DOUBLE) {
+ ld = *JSVAL_TO_DOUBLE(lval);
+ rd = *JSVAL_TO_DOUBLE(rval);
+ return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
+ }
+ if (ltag == JSVAL_OBJECT &&
+ lval != rval &&
+ !JSVAL_IS_NULL(lval) &&
+ !JSVAL_IS_NULL(rval)) {
+ JSObject *lobj, *robj;
+
+ lobj = js_GetWrappedObject(cx, JSVAL_TO_OBJECT(lval));
+ robj = js_GetWrappedObject(cx, JSVAL_TO_OBJECT(rval));
+ lval = OBJECT_TO_JSVAL(lobj);
+ rval = OBJECT_TO_JSVAL(robj);
+ }
+ return lval == rval;
+ }
+ if (ltag == JSVAL_DOUBLE && JSVAL_IS_INT(rval)) {
+ ld = *JSVAL_TO_DOUBLE(lval);
+ rd = JSVAL_TO_INT(rval);
+ return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
+ }
+ if (JSVAL_IS_INT(lval) && rtag == JSVAL_DOUBLE) {
+ ld = JSVAL_TO_INT(lval);
+ rd = *JSVAL_TO_DOUBLE(rval);
+ return JSDOUBLE_COMPARE(ld, ==, rd, JS_FALSE);
+ }
+ return lval == rval;
+}
+
+JSBool
+js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
+{
+ JSFunction *fun, *fun2;
+ JSObject *obj, *obj2, *proto, *parent;
+ jsval lval, rval;
+ JSClass *clasp;
+
+ fun = NULL;
+ obj2 = NULL;
+ lval = *vp;
+ if (!JSVAL_IS_OBJECT(lval) ||
+ (obj2 = JSVAL_TO_OBJECT(lval)) == NULL ||
+ /* XXX clean up to avoid special cases above ObjectOps layer */
+ OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass ||
+ !obj2->map->ops->construct)
+ {
+ fun = js_ValueToFunction(cx, vp, JSV2F_CONSTRUCT);
+ if (!fun)
+ return JS_FALSE;
+ }
+
+ clasp = &js_ObjectClass;
+ if (!obj2) {
+ proto = parent = NULL;
+ fun = NULL;
+ } else {
+ /*
+ * Get the constructor prototype object for this function.
+ * Use the nominal 'this' parameter slot, vp[1], as a local
+ * root to protect this prototype, in case it has no other
+ * strong refs.
+ */
+ if (!OBJ_GET_PROPERTY(cx, obj2,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &vp[1])) {
+ return JS_FALSE;
+ }
+ rval = vp[1];
+ proto = JSVAL_IS_OBJECT(rval) ? JSVAL_TO_OBJECT(rval) : NULL;
+ parent = OBJ_GET_PARENT(cx, obj2);
+
+ if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) {
+ fun2 = GET_FUNCTION_PRIVATE(cx, obj2);
+ if (!FUN_INTERPRETED(fun2) &&
+ !(fun2->flags & JSFUN_TRACEABLE) &&
+ fun2->u.n.u.clasp) {
+ clasp = fun2->u.n.u.clasp;
+ }
+ }
+ }
+ obj = js_NewObject(cx, clasp, proto, parent, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ /* Now we have an object with a constructor method; call it. */
+ vp[1] = OBJECT_TO_JSVAL(obj);
+ if (!js_Invoke(cx, argc, vp, JSINVOKE_CONSTRUCT)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return JS_FALSE;
+ }
+
+ /* Check the return value and if it's primitive, force it to be obj. */
+ rval = *vp;
+ if (clampReturn && JSVAL_IS_PRIMITIVE(rval)) {
+ if (!fun) {
+ /* native [[Construct]] returning primitive is error */
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_NEW_RESULT,
+ js_ValueToPrintableString(cx, rval));
+ return JS_FALSE;
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ }
+
+ JS_RUNTIME_METER(cx->runtime, constructs);
+ return JS_TRUE;
+}
+
+JSBool
+js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp)
+{
+ JS_ASSERT(!JSVAL_IS_INT(idval));
+
+#if JS_HAS_XML_SUPPORT
+ if (!JSVAL_IS_PRIMITIVE(idval)) {
+ if (OBJECT_IS_XML(cx, obj)) {
+ *idp = OBJECT_JSVAL_TO_JSID(idval);
+ return JS_TRUE;
+ }
+ if (!js_IsFunctionQName(cx, JSVAL_TO_OBJECT(idval), idp))
+ return JS_FALSE;
+ if (*idp != 0)
+ return JS_TRUE;
+ }
+#endif
+
+ return js_ValueToStringId(cx, idval, idp);
+}
+
+/*
+ * Enter the new with scope using an object at sp[-1] and associate the depth
+ * of the with block with sp + stackIndex.
+ */
+JS_STATIC_INTERPRET JSBool
+js_EnterWith(JSContext *cx, jsint stackIndex)
+{
+ JSStackFrame *fp;
+ jsval *sp;
+ JSObject *obj, *parent, *withobj;
+
+ fp = cx->fp;
+ sp = fp->regs->sp;
+ JS_ASSERT(stackIndex < 0);
+ JS_ASSERT(StackBase(fp) <= sp + stackIndex);
+
+ if (!JSVAL_IS_PRIMITIVE(sp[-1])) {
+ obj = JSVAL_TO_OBJECT(sp[-1]);
+ } else {
+ obj = js_ValueToNonNullObject(cx, sp[-1]);
+ if (!obj)
+ return JS_FALSE;
+ sp[-1] = OBJECT_TO_JSVAL(obj);
+ }
+
+ parent = js_GetScopeChain(cx, fp);
+ if (!parent)
+ return JS_FALSE;
+
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ if (!obj)
+ return JS_FALSE;
+
+ withobj = js_NewWithObject(cx, obj, parent,
+ sp + stackIndex - StackBase(fp));
+ if (!withobj)
+ return JS_FALSE;
+
+ fp->scopeChain = withobj;
+ js_DisablePropertyCache(cx);
+ return JS_TRUE;
+}
+
+JS_STATIC_INTERPRET void
+js_LeaveWith(JSContext *cx)
+{
+ JSObject *withobj;
+
+ withobj = cx->fp->scopeChain;
+ JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, withobj) == cx->fp);
+ JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
+ cx->fp->scopeChain = OBJ_GET_PARENT(cx, withobj);
+ JS_SetPrivate(cx, withobj, NULL);
+ js_EnablePropertyCache(cx);
+}
+
+JSClass *
+js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&
+ OBJ_GET_PRIVATE(cx, obj) == cx->fp &&
+ OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {
+ return clasp;
+ }
+ return NULL;
+}
+
+JS_STATIC_INTERPRET jsint
+js_CountWithBlocks(JSContext *cx, JSStackFrame *fp)
+{
+ jsint n;
+ JSObject *obj;
+ JSClass *clasp;
+
+ n = 0;
+ for (obj = fp->scopeChain;
+ (clasp = js_IsActiveWithOrBlock(cx, obj, 0)) != NULL;
+ obj = OBJ_GET_PARENT(cx, obj)) {
+ if (clasp == &js_WithClass)
+ ++n;
+ }
+ return n;
+}
+
+/*
+ * Unwind block and scope chains to match the given depth. The function sets
+ * fp->sp on return to stackDepth.
+ */
+JSBool
+js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth,
+ JSBool normalUnwind)
+{
+ JSObject *obj;
+ JSClass *clasp;
+
+ JS_ASSERT(stackDepth >= 0);
+ JS_ASSERT(StackBase(fp) + stackDepth <= fp->regs->sp);
+
+ for (obj = fp->blockChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
+ if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
+ break;
+ }
+ fp->blockChain = obj;
+
+ for (;;) {
+ obj = fp->scopeChain;
+ clasp = js_IsActiveWithOrBlock(cx, obj, stackDepth);
+ if (!clasp)
+ break;
+ if (clasp == &js_BlockClass) {
+ /* Don't fail until after we've updated all stacks. */
+ normalUnwind &= js_PutBlockObject(cx, normalUnwind);
+ } else {
+ js_LeaveWith(cx);
+ }
+ }
+
+ fp->regs->sp = StackBase(fp) + stackDepth;
+ return normalUnwind;
+}
+
+JS_STATIC_INTERPRET JSBool
+js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
+{
+ jsval v;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_DOUBLE(v)) {
+ d = *JSVAL_TO_DOUBLE(v);
+ } else if (JSVAL_IS_INT(v)) {
+ d = JSVAL_TO_INT(v);
+ } else {
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(*vp) || *vp == JSVAL_TRUE);
+
+ /* Store the result of v conversion back in vp for post increments. */
+ if ((cs->format & JOF_POST) &&
+ *vp == JSVAL_TRUE
+ && !js_NewNumberInRootedValue(cx, d, vp)) {
+ return JS_FALSE;
+ }
+ }
+
+ (cs->format & JOF_INC) ? d++ : d--;
+ if (!js_NewNumberInRootedValue(cx, d, vp2))
+ return JS_FALSE;
+
+ if (!(cs->format & JOF_POST))
+ *vp = *vp2;
+ return JS_TRUE;
+}
+
+#ifdef DEBUG
+
+JS_STATIC_INTERPRET void
+js_TraceOpcode(JSContext *cx, jsint len)
+{
+ FILE *tracefp;
+ JSStackFrame *fp;
+ JSFrameRegs *regs;
+ JSOp prevop;
+ intN ndefs, n, nuses;
+ jsval *siter;
+ JSString *str;
+ JSOp op;
+
+ tracefp = (FILE *) cx->tracefp;
+ JS_ASSERT(tracefp);
+ fp = cx->fp;
+ regs = fp->regs;
+ if (len != 0) {
+ prevop = (JSOp) regs->pc[-len];
+ ndefs = js_CodeSpec[prevop].ndefs;
+ if (ndefs != 0) {
+ for (n = -ndefs; n < 0; n++) {
+ char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
+ NULL);
+ if (bytes) {
+ fprintf(tracefp, "%s %s",
+ (n == -ndefs) ? " output:" : ",",
+ bytes);
+ JS_free(cx, bytes);
+ }
+ }
+ fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
+ }
+ fprintf(tracefp, " stack: ");
+ for (siter = StackBase(fp); siter < regs->sp; siter++) {
+ str = js_ValueToString(cx, *siter);
+ if (!str)
+ fputs("<null>", tracefp);
+ else
+ js_FileEscapedString(tracefp, str, 0);
+ fputc(' ', tracefp);
+ }
+ fputc('\n', tracefp);
+ }
+
+ fprintf(tracefp, "%4u: ",
+ js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : regs->pc));
+ js_Disassemble1(cx, fp->script, regs->pc,
+ PTRDIFF(regs->pc, fp->script->code, jsbytecode),
+ JS_FALSE, tracefp);
+ op = (JSOp) *regs->pc;
+ nuses = js_CodeSpec[op].nuses;
+ if (nuses != 0) {
+ for (n = -nuses; n < 0; n++) {
+ char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n],
+ NULL);
+ if (bytes) {
+ fprintf(tracefp, "%s %s",
+ (n == -nuses) ? " inputs:" : ",",
+ bytes);
+ JS_free(cx, bytes);
+ }
+ }
+ fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
+ }
+}
+
+#endif /* DEBUG */
+
+#ifdef JS_OPMETER
+
+# include <stdlib.h>
+
+# define HIST_NSLOTS 8
+
+/*
+ * The second dimension is hardcoded at 256 because we know that many bits fit
+ * in a byte, and mainly to optimize away multiplying by JSOP_LIMIT to address
+ * any particular row.
+ */
+static uint32 succeeds[JSOP_LIMIT][256];
+static uint32 slot_ops[JSOP_LIMIT][HIST_NSLOTS];
+
+JS_STATIC_INTERPRET void
+js_MeterOpcodePair(JSOp op1, JSOp op2)
+{
+ if (op1 != JSOP_STOP)
+ ++succeeds[op1][op2];
+}
+
+JS_STATIC_INTERPRET void
+js_MeterSlotOpcode(JSOp op, uint32 slot)
+{
+ if (slot < HIST_NSLOTS)
+ ++slot_ops[op][slot];
+}
+
+typedef struct Edge {
+ const char *from;
+ const char *to;
+ uint32 count;
+} Edge;
+
+static int
+compare_edges(const void *a, const void *b)
+{
+ const Edge *ea = (const Edge *) a;
+ const Edge *eb = (const Edge *) b;
+
+ return (int32)eb->count - (int32)ea->count;
+}
+
+void
+js_DumpOpMeters()
+{
+ const char *name, *from, *style;
+ FILE *fp;
+ uint32 total, count;
+ uint32 i, j, nedges;
+ Edge *graph;
+
+ name = getenv("JS_OPMETER_FILE");
+ if (!name)
+ name = "/tmp/ops.dot";
+ fp = fopen(name, "w");
+ if (!fp) {
+ perror(name);
+ return;
+ }
+
+ total = nedges = 0;
+ for (i = 0; i < JSOP_LIMIT; i++) {
+ for (j = 0; j < JSOP_LIMIT; j++) {
+ count = succeeds[i][j];
+ if (count != 0) {
+ total += count;
+ ++nedges;
+ }
+ }
+ }
+
+# define SIGNIFICANT(count,total) (200. * (count) >= (total))
+
+ graph = (Edge *) calloc(nedges, sizeof graph[0]);
+ for (i = nedges = 0; i < JSOP_LIMIT; i++) {
+ from = js_CodeName[i];
+ for (j = 0; j < JSOP_LIMIT; j++) {
+ count = succeeds[i][j];
+ if (count != 0 && SIGNIFICANT(count, total)) {
+ graph[nedges].from = from;
+ graph[nedges].to = js_CodeName[j];
+ graph[nedges].count = count;
+ ++nedges;
+ }
+ }
+ }
+ qsort(graph, nedges, sizeof(Edge), compare_edges);
+
+# undef SIGNIFICANT
+
+ fputs("digraph {\n", fp);
+ for (i = 0, style = NULL; i < nedges; i++) {
+ JS_ASSERT(i == 0 || graph[i-1].count >= graph[i].count);
+ if (!style || graph[i-1].count != graph[i].count) {
+ style = (i > nedges * .75) ? "dotted" :
+ (i > nedges * .50) ? "dashed" :
+ (i > nedges * .25) ? "solid" : "bold";
+ }
+ fprintf(fp, " %s -> %s [label=\"%lu\" style=%s]\n",
+ graph[i].from, graph[i].to,
+ (unsigned long)graph[i].count, style);
+ }
+ free(graph);
+ fputs("}\n", fp);
+ fclose(fp);
+
+ name = getenv("JS_OPMETER_HIST");
+ if (!name)
+ name = "/tmp/ops.hist";
+ fp = fopen(name, "w");
+ if (!fp) {
+ perror(name);
+ return;
+ }
+ fputs("bytecode", fp);
+ for (j = 0; j < HIST_NSLOTS; j++)
+ fprintf(fp, " slot %1u", (unsigned)j);
+ putc('\n', fp);
+ fputs("========", fp);
+ for (j = 0; j < HIST_NSLOTS; j++)
+ fputs(" =======", fp);
+ putc('\n', fp);
+ for (i = 0; i < JSOP_LIMIT; i++) {
+ for (j = 0; j < HIST_NSLOTS; j++) {
+ if (slot_ops[i][j] != 0) {
+ /* Reuse j in the next loop, since we break after. */
+ fprintf(fp, "%-8.8s", js_CodeName[i]);
+ for (j = 0; j < HIST_NSLOTS; j++)
+ fprintf(fp, " %7lu", (unsigned long)slot_ops[i][j]);
+ putc('\n', fp);
+ break;
+ }
+ }
+ }
+ fclose(fp);
+}
+
+#endif /* JS_OPSMETER */
+
+#endif /* !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___ */
+
+#ifndef jsinvoke_cpp___
+
+#define PUSH(v) (*regs.sp++ = (v))
+#define PUSH_OPND(v) PUSH(v)
+#define STORE_OPND(n,v) (regs.sp[n] = (v))
+#define POP() (*--regs.sp)
+#define POP_OPND() POP()
+#define FETCH_OPND(n) (regs.sp[n])
+
+/*
+ * Push the jsdouble d using sp from the lexical environment. Try to convert d
+ * to a jsint that fits in a jsval, otherwise GC-alloc space for it and push a
+ * reference.
+ */
+#define STORE_NUMBER(cx, n, d) \
+ JS_BEGIN_MACRO \
+ jsint i_; \
+ \
+ if (JSDOUBLE_IS_INT(d, i_) && INT_FITS_IN_JSVAL(i_)) \
+ regs.sp[n] = INT_TO_JSVAL(i_); \
+ else if (!js_NewDoubleInRootedValue(cx, d, &regs.sp[n])) \
+ goto error; \
+ JS_END_MACRO
+
+#define STORE_INT(cx, n, i) \
+ JS_BEGIN_MACRO \
+ if (INT_FITS_IN_JSVAL(i)) \
+ regs.sp[n] = INT_TO_JSVAL(i); \
+ else if (!js_NewDoubleInRootedValue(cx, (jsdouble) (i), &regs.sp[n])) \
+ goto error; \
+ JS_END_MACRO
+
+#define STORE_UINT(cx, n, u) \
+ JS_BEGIN_MACRO \
+ if ((u) <= JSVAL_INT_MAX) \
+ regs.sp[n] = INT_TO_JSVAL(u); \
+ else if (!js_NewDoubleInRootedValue(cx, (jsdouble) (u), &regs.sp[n])) \
+ goto error; \
+ JS_END_MACRO
+
+#define FETCH_NUMBER(cx, n, d) \
+ JS_BEGIN_MACRO \
+ jsval v_; \
+ \
+ v_ = FETCH_OPND(n); \
+ VALUE_TO_NUMBER(cx, n, v_, d); \
+ JS_END_MACRO
+
+#define FETCH_INT(cx, n, i) \
+ JS_BEGIN_MACRO \
+ jsval v_; \
+ \
+ v_= FETCH_OPND(n); \
+ if (JSVAL_IS_INT(v_)) { \
+ i = JSVAL_TO_INT(v_); \
+ } else { \
+ i = js_ValueToECMAInt32(cx, &regs.sp[n]); \
+ if (JSVAL_IS_NULL(regs.sp[n])) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#define FETCH_UINT(cx, n, ui) \
+ JS_BEGIN_MACRO \
+ jsval v_; \
+ \
+ v_= FETCH_OPND(n); \
+ if (JSVAL_IS_INT(v_)) { \
+ ui = (uint32) JSVAL_TO_INT(v_); \
+ } else { \
+ ui = js_ValueToECMAUint32(cx, &regs.sp[n]); \
+ if (JSVAL_IS_NULL(regs.sp[n])) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Optimized conversion macros that test for the desired type in v before
+ * homing sp and calling a conversion function.
+ */
+#define VALUE_TO_NUMBER(cx, n, v, d) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(v == regs.sp[n]); \
+ if (JSVAL_IS_INT(v)) { \
+ d = (jsdouble)JSVAL_TO_INT(v); \
+ } else if (JSVAL_IS_DOUBLE(v)) { \
+ d = *JSVAL_TO_DOUBLE(v); \
+ } else { \
+ d = js_ValueToNumber(cx, &regs.sp[n]); \
+ if (JSVAL_IS_NULL(regs.sp[n])) \
+ goto error; \
+ JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[n]) || \
+ regs.sp[n] == JSVAL_TRUE); \
+ } \
+ JS_END_MACRO
+
+#define POP_BOOLEAN(cx, v, b) \
+ JS_BEGIN_MACRO \
+ v = FETCH_OPND(-1); \
+ if (v == JSVAL_NULL) { \
+ b = JS_FALSE; \
+ } else if (JSVAL_IS_BOOLEAN(v)) { \
+ b = JSVAL_TO_BOOLEAN(v); \
+ } else { \
+ b = js_ValueToBoolean(v); \
+ } \
+ regs.sp--; \
+ JS_END_MACRO
+
+#define VALUE_TO_OBJECT(cx, n, v, obj) \
+ JS_BEGIN_MACRO \
+ if (!JSVAL_IS_PRIMITIVE(v)) { \
+ obj = JSVAL_TO_OBJECT(v); \
+ } else { \
+ obj = js_ValueToNonNullObject(cx, v); \
+ if (!obj) \
+ goto error; \
+ STORE_OPND(n, OBJECT_TO_JSVAL(obj)); \
+ } \
+ JS_END_MACRO
+
+#define FETCH_OBJECT(cx, n, v, obj) \
+ JS_BEGIN_MACRO \
+ v = FETCH_OPND(n); \
+ VALUE_TO_OBJECT(cx, n, v, obj); \
+ JS_END_MACRO
+
+#define DEFAULT_VALUE(cx, n, hint, v) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v)); \
+ JS_ASSERT(v == regs.sp[n]); \
+ if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, &regs.sp[n])) \
+ goto error; \
+ v = regs.sp[n]; \
+ JS_END_MACRO
+
+/*
+ * Quickly test if v is an int from the [-2**29, 2**29) range, that is, when
+ * the lowest bit of v is 1 and the bits 30 and 31 are both either 0 or 1. For
+ * such v we can do increment or decrement via adding or subtracting two
+ * without checking that the result overflows JSVAL_INT_MIN or JSVAL_INT_MAX.
+ */
+#define CAN_DO_FAST_INC_DEC(v) (((((v) << 1) ^ v) & 0x80000001) == 1)
+
+JS_STATIC_ASSERT(JSVAL_INT == 1);
+JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MIN)));
+JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX)));
+
+/*
+ * Conditional assert to detect failure to clear a pending exception that is
+ * suppressed (or unintentional suppression of a wanted exception).
+ */
+#if defined DEBUG_brendan || defined DEBUG_mrbkap || defined DEBUG_shaver
+# define DEBUG_NOT_THROWING 1
+#endif
+
+#ifdef DEBUG_NOT_THROWING
+# define ASSERT_NOT_THROWING(cx) JS_ASSERT(!(cx)->throwing)
+#else
+# define ASSERT_NOT_THROWING(cx) /* nothing */
+#endif
+
+/*
+ * Define JS_OPMETER to instrument bytecode succession, generating a .dot file
+ * on shutdown that shows the graph of significant predecessor/successor pairs
+ * executed, where the edge labels give the succession counts. The .dot file
+ * is named by the JS_OPMETER_FILE envariable, and defaults to /tmp/ops.dot.
+ *
+ * Bonus feature: JS_OPMETER also enables counters for stack-addressing ops
+ * such as JSOP_GETLOCAL, JSOP_INCARG, via METER_SLOT_OP. The resulting counts
+ * are written to JS_OPMETER_HIST, defaulting to /tmp/ops.hist.
+ */
+#ifndef JS_OPMETER
+# define METER_OP_INIT(op) /* nothing */
+# define METER_OP_PAIR(op1,op2) /* nothing */
+# define METER_SLOT_OP(op,slot) /* nothing */
+#else
+
+/*
+ * The second dimension is hardcoded at 256 because we know that many bits fit
+ * in a byte, and mainly to optimize away multiplying by JSOP_LIMIT to address
+ * any particular row.
+ */
+# define METER_OP_INIT(op) ((op) = JSOP_STOP)
+# define METER_OP_PAIR(op1,op2) (js_MeterOpcodePair(op1, op2))
+# define METER_SLOT_OP(op,slot) (js_MeterSlotOpcode(op, slot))
+
+#endif
+
+#define MAX_INLINE_CALL_COUNT 3000
+
+/*
+ * Threaded interpretation via computed goto appears to be well-supported by
+ * GCC 3 and higher. IBM's C compiler when run with the right options (e.g.,
+ * -qlanglvl=extended) also supports threading. Ditto the SunPro C compiler.
+ * Currently it's broken for JS_VERSION < 160, though this isn't worth fixing.
+ * Add your compiler support macros here.
+ */
+#ifndef JS_THREADED_INTERP
+# if JS_VERSION >= 160 && ( \
+ __GNUC__ >= 3 || \
+ (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \
+ __SUNPRO_C >= 0x570)
+# define JS_THREADED_INTERP 1
+# else
+# define JS_THREADED_INTERP 0
+# endif
+#endif
+
+/*
+ * Interpreter assumes the following to implement condition-free interrupt
+ * implementation when !JS_THREADED_INTERP.
+ */
+JS_STATIC_ASSERT(JSOP_INTERRUPT == 0);
+
+/*
+ * Ensure that the intrepreter switch can close call-bytecode cases in the
+ * same way as non-call bytecodes.
+ */
+JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETGVAR_LENGTH == JSOP_CALLGVAR_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETUPVAR_LENGTH == JSOP_CALLUPVAR_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
+JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH);
+JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH);
+
+/*
+ * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
+ * remain distinct for the decompiler. Ditto for JSOP_NULL{,THIS}.
+ */
+JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
+JS_STATIC_ASSERT(JSOP_NULL_LENGTH == JSOP_NULLTHIS_LENGTH);
+
+/* See TRY_BRANCH_AFTER_COND. */
+JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
+JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
+
+/* For the fastest case inder JSOP_INCNAME, etc. */
+JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_DECNAME_LENGTH);
+JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEINC_LENGTH);
+JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEDEC_LENGTH);
+
+JSBool
+js_Interpret(JSContext *cx)
+{
+ JSRuntime *rt;
+ JSStackFrame *fp;
+ JSScript *script;
+ uintN inlineCallCount;
+ JSAtom **atoms;
+ JSVersion currentVersion, originalVersion;
+ JSFrameRegs regs;
+ JSObject *obj, *obj2, *parent;
+ JSBool ok, cond;
+ jsint len;
+ jsbytecode *endpc, *pc2;
+ JSOp op, op2;
+ jsatomid index;
+ JSAtom *atom;
+ uintN argc, attrs, flags;
+ uint32 slot;
+ jsval *vp, lval, rval, ltmp, rtmp;
+ jsid id;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSString *str, *str2;
+ jsint i, j;
+ jsdouble d, d2;
+ JSClass *clasp;
+ JSFunction *fun;
+ JSType type;
+#if JS_THREADED_INTERP
+ register void * const *jumpTable;
+#else
+ register uint32 switchMask;
+ uintN switchOp;
+#endif
+ jsint low, high, off, npairs;
+ JSBool match;
+#if JS_HAS_GETTER_SETTER
+ JSPropertyOp getter, setter;
+#endif
+ JSAutoResolveFlags rf(cx, JSRESOLVE_INFER);
+
+#ifdef __GNUC__
+# define JS_EXTENSION __extension__
+# define JS_EXTENSION_(s) __extension__ ({ s; })
+#else
+# define JS_EXTENSION
+# define JS_EXTENSION_(s) s
+#endif
+
+#if JS_THREADED_INTERP
+ static void *const normalJumpTable[] = {
+# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_EXTENSION &&L_##op,
+# include "jsopcode.tbl"
+# undef OPDEF
+ };
+
+#ifdef JS_TRACER
+ static void *const recordingJumpTable[] = {
+# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_EXTENSION &&R_##op,
+# include "jsopcode.tbl"
+# undef OPDEF
+ };
+#endif /* JS_TRACER */
+
+ static void *const interruptJumpTable[] = {
+# define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_EXTENSION &&L_JSOP_INTERRUPT,
+# include "jsopcode.tbl"
+# undef OPDEF
+ };
+
+ METER_OP_INIT(op); /* to nullify first METER_OP_PAIR */
+
+# ifdef JS_TRACER
+# define CHECK_RECORDER() JS_BEGIN_MACRO \
+ JS_ASSERT(!TRACE_RECORDER(cx) ^ \
+ (jumpTable == recordingJumpTable)); \
+ JS_END_MACRO
+# else
+# define CHECK_RECORDER() ((void)0)
+# endif
+
+# define DO_OP() JS_BEGIN_MACRO \
+ CHECK_RECORDER(); \
+ JS_EXTENSION_(goto *jumpTable[op]); \
+ JS_END_MACRO
+# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
+ METER_OP_PAIR(op, regs.pc[n]); \
+ op = (JSOp) *(regs.pc += (n)); \
+ DO_OP(); \
+ JS_END_MACRO
+
+# define BEGIN_CASE(OP) L_##OP: \
+ CHECK_RECORDER();
+# define END_CASE(OP) DO_NEXT_OP(OP##_LENGTH);
+# define END_VARLEN_CASE DO_NEXT_OP(len);
+# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP) \
+ JS_ASSERT(js_CodeSpec[OP].length == 1); \
+ op = (JSOp) *++regs.pc; \
+ DO_OP();
+
+# define END_EMPTY_CASES
+
+#else /* !JS_THREADED_INTERP */
+
+# define DO_OP() goto do_op
+# define DO_NEXT_OP(n) JS_BEGIN_MACRO \
+ JS_ASSERT((n) == len); \
+ goto advance_pc; \
+ JS_END_MACRO
+
+# define BEGIN_CASE(OP) case OP:
+# define END_CASE(OP) END_CASE_LEN(OP##_LENGTH)
+# define END_CASE_LEN(n) END_CASE_LENX(n)
+# define END_CASE_LENX(n) END_CASE_LEN##n
+
+/*
+ * To share the code for all len == 1 cases we use the specialized label with
+ * code that falls through to advance_pc: .
+ */
+# define END_CASE_LEN1 goto advance_pc_by_one;
+# define END_CASE_LEN2 len = 2; goto advance_pc;
+# define END_CASE_LEN3 len = 3; goto advance_pc;
+# define END_CASE_LEN4 len = 4; goto advance_pc;
+# define END_CASE_LEN5 len = 5; goto advance_pc;
+# define END_VARLEN_CASE goto advance_pc;
+# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
+# define END_EMPTY_CASES goto advance_pc_by_one;
+
+#endif /* !JS_THREADED_INTERP */
+
+#ifdef JS_TRACER
+ /* We had better not be entering the interpreter from JIT-compiled code. */
+ TraceRecorder *tr = NULL;
+ if (JS_ON_TRACE(cx)) {
+ tr = TRACE_RECORDER(cx);
+ SET_TRACE_RECORDER(cx, NULL);
+ JS_TRACE_MONITOR(cx).onTrace = JS_FALSE;
+ /*
+ * ON_TRACE means either recording or coming from traced code.
+ * If there's no recorder (the latter case), don't care.
+ */
+ if (tr) {
+ if (tr->wasDeepAborted())
+ tr->removeFragmentoReferences();
+ else
+ tr->pushAbortStack();
+ }
+ }
+#endif
+
+ /* Check for too deep of a native thread stack. */
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ rt = cx->runtime;
+
+ /* Set registerized frame pointer and derived script pointer. */
+ fp = cx->fp;
+ script = fp->script;
+ JS_ASSERT(script->length != 0);
+
+ /* Count of JS function calls that nest in this C js_Interpret frame. */
+ inlineCallCount = 0;
+
+ /*
+ * Initialize the index segment register used by LOAD_ATOM and
+ * GET_FULL_INDEX macros below. As a register we use a pointer based on
+ * the atom map to turn frequently executed LOAD_ATOM into simple array
+ * access. For less frequent object and regexp loads we have to recover
+ * the segment from atoms pointer first.
+ */
+ atoms = script->atomMap.vector;
+
+#define LOAD_ATOM(PCOFF) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(fp->imacpc \
+ ? atoms == COMMON_ATOMS_START(&rt->atomState) && \
+ GET_INDEX(regs.pc + PCOFF) < js_common_atom_count \
+ : (size_t)(atoms - script->atomMap.vector) < \
+ (size_t)(script->atomMap.length - \
+ GET_INDEX(regs.pc + PCOFF))); \
+ atom = atoms[GET_INDEX(regs.pc + PCOFF)]; \
+ JS_END_MACRO
+
+#define GET_FULL_INDEX(PCOFF) \
+ (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))
+
+#define LOAD_OBJECT(PCOFF) \
+ JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(PCOFF), obj)
+
+#define LOAD_FUNCTION(PCOFF) \
+ JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)
+
+#ifdef JS_TRACER
+
+#define MONITOR_BRANCH() \
+ JS_BEGIN_MACRO \
+ if (TRACING_ENABLED(cx)) { \
+ ENABLE_TRACER(js_MonitorLoopEdge(cx, inlineCallCount)); \
+ fp = cx->fp; \
+ script = fp->script; \
+ atoms = script->atomMap.vector; \
+ currentVersion = (JSVersion) script->version; \
+ JS_ASSERT(fp->regs == &regs); \
+ if (cx->throwing) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#else /* !JS_TRACER */
+
+#define MONITOR_BRANCH() ((void) 0)
+
+#endif /* !JS_TRACER */
+
+ /*
+ * Prepare to call a user-supplied branch handler, and abort the script
+ * if it returns false.
+ */
+#define CHECK_BRANCH() \
+ JS_BEGIN_MACRO \
+ if ((cx->operationCount -= JSOW_SCRIPT_JUMP) <= 0) { \
+ if (!js_ResetOperationCount(cx)) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#define BRANCH(n) \
+ JS_BEGIN_MACRO \
+ regs.pc += n; \
+ if (n <= 0) { \
+ CHECK_BRANCH(); \
+ MONITOR_BRANCH(); \
+ } \
+ op = (JSOp) *regs.pc; \
+ DO_OP(); \
+ JS_END_MACRO
+
+ MUST_FLOW_THROUGH("exit");
+ ++cx->interpLevel;
+
+ /*
+ * Optimized Get and SetVersion for proper script language versioning.
+ *
+ * If any native method or JSClass/JSObjectOps hook calls js_SetVersion
+ * and changes cx->version, the effect will "stick" and we will stop
+ * maintaining currentVersion. This is relied upon by testsuites, for
+ * the most part -- web browsers select version before compiling and not
+ * at run-time.
+ */
+ currentVersion = (JSVersion) script->version;
+ originalVersion = (JSVersion) cx->version;
+ if (currentVersion != originalVersion)
+ js_SetVersion(cx, currentVersion);
+
+ /* Update the static-link display. */
+ if (script->staticDepth < JS_DISPLAY_SIZE) {
+ JSStackFrame **disp = &cx->display[script->staticDepth];
+ fp->displaySave = *disp;
+ *disp = fp;
+ }
+#ifdef DEBUG
+ fp->pcDisabledSave = JS_PROPERTY_CACHE(cx).disabled;
+#endif
+
+ /*
+ * Load the debugger's interrupt hook here and after calling out to native
+ * functions (but not to getters, setters, or other native hooks), so we do
+ * not have to reload it each time through the interpreter loop -- we hope
+ * the compiler can keep it in a register when it is non-null.
+ */
+#if JS_THREADED_INTERP
+#ifdef JS_TRACER
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (jumpTable = (cx)->debugHooks->interruptHandler \
+ ? interruptJumpTable \
+ : TRACE_RECORDER(cx) \
+ ? recordingJumpTable \
+ : normalJumpTable))
+# define ENABLE_TRACER(flag) \
+ JS_BEGIN_MACRO \
+ bool flag_ = (flag); \
+ JS_ASSERT(flag_ == !!TRACE_RECORDER(cx)); \
+ jumpTable = flag_ ? recordingJumpTable : normalJumpTable; \
+ JS_END_MACRO
+#else /* !JS_TRACER */
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (jumpTable = (cx)->debugHooks->interruptHandler \
+ ? interruptJumpTable \
+ : normalJumpTable))
+# define ENABLE_TRACER(flag) ((void)0)
+#endif /* !JS_TRACER */
+#else /* !JS_THREADED_INTERP */
+#ifdef JS_TRACER
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (switchMask = ((cx)->debugHooks->interruptHandler || \
+ TRACE_RECORDER(cx)) ? 0 : 255))
+# define ENABLE_TRACER(flag) \
+ JS_BEGIN_MACRO \
+ bool flag_ = (flag); \
+ JS_ASSERT(flag_ == !!TRACE_RECORDER(cx)); \
+ switchMask = flag_ ? 0 : 255; \
+ JS_END_MACRO
+#else /* !JS_TRACER */
+# define LOAD_INTERRUPT_HANDLER(cx) \
+ ((void) (switchMask = ((cx)->debugHooks->interruptHandler \
+ ? 0 : 255)))
+# define ENABLE_TRACER(flag) ((void)0)
+#endif /* !JS_TRACER */
+#endif /* !JS_THREADED_INTERP */
+
+ LOAD_INTERRUPT_HANDLER(cx);
+
+#if !JS_HAS_GENERATORS
+ JS_ASSERT(!fp->regs);
+#else
+ /* Initialize the pc and sp registers unless we're resuming a generator. */
+ if (JS_LIKELY(!fp->regs)) {
+#endif
+ ASSERT_NOT_THROWING(cx);
+ regs.pc = script->code;
+ regs.sp = StackBase(fp);
+ fp->regs = &regs;
+#if JS_HAS_GENERATORS
+ } else {
+ JSGenerator *gen;
+
+ JS_ASSERT(fp->flags & JSFRAME_GENERATOR);
+ gen = FRAME_TO_GENERATOR(fp);
+ JS_ASSERT(fp->regs == &gen->savedRegs);
+ regs = gen->savedRegs;
+ fp->regs = &regs;
+ JS_ASSERT((size_t) (regs.pc - script->code) <= script->length);
+ JS_ASSERT((size_t) (regs.sp - StackBase(fp)) <= StackDepth(script));
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+ JS_PROPERTY_CACHE(cx).disabled += js_CountWithBlocks(cx, fp);
+
+ /*
+ * To support generator_throw and to catch ignored exceptions,
+ * fail if cx->throwing is set.
+ */
+ if (cx->throwing) {
+#ifdef DEBUG_NOT_THROWING
+ if (cx->exception != JSVAL_ARETURN) {
+ printf("JS INTERPRETER CALLED WITH PENDING EXCEPTION %lx\n",
+ (unsigned long) cx->exception);
+ }
+#endif
+ goto error;
+ }
+ }
+#endif /* JS_HAS_GENERATORS */
+
+ /*
+ * It is important that "op" be initialized before calling DO_OP because
+ * it is possible for "op" to be specially assigned during the normal
+ * processing of an opcode while looping. We rely on DO_NEXT_OP to manage
+ * "op" correctly in all other cases.
+ */
+ len = 0;
+ DO_NEXT_OP(len);
+
+#if JS_THREADED_INTERP
+ /*
+ * This is a loop, but it does not look like a loop. The loop-closing
+ * jump is distributed throughout goto *jumpTable[op] inside of DO_OP.
+ * When interrupts are enabled, jumpTable is set to interruptJumpTable
+ * where all jumps point to the JSOP_INTERRUPT case. The latter, after
+ * calling the interrupt handler, dispatches through normalJumpTable to
+ * continue the normal bytecode processing.
+ */
+#else
+ for (;;) {
+ advance_pc_by_one:
+ JS_ASSERT(js_CodeSpec[op].length == 1);
+ len = 1;
+ advance_pc:
+ regs.pc += len;
+ op = (JSOp) *regs.pc;
+#ifdef DEBUG
+ if (cx->tracefp)
+ js_TraceOpcode(cx, len);
+#endif
+
+ do_op:
+ switchOp = op & switchMask;
+ do_switch:
+ switch (switchOp) {
+#endif /* !JS_THREADED_INTERP */
+
+ BEGIN_CASE(JSOP_INTERRUPT)
+ {
+ JSTrapHandler handler;
+
+ handler = cx->debugHooks->interruptHandler;
+ if (handler) {
+ switch (handler(cx, script, regs.pc, &rval,
+ cx->debugHooks->interruptHandlerData)) {
+ case JSTRAP_ERROR:
+ goto error;
+ case JSTRAP_CONTINUE:
+ break;
+ case JSTRAP_RETURN:
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ default:;
+ }
+#if !JS_THREADED_INTERP
+ } else {
+ /* this was not a real interrupt, the tracer is trying to
+ record a trace */
+ switchOp = op + 256;
+ goto do_switch;
+#endif
+ }
+ LOAD_INTERRUPT_HANDLER(cx);
+
+#if JS_THREADED_INTERP
+ JS_EXTENSION_(goto *normalJumpTable[op]);
+#else
+ switchOp = op;
+ goto do_switch;
+#endif
+ }
+
+ /* No-ops for ease of decompilation. */
+ ADD_EMPTY_CASE(JSOP_NOP)
+ ADD_EMPTY_CASE(JSOP_CONDSWITCH)
+ ADD_EMPTY_CASE(JSOP_TRY)
+ ADD_EMPTY_CASE(JSOP_FINALLY)
+#if JS_HAS_XML_SUPPORT
+ ADD_EMPTY_CASE(JSOP_STARTXML)
+ ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
+#endif
+ END_EMPTY_CASES
+
+ /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */
+ BEGIN_CASE(JSOP_LINENO)
+ END_CASE(JSOP_LINENO)
+
+ BEGIN_CASE(JSOP_PUSH)
+ PUSH_OPND(JSVAL_VOID);
+ END_CASE(JSOP_PUSH)
+
+ BEGIN_CASE(JSOP_POP)
+ regs.sp--;
+ END_CASE(JSOP_POP)
+
+ BEGIN_CASE(JSOP_POPN)
+ regs.sp -= GET_UINT16(regs.pc);
+#ifdef DEBUG
+ JS_ASSERT(StackBase(fp) <= regs.sp);
+ obj = fp->blockChain;
+ JS_ASSERT_IF(obj,
+ OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
+ <= (size_t) (regs.sp - StackBase(fp)));
+ for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp != &js_BlockClass && clasp != &js_WithClass)
+ continue;
+ if (OBJ_GET_PRIVATE(cx, obj) != fp)
+ break;
+ JS_ASSERT(StackBase(fp) + OBJ_BLOCK_DEPTH(cx, obj)
+ + ((clasp == &js_BlockClass)
+ ? OBJ_BLOCK_COUNT(cx, obj)
+ : 1)
+ <= regs.sp);
+ }
+#endif
+ END_CASE(JSOP_POPN)
+
+ BEGIN_CASE(JSOP_SETRVAL)
+ BEGIN_CASE(JSOP_POPV)
+ ASSERT_NOT_THROWING(cx);
+ fp->rval = POP_OPND();
+ END_CASE(JSOP_POPV)
+
+ BEGIN_CASE(JSOP_ENTERWITH)
+ if (!js_EnterWith(cx, -1))
+ goto error;
+
+ /*
+ * We must ensure that different "with" blocks have different
+ * stack depth associated with them. This allows the try handler
+ * search to properly recover the scope chain. Thus we must keep
+ * the stack at least at the current level.
+ *
+ * We set sp[-1] to the current "with" object to help asserting
+ * the enter/leave balance in [leavewith].
+ */
+ regs.sp[-1] = OBJECT_TO_JSVAL(fp->scopeChain);
+ END_CASE(JSOP_ENTERWITH)
+
+ BEGIN_CASE(JSOP_LEAVEWITH)
+ JS_ASSERT(regs.sp[-1] == OBJECT_TO_JSVAL(fp->scopeChain));
+ regs.sp--;
+ js_LeaveWith(cx);
+ END_CASE(JSOP_LEAVEWITH)
+
+ BEGIN_CASE(JSOP_RETURN)
+ CHECK_BRANCH();
+ fp->rval = POP_OPND();
+ /* FALL THROUGH */
+
+ BEGIN_CASE(JSOP_RETRVAL) /* fp->rval already set */
+ BEGIN_CASE(JSOP_STOP)
+ /*
+ * When the inlined frame exits with an exception or an error, ok
+ * will be false after the inline_return label.
+ */
+ ASSERT_NOT_THROWING(cx);
+
+ if (fp->imacpc) {
+ /*
+ * If we are at the end of an imacro, return to its caller in
+ * the current frame.
+ */
+ JS_ASSERT(op == JSOP_STOP);
+
+ end_imacro:
+ JS_ASSERT((uintN)(regs.sp - fp->slots) <= script->nslots);
+ regs.pc = fp->imacpc + js_CodeSpec[*fp->imacpc].length;
+ fp->imacpc = NULL;
+ atoms = script->atomMap.vector;
+ op = JSOp(*regs.pc);
+ DO_OP();
+ }
+
+ JS_ASSERT(regs.sp == StackBase(fp));
+ if ((fp->flags & JSFRAME_CONSTRUCTING) &&
+ JSVAL_IS_PRIMITIVE(fp->rval)) {
+ if (!fp->fun) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_NEW_RESULT,
+ js_ValueToPrintableString(cx, rval));
+ goto error;
+ }
+ fp->rval = OBJECT_TO_JSVAL(fp->thisp);
+ }
+ ok = JS_TRUE;
+ if (inlineCallCount)
+ inline_return:
+ {
+ JSInlineFrame *ifp = (JSInlineFrame *) fp;
+ void *hookData = ifp->hookData;
+
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
+ JS_ASSERT(!fp->blockChain);
+ JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
+
+ if (script->staticDepth < JS_DISPLAY_SIZE)
+ cx->display[script->staticDepth] = fp->displaySave;
+
+ if (hookData) {
+ JSInterpreterHook hook;
+ JSBool status;
+
+ hook = cx->debugHooks->callHook;
+ if (hook) {
+ /*
+ * Do not pass &ok directly as exposing the address
+ * inhibits optimizations and uninitialised warnings.
+ */
+ status = ok;
+ hook(cx, fp, JS_FALSE, &status, hookData);
+ ok = status;
+ LOAD_INTERRUPT_HANDLER(cx);
+ }
+ }
+
+ /*
+ * If fp has a call object, sync values and clear the back-
+ * pointer. This can happen for a lightweight function if it
+ * calls eval unexpectedly (in a way that is hidden from the
+ * compiler). See bug 325540.
+ */
+ if (fp->callobj)
+ ok &= js_PutCallObject(cx, fp);
+
+ if (fp->argsobj)
+ ok &= js_PutArgsObject(cx, fp);
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function return, inlines */
+ if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
+ jsdtrace_function_rval(cx, fp, fp->fun);
+ if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
+ jsdtrace_function_return(cx, fp, fp->fun);
+#endif
+
+ /* Restore context version only if callee hasn't set version. */
+ if (JS_LIKELY(cx->version == currentVersion)) {
+ currentVersion = ifp->callerVersion;
+ if (currentVersion != cx->version)
+ js_SetVersion(cx, currentVersion);
+ }
+
+ /*
+ * If inline-constructing, replace primitive rval with the new
+ * object passed in via |this|, and instrument this constructor
+ * invocation
+ */
+ if (fp->flags & JSFRAME_CONSTRUCTING) {
+ if (JSVAL_IS_PRIMITIVE(fp->rval))
+ fp->rval = OBJECT_TO_JSVAL(fp->thisp);
+ JS_RUNTIME_METER(cx->runtime, constructs);
+ }
+
+ /* Restore caller's registers. */
+ regs = ifp->callerRegs;
+
+ /* Store the return value in the caller's operand frame. */
+ regs.sp -= 1 + (size_t) ifp->frame.argc;
+ regs.sp[-1] = fp->rval;
+
+ /* Restore cx->fp and release the inline frame's space. */
+ cx->fp = fp = fp->down;
+ JS_ASSERT(fp->regs == &ifp->callerRegs);
+ fp->regs = &regs;
+ JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);
+
+ /* Restore the calling script's interpreter registers. */
+ script = fp->script;
+ atoms = script->atomMap.vector;
+
+ /* Resume execution in the calling frame. */
+ inlineCallCount--;
+ if (JS_LIKELY(ok)) {
+ TRACE_0(LeaveFrame);
+ JS_ASSERT(js_CodeSpec[*regs.pc].length == JSOP_CALL_LENGTH);
+ len = JSOP_CALL_LENGTH;
+ DO_NEXT_OP(len);
+ }
+ goto error;
+ }
+ goto exit;
+
+ BEGIN_CASE(JSOP_DEFAULT)
+ (void) POP();
+ /* FALL THROUGH */
+ BEGIN_CASE(JSOP_GOTO)
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ END_CASE(JSOP_GOTO)
+
+ BEGIN_CASE(JSOP_IFEQ)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFEQ)
+
+ BEGIN_CASE(JSOP_IFNE)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond != JS_FALSE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFNE)
+
+ BEGIN_CASE(JSOP_OR)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_TRUE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_OR)
+
+ BEGIN_CASE(JSOP_AND)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_AND)
+
+ BEGIN_CASE(JSOP_DEFAULTX)
+ (void) POP();
+ /* FALL THROUGH */
+ BEGIN_CASE(JSOP_GOTOX)
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ END_CASE(JSOP_GOTOX);
+
+ BEGIN_CASE(JSOP_IFEQX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFEQX)
+
+ BEGIN_CASE(JSOP_IFNEX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond != JS_FALSE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ END_CASE(JSOP_IFNEX)
+
+ BEGIN_CASE(JSOP_ORX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_TRUE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_ORX)
+
+ BEGIN_CASE(JSOP_ANDX)
+ POP_BOOLEAN(cx, rval, cond);
+ if (cond == JS_FALSE) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ PUSH_OPND(rval);
+ DO_NEXT_OP(len);
+ }
+ END_CASE(JSOP_ANDX)
+
+/*
+ * If the index value at sp[n] is not an int that fits in a jsval, it could
+ * be an object (an XML QName, AttributeName, or AnyName), but only if we are
+ * compiling with JS_HAS_XML_SUPPORT. Otherwise convert the index value to a
+ * string atom id.
+ */
+#define FETCH_ELEMENT_ID(obj, n, id) \
+ JS_BEGIN_MACRO \
+ jsval idval_ = FETCH_OPND(n); \
+ if (JSVAL_IS_INT(idval_)) { \
+ id = INT_JSVAL_TO_JSID(idval_); \
+ } else { \
+ if (!js_InternNonIntElementId(cx, obj, idval_, &id)) \
+ goto error; \
+ regs.sp[n] = ID_TO_VALUE(id); \
+ } \
+ JS_END_MACRO
+
+#define TRY_BRANCH_AFTER_COND(cond,spdec) \
+ JS_BEGIN_MACRO \
+ uintN diff_; \
+ JS_ASSERT(js_CodeSpec[op].length == 1); \
+ diff_ = (uintN) regs.pc[1] - (uintN) JSOP_IFEQ; \
+ if (diff_ <= 1) { \
+ regs.sp -= spdec; \
+ if (cond == (diff_ != 0)) { \
+ ++regs.pc; \
+ len = GET_JUMP_OFFSET(regs.pc); \
+ BRANCH(len); \
+ } \
+ len = 1 + JSOP_IFEQ_LENGTH; \
+ DO_NEXT_OP(len); \
+ } \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_IN)
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_PRIMITIVE(rval)) {
+ js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rval, NULL);
+ goto error;
+ }
+ obj = JSVAL_TO_OBJECT(rval);
+ FETCH_ELEMENT_ID(obj, -2, id);
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ goto error;
+ cond = prop != NULL;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ TRY_BRANCH_AFTER_COND(cond, 2);
+ regs.sp--;
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
+ END_CASE(JSOP_IN)
+
+ BEGIN_CASE(JSOP_ITER)
+ JS_ASSERT(regs.sp > StackBase(fp));
+ flags = regs.pc[1];
+ if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))
+ goto error;
+ LOAD_INTERRUPT_HANDLER(cx);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1]));
+ PUSH(JSVAL_VOID);
+ END_CASE(JSOP_ITER)
+
+ BEGIN_CASE(JSOP_NEXTITER)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-2]));
+ if (!js_CallIteratorNext(cx, JSVAL_TO_OBJECT(regs.sp[-2]), &regs.sp[-1]))
+ goto error;
+ LOAD_INTERRUPT_HANDLER(cx);
+ rval = BOOLEAN_TO_JSVAL(regs.sp[-1] != JSVAL_HOLE);
+ PUSH(rval);
+ TRACE_0(IteratorNextComplete);
+ END_CASE(JSOP_NEXTITER)
+
+ BEGIN_CASE(JSOP_ENDITER)
+ /*
+ * Decrease the stack pointer even when !ok -- see comments in the
+ * exception capturing code for details.
+ */
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ ok = js_CloseIterator(cx, regs.sp[-2]);
+ regs.sp -= 2;
+ if (!ok)
+ goto error;
+ END_CASE(JSOP_ENDITER)
+
+ BEGIN_CASE(JSOP_FORARG)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ fp->argv[slot] = regs.sp[-1];
+ END_CASE(JSOP_FORARG)
+
+ BEGIN_CASE(JSOP_FORLOCAL)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < fp->script->nslots);
+ vp = &fp->slots[slot];
+ GC_POKE(cx, *vp);
+ *vp = regs.sp[-1];
+ END_CASE(JSOP_FORLOCAL)
+
+ BEGIN_CASE(JSOP_FORNAME)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+ goto error;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+ if (!ok)
+ goto error;
+ END_CASE(JSOP_FORNAME)
+
+ BEGIN_CASE(JSOP_FORPROP)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ FETCH_OBJECT(cx, -1, lval, obj);
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-2]);
+ if (!ok)
+ goto error;
+ regs.sp--;
+ END_CASE(JSOP_FORPROP)
+
+ BEGIN_CASE(JSOP_FORELEM)
+ /*
+ * JSOP_FORELEM simply dups the property identifier at top of stack
+ * and lets the subsequent JSOP_ENUMELEM opcode sequence handle the
+ * left-hand side expression evaluation and assignment. This opcode
+ * exists solely to help the decompiler.
+ */
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ rval = FETCH_OPND(-1);
+ PUSH(rval);
+ END_CASE(JSOP_FORELEM)
+
+ BEGIN_CASE(JSOP_DUP)
+ JS_ASSERT(regs.sp > StackBase(fp));
+ rval = FETCH_OPND(-1);
+ PUSH(rval);
+ END_CASE(JSOP_DUP)
+
+ BEGIN_CASE(JSOP_DUP2)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ lval = FETCH_OPND(-2);
+ rval = FETCH_OPND(-1);
+ PUSH(lval);
+ PUSH(rval);
+ END_CASE(JSOP_DUP2)
+
+ BEGIN_CASE(JSOP_SWAP)
+ JS_ASSERT(regs.sp - 2 >= StackBase(fp));
+ lval = FETCH_OPND(-2);
+ rval = FETCH_OPND(-1);
+ STORE_OPND(-1, lval);
+ STORE_OPND(-2, rval);
+ END_CASE(JSOP_SWAP)
+
+#define PROPERTY_OP(n, call) \
+ JS_BEGIN_MACRO \
+ /* Fetch the left part and resolve it to a non-null object. */ \
+ FETCH_OBJECT(cx, n, lval, obj); \
+ \
+ /* Get or set the property. */ \
+ if (!call) \
+ goto error; \
+ JS_END_MACRO
+
+#define ELEMENT_OP(n, call) \
+ JS_BEGIN_MACRO \
+ /* Fetch the left part and resolve it to a non-null object. */ \
+ FETCH_OBJECT(cx, n - 1, lval, obj); \
+ \
+ /* Fetch index and convert it to id suitable for use with obj. */ \
+ FETCH_ELEMENT_ID(obj, n, id); \
+ \
+ /* Get or set the element. */ \
+ if (!call) \
+ goto error; \
+ JS_END_MACRO
+
+#define NATIVE_GET(cx,obj,pobj,sprop,vp) \
+ JS_BEGIN_MACRO \
+ if (SPROP_HAS_STUB_GETTER(sprop)) { \
+ /* Fast path for Object instance properties. */ \
+ JS_ASSERT((sprop)->slot != SPROP_INVALID_SLOT || \
+ !SPROP_HAS_STUB_SETTER(sprop)); \
+ *vp = ((sprop)->slot != SPROP_INVALID_SLOT) \
+ ? LOCKED_OBJ_GET_SLOT(pobj, (sprop)->slot) \
+ : JSVAL_VOID; \
+ } else { \
+ if (!js_NativeGet(cx, obj, pobj, sprop, vp)) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+#define NATIVE_SET(cx,obj,sprop,vp) \
+ JS_BEGIN_MACRO \
+ if (SPROP_HAS_STUB_SETTER(sprop) && \
+ (sprop)->slot != SPROP_INVALID_SLOT) { \
+ /* Fast path for, e.g., Object instance properties. */ \
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *vp); \
+ } else { \
+ if (!js_NativeSet(cx, obj, sprop, vp)) \
+ goto error; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Deadlocks or else bad races are likely if JS_THREADSAFE, so we must rely on
+ * single-thread DEBUG js shell testing to verify property cache hits.
+ */
+#if defined DEBUG && !defined JS_THREADSAFE
+# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) \
+ do { \
+ JSAtom *atom_; \
+ JSObject *obj_, *pobj_; \
+ JSProperty *prop_; \
+ JSScopeProperty *sprop_; \
+ uint32 sample_ = rt->gcNumber; \
+ if (pcoff >= 0) \
+ GET_ATOM_FROM_BYTECODE(script, regs.pc, pcoff, atom_); \
+ else \
+ atom_ = rt->atomState.lengthAtom; \
+ if (JOF_OPMODE(*regs.pc) == JOF_NAME) { \
+ ok = js_FindProperty(cx, ATOM_TO_JSID(atom_), &obj_, &pobj_, \
+ &prop_); \
+ } else { \
+ obj_ = obj; \
+ ok = js_LookupProperty(cx, obj, ATOM_TO_JSID(atom_), &pobj_, \
+ &prop_); \
+ } \
+ if (!ok) \
+ goto error; \
+ if (rt->gcNumber != sample_) \
+ break; \
+ JS_ASSERT(prop_); \
+ JS_ASSERT(pobj_ == pobj); \
+ sprop_ = (JSScopeProperty *) prop_; \
+ if (PCVAL_IS_SLOT(entry->vword)) { \
+ JS_ASSERT(PCVAL_TO_SLOT(entry->vword) == sprop_->slot); \
+ } else if (PCVAL_IS_SPROP(entry->vword)) { \
+ JS_ASSERT(PCVAL_TO_SPROP(entry->vword) == sprop_); \
+ } else { \
+ jsval v_; \
+ JS_ASSERT(PCVAL_IS_OBJECT(entry->vword)); \
+ JS_ASSERT(entry->vword != PCVAL_NULL); \
+ JS_ASSERT(SCOPE_IS_BRANDED(OBJ_SCOPE(pobj))); \
+ JS_ASSERT(SPROP_HAS_STUB_GETTER(sprop_)); \
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop_, OBJ_SCOPE(pobj_))); \
+ v_ = LOCKED_OBJ_GET_SLOT(pobj_, sprop_->slot); \
+ JS_ASSERT(VALUE_IS_FUNCTION(cx, v_)); \
+ JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v_)); \
+ } \
+ OBJ_DROP_PROPERTY(cx, pobj_, prop_); \
+ } while (0)
+#else
+# define ASSERT_VALID_PROPERTY_CACHE_HIT(pcoff,obj,pobj,entry) ((void) 0)
+#endif
+
+/*
+ * Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is
+ * the constant length of the SET opcode sequence, and spdec is the constant
+ * by which to decrease the stack pointer to pop all of the SET op's operands.
+ *
+ * NB: unlike macros that could conceivably be replaced by functions (ignoring
+ * goto error), where a call should not have to be braced in order to expand
+ * correctly (e.g., in if (cond) FOO(); else BAR()), these three macros lack
+ * JS_{BEGIN,END}_MACRO brackets. They are also indented so as to align with
+ * nearby opcode code.
+ */
+#define SKIP_POP_AFTER_SET(oplen,spdec) \
+ if (regs.pc[oplen] == JSOP_POP) { \
+ regs.sp -= spdec; \
+ regs.pc += oplen + JSOP_POP_LENGTH; \
+ op = (JSOp) *regs.pc; \
+ DO_OP(); \
+ }
+
+#define END_SET_CASE(OP) \
+ SKIP_POP_AFTER_SET(OP##_LENGTH, 1); \
+ END_CASE(OP)
+
+#define END_SET_CASE_STORE_RVAL(OP,spdec) \
+ SKIP_POP_AFTER_SET(OP##_LENGTH, spdec); \
+ rval = FETCH_OPND(-1); \
+ regs.sp -= (spdec) - 1; \
+ STORE_OPND(-1, rval); \
+ END_CASE(OP)
+
+ BEGIN_CASE(JSOP_SETCONST)
+ LOAD_ATOM(0);
+ obj = fp->varobj;
+ rval = FETCH_OPND(-1);
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY,
+ NULL)) {
+ goto error;
+ }
+ END_SET_CASE(JSOP_SETCONST);
+
+#if JS_HAS_DESTRUCTURING
+ BEGIN_CASE(JSOP_ENUMCONSTELEM)
+ rval = FETCH_OPND(-3);
+ FETCH_OBJECT(cx, -2, lval, obj);
+ FETCH_ELEMENT_ID(obj, -1, id);
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, id, rval,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY,
+ NULL)) {
+ goto error;
+ }
+ regs.sp -= 3;
+ END_CASE(JSOP_ENUMCONSTELEM)
+#endif
+
+ BEGIN_CASE(JSOP_BINDNAME)
+ do {
+ JSPropCacheEntry *entry;
+
+ obj = fp->scopeChain;
+ if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ JS_UNLOCK_OBJ(cx, obj2);
+ break;
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+ id = ATOM_TO_JSID(atom);
+ obj = js_FindIdentifierBase(cx, id, entry);
+ if (!obj)
+ goto error;
+ } while (0);
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_BINDNAME)
+
+ BEGIN_CASE(JSOP_IMACOP)
+ JS_ASSERT(JS_UPTRDIFF(fp->imacpc, script->code) < script->length);
+ op = JSOp(*fp->imacpc);
+ DO_OP();
+
+#define BITWISE_OP(OP) \
+ JS_BEGIN_MACRO \
+ FETCH_INT(cx, -2, i); \
+ FETCH_INT(cx, -1, j); \
+ i = i OP j; \
+ regs.sp--; \
+ STORE_INT(cx, -1, i); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_BITOR)
+ BITWISE_OP(|);
+ END_CASE(JSOP_BITOR)
+
+ BEGIN_CASE(JSOP_BITXOR)
+ BITWISE_OP(^);
+ END_CASE(JSOP_BITXOR)
+
+ BEGIN_CASE(JSOP_BITAND)
+ BITWISE_OP(&);
+ END_CASE(JSOP_BITAND)
+
+#define RELATIONAL_OP(OP) \
+ JS_BEGIN_MACRO \
+ rval = FETCH_OPND(-1); \
+ lval = FETCH_OPND(-2); \
+ /* Optimize for two int-tagged operands (typical loop control). */ \
+ if ((lval & rval) & JSVAL_INT) { \
+ cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval); \
+ } else { \
+ if (!JSVAL_IS_PRIMITIVE(lval)) \
+ DEFAULT_VALUE(cx, -2, JSTYPE_NUMBER, lval); \
+ if (!JSVAL_IS_PRIMITIVE(rval)) \
+ DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval); \
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { \
+ str = JSVAL_TO_STRING(lval); \
+ str2 = JSVAL_TO_STRING(rval); \
+ cond = js_CompareStrings(str, str2) OP 0; \
+ } else { \
+ VALUE_TO_NUMBER(cx, -2, lval, d); \
+ VALUE_TO_NUMBER(cx, -1, rval, d2); \
+ cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE); \
+ } \
+ } \
+ TRY_BRANCH_AFTER_COND(cond, 2); \
+ regs.sp--; \
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
+ JS_END_MACRO
+
+/*
+ * NB: These macros can't use JS_BEGIN_MACRO/JS_END_MACRO around their bodies
+ * because they begin if/else chains, so callers must not put semicolons after
+ * the call expressions!
+ */
+#if JS_HAS_XML_SUPPORT
+#define XML_EQUALITY_OP(OP) \
+ if ((ltmp == JSVAL_OBJECT && \
+ (obj2 = JSVAL_TO_OBJECT(lval)) && \
+ OBJECT_IS_XML(cx, obj2)) || \
+ (rtmp == JSVAL_OBJECT && \
+ (obj2 = JSVAL_TO_OBJECT(rval)) && \
+ OBJECT_IS_XML(cx, obj2))) { \
+ JSXMLObjectOps *ops; \
+ \
+ ops = (JSXMLObjectOps *) obj2->map->ops; \
+ if (obj2 == JSVAL_TO_OBJECT(rval)) \
+ rval = lval; \
+ if (!ops->equality(cx, obj2, rval, &cond)) \
+ goto error; \
+ cond = cond OP JS_TRUE; \
+ } else
+
+#define EXTENDED_EQUALITY_OP(OP) \
+ if (ltmp == JSVAL_OBJECT && \
+ (obj2 = JSVAL_TO_OBJECT(lval)) && \
+ ((clasp = OBJ_GET_CLASS(cx, obj2))->flags & JSCLASS_IS_EXTENDED)) { \
+ JSExtendedClass *xclasp; \
+ \
+ xclasp = (JSExtendedClass *) clasp; \
+ if (!xclasp->equality(cx, obj2, rval, &cond)) \
+ goto error; \
+ cond = cond OP JS_TRUE; \
+ } else
+#else
+#define XML_EQUALITY_OP(OP) /* nothing */
+#define EXTENDED_EQUALITY_OP(OP) /* nothing */
+#endif
+
+#define EQUALITY_OP(OP, IFNAN) \
+ JS_BEGIN_MACRO \
+ rval = FETCH_OPND(-1); \
+ lval = FETCH_OPND(-2); \
+ ltmp = JSVAL_TAG(lval); \
+ rtmp = JSVAL_TAG(rval); \
+ XML_EQUALITY_OP(OP) \
+ if (ltmp == rtmp) { \
+ if (ltmp == JSVAL_STRING) { \
+ str = JSVAL_TO_STRING(lval); \
+ str2 = JSVAL_TO_STRING(rval); \
+ cond = js_EqualStrings(str, str2) OP JS_TRUE; \
+ } else if (ltmp == JSVAL_DOUBLE) { \
+ d = *JSVAL_TO_DOUBLE(lval); \
+ d2 = *JSVAL_TO_DOUBLE(rval); \
+ cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \
+ } else { \
+ EXTENDED_EQUALITY_OP(OP) \
+ /* Handle all undefined (=>NaN) and int combinations. */ \
+ cond = lval OP rval; \
+ } \
+ } else { \
+ if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) { \
+ cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1; \
+ } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) { \
+ cond = 1 OP 0; \
+ } else { \
+ if (ltmp == JSVAL_OBJECT) { \
+ DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval); \
+ ltmp = JSVAL_TAG(lval); \
+ } else if (rtmp == JSVAL_OBJECT) { \
+ DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval); \
+ rtmp = JSVAL_TAG(rval); \
+ } \
+ if (ltmp == JSVAL_STRING && rtmp == JSVAL_STRING) { \
+ str = JSVAL_TO_STRING(lval); \
+ str2 = JSVAL_TO_STRING(rval); \
+ cond = js_EqualStrings(str, str2) OP JS_TRUE; \
+ } else { \
+ VALUE_TO_NUMBER(cx, -2, lval, d); \
+ VALUE_TO_NUMBER(cx, -1, rval, d2); \
+ cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN); \
+ } \
+ } \
+ } \
+ TRY_BRANCH_AFTER_COND(cond, 2); \
+ regs.sp--; \
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_EQ)
+ EQUALITY_OP(==, JS_FALSE);
+ END_CASE(JSOP_EQ)
+
+ BEGIN_CASE(JSOP_NE)
+ EQUALITY_OP(!=, JS_TRUE);
+ END_CASE(JSOP_NE)
+
+#define STRICT_EQUALITY_OP(OP) \
+ JS_BEGIN_MACRO \
+ rval = FETCH_OPND(-1); \
+ lval = FETCH_OPND(-2); \
+ cond = js_StrictlyEqual(cx, lval, rval) OP JS_TRUE; \
+ regs.sp--; \
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond)); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_STRICTEQ)
+ STRICT_EQUALITY_OP(==);
+ END_CASE(JSOP_STRICTEQ)
+
+ BEGIN_CASE(JSOP_STRICTNE)
+ STRICT_EQUALITY_OP(!=);
+ END_CASE(JSOP_STRICTNE)
+
+ BEGIN_CASE(JSOP_CASE)
+ STRICT_EQUALITY_OP(==);
+ (void) POP();
+ if (cond) {
+ len = GET_JUMP_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ PUSH(lval);
+ END_CASE(JSOP_CASE)
+
+ BEGIN_CASE(JSOP_CASEX)
+ STRICT_EQUALITY_OP(==);
+ (void) POP();
+ if (cond) {
+ len = GET_JUMPX_OFFSET(regs.pc);
+ BRANCH(len);
+ }
+ PUSH(lval);
+ END_CASE(JSOP_CASEX)
+
+ BEGIN_CASE(JSOP_LT)
+ RELATIONAL_OP(<);
+ END_CASE(JSOP_LT)
+
+ BEGIN_CASE(JSOP_LE)
+ RELATIONAL_OP(<=);
+ END_CASE(JSOP_LE)
+
+ BEGIN_CASE(JSOP_GT)
+ RELATIONAL_OP(>);
+ END_CASE(JSOP_GT)
+
+ BEGIN_CASE(JSOP_GE)
+ RELATIONAL_OP(>=);
+ END_CASE(JSOP_GE)
+
+#undef EQUALITY_OP
+#undef RELATIONAL_OP
+
+#define SIGNED_SHIFT_OP(OP) \
+ JS_BEGIN_MACRO \
+ FETCH_INT(cx, -2, i); \
+ FETCH_INT(cx, -1, j); \
+ i = i OP (j & 31); \
+ regs.sp--; \
+ STORE_INT(cx, -1, i); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_LSH)
+ SIGNED_SHIFT_OP(<<);
+ END_CASE(JSOP_LSH)
+
+ BEGIN_CASE(JSOP_RSH)
+ SIGNED_SHIFT_OP(>>);
+ END_CASE(JSOP_RSH)
+
+ BEGIN_CASE(JSOP_URSH)
+ {
+ uint32 u;
+
+ FETCH_UINT(cx, -2, u);
+ FETCH_INT(cx, -1, j);
+ u >>= (j & 31);
+ regs.sp--;
+ STORE_UINT(cx, -1, u);
+ }
+ END_CASE(JSOP_URSH)
+
+#undef BITWISE_OP
+#undef SIGNED_SHIFT_OP
+
+ BEGIN_CASE(JSOP_ADD)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+#if JS_HAS_XML_SUPPORT
+ if (!JSVAL_IS_PRIMITIVE(lval) &&
+ (obj2 = JSVAL_TO_OBJECT(lval), OBJECT_IS_XML(cx, obj2)) &&
+ VALUE_IS_XML(cx, rval)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj2->map->ops;
+ if (!ops->concatenate(cx, obj2, rval, &rval))
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ } else
+#endif
+ {
+ if (!JSVAL_IS_PRIMITIVE(lval))
+ DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);
+ if (!JSVAL_IS_PRIMITIVE(rval))
+ DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);
+ if ((cond = JSVAL_IS_STRING(lval)) || JSVAL_IS_STRING(rval)) {
+ if (cond) {
+ str = JSVAL_TO_STRING(lval);
+ str2 = js_ValueToString(cx, rval);
+ if (!str2)
+ goto error;
+ regs.sp[-1] = STRING_TO_JSVAL(str2);
+ } else {
+ str2 = JSVAL_TO_STRING(rval);
+ str = js_ValueToString(cx, lval);
+ if (!str)
+ goto error;
+ regs.sp[-2] = STRING_TO_JSVAL(str);
+ }
+ str = js_ConcatStrings(cx, str, str2);
+ if (!str)
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ } else {
+ VALUE_TO_NUMBER(cx, -2, lval, d);
+ VALUE_TO_NUMBER(cx, -1, rval, d2);
+ d += d2;
+ regs.sp--;
+ STORE_NUMBER(cx, -1, d);
+ }
+ }
+ END_CASE(JSOP_ADD)
+
+#define BINARY_OP(OP) \
+ JS_BEGIN_MACRO \
+ FETCH_NUMBER(cx, -2, d); \
+ FETCH_NUMBER(cx, -1, d2); \
+ d = d OP d2; \
+ regs.sp--; \
+ STORE_NUMBER(cx, -1, d); \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_SUB)
+ BINARY_OP(-);
+ END_CASE(JSOP_SUB)
+
+ BEGIN_CASE(JSOP_MUL)
+ BINARY_OP(*);
+ END_CASE(JSOP_MUL)
+
+ BEGIN_CASE(JSOP_DIV)
+ FETCH_NUMBER(cx, -1, d2);
+ FETCH_NUMBER(cx, -2, d);
+ regs.sp--;
+ if (d2 == 0) {
+#ifdef XP_WIN
+ /* XXX MSVC miscompiles such that (NaN == 0) */
+ if (JSDOUBLE_IS_NaN(d2))
+ rval = DOUBLE_TO_JSVAL(rt->jsNaN);
+ else
+#endif
+ if (d == 0 || JSDOUBLE_IS_NaN(d))
+ rval = DOUBLE_TO_JSVAL(rt->jsNaN);
+ else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
+ rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);
+ else
+ rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);
+ STORE_OPND(-1, rval);
+ } else {
+ d /= d2;
+ STORE_NUMBER(cx, -1, d);
+ }
+ END_CASE(JSOP_DIV)
+
+ BEGIN_CASE(JSOP_MOD)
+ FETCH_NUMBER(cx, -1, d2);
+ FETCH_NUMBER(cx, -2, d);
+ regs.sp--;
+ if (d2 == 0) {
+ STORE_OPND(-1, DOUBLE_TO_JSVAL(rt->jsNaN));
+ } else {
+#ifdef XP_WIN
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
+ if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
+#endif
+ d = fmod(d, d2);
+ STORE_NUMBER(cx, -1, d);
+ }
+ END_CASE(JSOP_MOD)
+
+ BEGIN_CASE(JSOP_NOT)
+ POP_BOOLEAN(cx, rval, cond);
+ PUSH_OPND(BOOLEAN_TO_JSVAL(!cond));
+ END_CASE(JSOP_NOT)
+
+ BEGIN_CASE(JSOP_BITNOT)
+ FETCH_INT(cx, -1, i);
+ i = ~i;
+ STORE_INT(cx, -1, i);
+ END_CASE(JSOP_BITNOT)
+
+ BEGIN_CASE(JSOP_NEG)
+ /*
+ * When the operand is int jsval, INT_FITS_IN_JSVAL(i) implies
+ * INT_FITS_IN_JSVAL(-i) unless i is 0 or JSVAL_INT_MIN when the
+ * results, -0.0 or JSVAL_INT_MAX + 1, are jsdouble values.
+ */
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_INT(rval) &&
+ rval != INT_TO_JSVAL(JSVAL_INT_MIN) &&
+ (i = JSVAL_TO_INT(rval)) != 0) {
+ JS_STATIC_ASSERT(!INT_FITS_IN_JSVAL(-JSVAL_INT_MIN));
+ i = -i;
+ JS_ASSERT(INT_FITS_IN_JSVAL(i));
+ regs.sp[-1] = INT_TO_JSVAL(i);
+ } else {
+ if (JSVAL_IS_DOUBLE(rval)) {
+ d = *JSVAL_TO_DOUBLE(rval);
+ } else {
+ d = js_ValueToNumber(cx, &regs.sp[-1]);
+ if (JSVAL_IS_NULL(regs.sp[-1]))
+ goto error;
+ JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[-1]) ||
+ regs.sp[-1] == JSVAL_TRUE);
+ }
+#ifdef HPUX
+ /*
+ * Negation of a zero doesn't produce a negative
+ * zero on HPUX. Perform the operation by bit
+ * twiddling.
+ */
+ JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
+#else
+ d = -d;
+#endif
+ if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
+ goto error;
+ }
+ END_CASE(JSOP_NEG)
+
+ BEGIN_CASE(JSOP_POS)
+ rval = FETCH_OPND(-1);
+ if (!JSVAL_IS_NUMBER(rval)) {
+ d = js_ValueToNumber(cx, &regs.sp[-1]);
+ rval = regs.sp[-1];
+ if (JSVAL_IS_NULL(rval))
+ goto error;
+ if (rval == JSVAL_TRUE) {
+ if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))
+ goto error;
+ } else {
+ JS_ASSERT(JSVAL_IS_NUMBER(rval));
+ }
+ }
+ END_CASE(JSOP_POS)
+
+ BEGIN_CASE(JSOP_DELNAME)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (!js_FindProperty(cx, id, &obj, &obj2, &prop))
+ goto error;
+
+ /* ECMA says to return true if name is undefined or inherited. */
+ PUSH_OPND(JSVAL_TRUE);
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_DELETE_PROPERTY(cx, obj, id, &regs.sp[-1]))
+ goto error;
+ }
+ END_CASE(JSOP_DELNAME)
+
+ BEGIN_CASE(JSOP_DELPROP)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ PROPERTY_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_DELPROP)
+
+ BEGIN_CASE(JSOP_DELELEM)
+ ELEMENT_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_DELELEM)
+
+ BEGIN_CASE(JSOP_TYPEOFEXPR)
+ BEGIN_CASE(JSOP_TYPEOF)
+ rval = FETCH_OPND(-1);
+ type = JS_TypeOfValue(cx, rval);
+ atom = rt->atomState.typeAtoms[type];
+ STORE_OPND(-1, ATOM_KEY(atom));
+ END_CASE(JSOP_TYPEOF)
+
+ BEGIN_CASE(JSOP_VOID)
+ STORE_OPND(-1, JSVAL_VOID);
+ END_CASE(JSOP_VOID)
+
+ BEGIN_CASE(JSOP_INCELEM)
+ BEGIN_CASE(JSOP_DECELEM)
+ BEGIN_CASE(JSOP_ELEMINC)
+ BEGIN_CASE(JSOP_ELEMDEC)
+ /*
+ * Delay fetching of id until we have the object to ensure
+ * the proper evaluation order. See bug 372331.
+ */
+ id = 0;
+ i = -2;
+ goto fetch_incop_obj;
+
+ BEGIN_CASE(JSOP_INCPROP)
+ BEGIN_CASE(JSOP_DECPROP)
+ BEGIN_CASE(JSOP_PROPINC)
+ BEGIN_CASE(JSOP_PROPDEC)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ i = -1;
+
+ fetch_incop_obj:
+ FETCH_OBJECT(cx, i, lval, obj);
+ if (id == 0)
+ FETCH_ELEMENT_ID(obj, -1, id);
+ goto do_incop;
+
+ BEGIN_CASE(JSOP_INCNAME)
+ BEGIN_CASE(JSOP_DECNAME)
+ BEGIN_CASE(JSOP_NAMEINC)
+ BEGIN_CASE(JSOP_NAMEDEC)
+ {
+ JSPropCacheEntry *entry;
+
+ obj = fp->scopeChain;
+ if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ if (obj == obj2 && PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj, slot);
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
+ rtmp = rval;
+ rval += (js_CodeSpec[op].format & JOF_INC) ? 2 : -2;
+ if (!(js_CodeSpec[op].format & JOF_POST))
+ rtmp = rval;
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval);
+ JS_UNLOCK_OBJ(cx, obj);
+ PUSH_OPND(rtmp);
+ len = JSOP_INCNAME_LENGTH;
+ DO_NEXT_OP(len);
+ }
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ LOAD_ATOM(0);
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+ id = ATOM_TO_JSID(atom);
+ if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
+ goto error;
+ if (!prop)
+ goto atom_not_defined;
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+
+ do_incop:
+ {
+ const JSCodeSpec *cs;
+ jsval v;
+
+ /*
+ * We need a root to store the value to leave on the stack until
+ * we have done with OBJ_SET_PROPERTY.
+ */
+ PUSH_OPND(JSVAL_NULL);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &regs.sp[-1]))
+ goto error;
+
+ cs = &js_CodeSpec[op];
+ JS_ASSERT(cs->ndefs == 1);
+ JS_ASSERT((cs->format & JOF_TMPSLOT_MASK) == JOF_TMPSLOT2);
+ v = regs.sp[-1];
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(v))) {
+ jsval incr;
+
+ incr = (cs->format & JOF_INC) ? 2 : -2;
+ if (cs->format & JOF_POST) {
+ regs.sp[-1] = v + incr;
+ } else {
+ v += incr;
+ regs.sp[-1] = v;
+ }
+ fp->flags |= JSFRAME_ASSIGNING;
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+ fp->flags &= ~JSFRAME_ASSIGNING;
+ if (!ok)
+ goto error;
+
+ /*
+ * We must set regs.sp[-1] to v for both post and pre increments
+ * as the setter overwrites regs.sp[-1].
+ */
+ regs.sp[-1] = v;
+ } else {
+ /* We need an extra root for the result. */
+ PUSH_OPND(JSVAL_NULL);
+ if (!js_DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1]))
+ goto error;
+ fp->flags |= JSFRAME_ASSIGNING;
+ ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);
+ fp->flags &= ~JSFRAME_ASSIGNING;
+ if (!ok)
+ goto error;
+ regs.sp--;
+ }
+
+ if (cs->nuses == 0) {
+ /* regs.sp[-1] already contains the result of name increment. */
+ } else {
+ rtmp = regs.sp[-1];
+ regs.sp -= cs->nuses;
+ regs.sp[-1] = rtmp;
+ }
+ len = cs->length;
+ DO_NEXT_OP(len);
+ }
+
+ {
+ jsval incr, incr2;
+
+ /* Position cases so the most frequent i++ does not need a jump. */
+ BEGIN_CASE(JSOP_DECARG)
+ incr = -2; incr2 = -2; goto do_arg_incop;
+ BEGIN_CASE(JSOP_ARGDEC)
+ incr = -2; incr2 = 0; goto do_arg_incop;
+ BEGIN_CASE(JSOP_INCARG)
+ incr = 2; incr2 = 2; goto do_arg_incop;
+ BEGIN_CASE(JSOP_ARGINC)
+ incr = 2; incr2 = 0;
+
+ do_arg_incop:
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ METER_SLOT_OP(op, slot);
+ vp = fp->argv + slot;
+ goto do_int_fast_incop;
+
+ BEGIN_CASE(JSOP_DECLOCAL)
+ incr = -2; incr2 = -2; goto do_local_incop;
+ BEGIN_CASE(JSOP_LOCALDEC)
+ incr = -2; incr2 = 0; goto do_local_incop;
+ BEGIN_CASE(JSOP_INCLOCAL)
+ incr = 2; incr2 = 2; goto do_local_incop;
+ BEGIN_CASE(JSOP_LOCALINC)
+ incr = 2; incr2 = 0;
+
+ /*
+ * do_local_incop comes right before do_int_fast_incop as we want to
+ * avoid an extra jump for variable cases as local++ is more frequent
+ * than arg++.
+ */
+ do_local_incop:
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < fp->script->nslots);
+ vp = fp->slots + slot;
+ METER_SLOT_OP(op, slot);
+ vp = fp->slots + slot;
+
+ do_int_fast_incop:
+ rval = *vp;
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
+ *vp = rval + incr;
+ JS_ASSERT(JSOP_INCARG_LENGTH == js_CodeSpec[op].length);
+ SKIP_POP_AFTER_SET(JSOP_INCARG_LENGTH, 0);
+ PUSH_OPND(rval + incr2);
+ } else {
+ PUSH_OPND(rval);
+ if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-1], vp))
+ goto error;
+ }
+ len = JSOP_INCARG_LENGTH;
+ JS_ASSERT(len == js_CodeSpec[op].length);
+ DO_NEXT_OP(len);
+ }
+
+/* NB: This macro doesn't use JS_BEGIN_MACRO/JS_END_MACRO around its body. */
+#define FAST_GLOBAL_INCREMENT_OP(SLOWOP,INCR,INCR2) \
+ op2 = SLOWOP; \
+ incr = INCR; \
+ incr2 = INCR2; \
+ goto do_global_incop
+
+ {
+ jsval incr, incr2;
+
+ BEGIN_CASE(JSOP_DECGVAR)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_DECNAME, -2, -2);
+ BEGIN_CASE(JSOP_GVARDEC)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEDEC, -2, 0);
+ BEGIN_CASE(JSOP_INCGVAR)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_INCNAME, 2, 2);
+ BEGIN_CASE(JSOP_GVARINC)
+ FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEINC, 2, 0);
+
+#undef FAST_GLOBAL_INCREMENT_OP
+
+ do_global_incop:
+ JS_ASSERT((js_CodeSpec[op].format & JOF_TMPSLOT_MASK) ==
+ JOF_TMPSLOT2);
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < GlobalVarCount(fp));
+ METER_SLOT_OP(op, slot);
+ lval = fp->slots[slot];
+ if (JSVAL_IS_NULL(lval)) {
+ op = op2;
+ DO_OP();
+ }
+ slot = JSVAL_TO_INT(lval);
+ rval = OBJ_GET_SLOT(cx, fp->varobj, slot);
+ if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {
+ PUSH_OPND(rval + incr2);
+ rval += incr;
+ } else {
+ PUSH_OPND(rval);
+ PUSH_OPND(JSVAL_NULL); /* Extra root */
+ if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-2], &regs.sp[-1]))
+ goto error;
+ rval = regs.sp[-1];
+ --regs.sp;
+ }
+ OBJ_SET_SLOT(cx, fp->varobj, slot, rval);
+ len = JSOP_INCGVAR_LENGTH; /* all gvar incops are same length */
+ JS_ASSERT(len == js_CodeSpec[op].length);
+ DO_NEXT_OP(len);
+ }
+
+#define COMPUTE_THIS(cx, fp, obj) \
+ JS_BEGIN_MACRO \
+ if (fp->flags & JSFRAME_COMPUTED_THIS) { \
+ obj = fp->thisp; \
+ } else { \
+ obj = js_ComputeThis(cx, JS_TRUE, fp->argv); \
+ if (!obj) \
+ goto error; \
+ fp->thisp = obj; \
+ fp->flags |= JSFRAME_COMPUTED_THIS; \
+ } \
+ JS_END_MACRO
+
+ BEGIN_CASE(JSOP_THIS)
+ COMPUTE_THIS(cx, fp, obj);
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_THIS)
+
+ BEGIN_CASE(JSOP_GETTHISPROP)
+ i = 0;
+ COMPUTE_THIS(cx, fp, obj);
+ PUSH(JSVAL_NULL);
+ goto do_getprop_with_obj;
+
+#undef COMPUTE_THIS
+
+ BEGIN_CASE(JSOP_GETARGPROP)
+ i = ARGNO_LEN;
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ PUSH_OPND(fp->argv[slot]);
+ goto do_getprop_body;
+
+ BEGIN_CASE(JSOP_GETLOCALPROP)
+ i = SLOTNO_LEN;
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ PUSH_OPND(fp->slots[slot]);
+ goto do_getprop_body;
+
+ BEGIN_CASE(JSOP_GETPROP)
+ BEGIN_CASE(JSOP_GETXPROP)
+ i = 0;
+
+ do_getprop_body:
+ lval = FETCH_OPND(-1);
+
+ do_getprop_with_lval:
+ VALUE_TO_OBJECT(cx, -1, lval, obj);
+
+ do_getprop_with_obj:
+ do {
+ JSObject *aobj;
+ JSPropCacheEntry *entry;
+
+ aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
+ if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(i, aobj, obj2, entry);
+ if (PCVAL_IS_OBJECT(entry->vword)) {
+ rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
+ } else if (PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj2->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
+ } else {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ NATIVE_GET(cx, obj, obj2, sprop, &rval);
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ break;
+ }
+ } else {
+ entry = NULL;
+ if (i < 0)
+ atom = rt->atomState.lengthAtom;
+ else
+ LOAD_ATOM(i);
+ }
+ id = ATOM_TO_JSID(atom);
+ if (entry
+ ? !js_GetPropertyHelper(cx, aobj, id, &rval, &entry)
+ : !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
+ goto error;
+ }
+ } while (0);
+
+ STORE_OPND(-1, rval);
+ JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length);
+ len = JSOP_GETPROP_LENGTH + i;
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_LENGTH)
+ lval = FETCH_OPND(-1);
+ if (JSVAL_IS_STRING(lval)) {
+ str = JSVAL_TO_STRING(lval);
+ regs.sp[-1] = INT_TO_JSVAL(JSSTRING_LENGTH(str));
+ } else if (!JSVAL_IS_PRIMITIVE(lval) &&
+ (obj = JSVAL_TO_OBJECT(lval), OBJ_IS_ARRAY(cx, obj))) {
+ jsuint length;
+
+ /*
+ * We know that the array is created with only its 'length'
+ * private data in a fixed slot at JSSLOT_ARRAY_LENGTH. See
+ * also JSOP_ARRAYPUSH, far below.
+ */
+ length = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (length <= JSVAL_INT_MAX) {
+ regs.sp[-1] = INT_TO_JSVAL(length);
+ } else if (!js_NewDoubleInRootedValue(cx, (jsdouble) length,
+ &regs.sp[-1])) {
+ goto error;
+ }
+ } else {
+ i = -2;
+ goto do_getprop_with_lval;
+ }
+ END_CASE(JSOP_LENGTH)
+
+ BEGIN_CASE(JSOP_CALLPROP)
+ {
+ JSObject *aobj;
+ JSPropCacheEntry *entry;
+
+ lval = FETCH_OPND(-1);
+ if (!JSVAL_IS_PRIMITIVE(lval)) {
+ obj = JSVAL_TO_OBJECT(lval);
+ } else {
+ if (JSVAL_IS_STRING(lval)) {
+ i = JSProto_String;
+ } else if (JSVAL_IS_NUMBER(lval)) {
+ i = JSProto_Number;
+ } else if (JSVAL_IS_BOOLEAN(lval)) {
+ i = JSProto_Boolean;
+ } else {
+ JS_ASSERT(JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval));
+ js_ReportIsNullOrUndefined(cx, -1, lval, NULL);
+ goto error;
+ }
+
+ if (!js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj))
+ goto error;
+ }
+
+ aobj = OBJ_IS_DENSE_ARRAY(cx, obj) ? OBJ_GET_PROTO(cx, obj) : obj;
+ if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry);
+ if (PCVAL_IS_OBJECT(entry->vword)) {
+ rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
+ } else if (PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj2->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
+ } else {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ NATIVE_GET(cx, obj, obj2, sprop, &rval);
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ STORE_OPND(-1, rval);
+ PUSH_OPND(lval);
+ goto end_callprop;
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+
+ /*
+ * Cache miss: use the immediate atom that was loaded for us under
+ * PROPERTY_CACHE_TEST.
+ */
+ id = ATOM_TO_JSID(atom);
+ PUSH(JSVAL_NULL);
+ if (!JSVAL_IS_PRIMITIVE(lval)) {
+#if JS_HAS_XML_SUPPORT
+ /* Special-case XML object method lookup, per ECMA-357. */
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, &rval);
+ if (!obj)
+ goto error;
+ } else
+#endif
+ if (entry
+ ? !js_GetPropertyHelper(cx, aobj, id, &rval, &entry)
+ : !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {
+ goto error;
+ }
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ STORE_OPND(-2, rval);
+ } else {
+ JS_ASSERT(obj->map->ops->getProperty == js_GetProperty);
+ if (!js_GetPropertyHelper(cx, obj, id, &rval, &entry))
+ goto error;
+ STORE_OPND(-1, lval);
+ STORE_OPND(-2, rval);
+ }
+
+ end_callprop:
+ /* Wrap primitive lval in object clothing if necessary. */
+ if (JSVAL_IS_PRIMITIVE(lval)) {
+ /* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
+ if (!VALUE_IS_FUNCTION(cx, rval) ||
+ (obj = JSVAL_TO_OBJECT(rval),
+ fun = GET_FUNCTION_PRIVATE(cx, obj),
+ !PRIMITIVE_THIS_TEST(fun, lval))) {
+ if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
+ goto error;
+ }
+ }
+#if JS_HAS_NO_SUCH_METHOD
+ if (JS_UNLIKELY(JSVAL_IS_VOID(rval))) {
+ LOAD_ATOM(0);
+ regs.sp[-2] = ATOM_KEY(atom);
+ if (!js_OnUnknownMethod(cx, regs.sp - 2))
+ goto error;
+ }
+#endif
+ }
+ END_CASE(JSOP_CALLPROP)
+
+ BEGIN_CASE(JSOP_SETNAME)
+ BEGIN_CASE(JSOP_SETPROP)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval) || op == JSOP_SETPROP);
+ VALUE_TO_OBJECT(cx, -2, lval, obj);
+
+ do {
+ JSPropCacheEntry *entry;
+
+ entry = NULL;
+ atom = NULL;
+ if (JS_LIKELY(obj->map->ops->setProperty == js_SetProperty)) {
+ JSPropertyCache *cache = &JS_PROPERTY_CACHE(cx);
+ uint32 kshape = OBJ_SHAPE(obj);
+
+ /*
+ * Open-code JS_PROPERTY_CACHE_TEST, specializing for two
+ * important set-property cases. First:
+ *
+ * function f(a, b, c) {
+ * var o = {p:a, q:b, r:c};
+ * return o;
+ * }
+ *
+ * or similar real-world cases, which evolve a newborn
+ * native object predicatably through some bounded number
+ * of property additions. And second:
+ *
+ * o.p = x;
+ *
+ * in a frequently executed method or loop body, where p
+ * will (possibly after the first iteration) always exist
+ * in native object o.
+ */
+ entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];
+ PCMETER(cache->tests++);
+ PCMETER(cache->settests++);
+ if (entry->kpc == regs.pc && entry->kshape == kshape) {
+ JSScope *scope;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (scope->shape == kshape) {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
+ JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj)));
+
+ if (scope->object == obj) {
+ /*
+ * Fastest path: the cached sprop is already
+ * in scope. Just NATIVE_SET and break to get
+ * out of the do-while(0).
+ */
+ if (sprop == scope->lastProp ||
+ SCOPE_HAS_PROPERTY(scope, sprop)) {
+ PCMETER(cache->pchits++);
+ PCMETER(cache->setpchits++);
+ NATIVE_SET(cx, obj, sprop, &rval);
+ JS_UNLOCK_SCOPE(cx, scope);
+ TRACE_2(SetPropHit, entry, sprop);
+ break;
+ }
+ } else {
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ goto error;
+ }
+ }
+
+ if (sprop->parent == scope->lastProp &&
+ !SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ SPROP_HAS_STUB_SETTER(sprop) &&
+ (slot = sprop->slot) == scope->map.freeslot) {
+ /*
+ * Fast path: adding a plain old property that
+ * was once at the frontier of the property
+ * tree, whose slot is next to claim among the
+ * allocated slots in obj, where scope->table
+ * has not been created yet.
+ *
+ * We may want to remove hazard conditions
+ * above and inline compensation code here,
+ * depending on real-world workloads.
+ */
+ JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
+ JSCLASS_SHARE_ALL_PROPERTIES));
+
+ PCMETER(cache->pchits++);
+ PCMETER(cache->addpchits++);
+
+ /*
+ * Beware classes such as Function that use
+ * the reserveSlots hook to allocate a number
+ * of reserved slots that may vary with obj.
+ */
+ if (slot < STOBJ_NSLOTS(obj) &&
+ !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
+ ++scope->map.freeslot;
+ } else {
+ if (!js_AllocSlot(cx, obj, &slot)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ }
+
+ /*
+ * If this obj's number of reserved slots
+ * differed, or if something created a hash
+ * table for scope, we must pay the price of
+ * js_AddScopeProperty.
+ *
+ * If slot does not match the cached sprop's
+ * slot, update the cache entry in the hope
+ * that obj and other instances with the same
+ * number of reserved slots are now "hot".
+ */
+ if (slot != sprop->slot || scope->table) {
+ JSScopeProperty *sprop2 =
+ js_AddScopeProperty(cx, scope,
+ sprop->id,
+ sprop->getter,
+ sprop->setter,
+ slot,
+ sprop->attrs,
+ sprop->flags,
+ sprop->shortid);
+ if (!sprop2) {
+ js_FreeSlot(cx, obj, slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ if (sprop2 != sprop) {
+ PCMETER(cache->slotchanges++);
+ JS_ASSERT(slot != sprop->slot &&
+ slot == sprop2->slot &&
+ sprop2->id == sprop->id);
+ entry->vword = SPROP_TO_PCVAL(sprop2);
+ }
+ sprop = sprop2;
+ } else {
+ SCOPE_EXTEND_SHAPE(cx, scope, sprop);
+ ++scope->entryCount;
+ scope->lastProp = sprop;
+ }
+
+ GC_WRITE_BARRIER(cx, scope,
+ LOCKED_OBJ_GET_SLOT(obj, slot),
+ rval);
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval);
+ JS_UNLOCK_SCOPE(cx, scope);
+ TRACE_2(SetPropHit, entry, sprop);
+ break;
+ }
+
+ PCMETER(cache->setpcmisses++);
+ atom = NULL;
+ }
+
+ JS_UNLOCK_OBJ(cx, obj);
+ }
+
+ atom = js_FullTestPropertyCache(cx, regs.pc, &obj, &obj2,
+ &entry);
+ if (atom) {
+ PCMETER(cache->misses++);
+ PCMETER(cache->setmisses++);
+ } else {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ sprop = NULL;
+ if (obj == obj2) {
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
+ JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj2)));
+ NATIVE_SET(cx, obj, sprop, &rval);
+ }
+ JS_UNLOCK_OBJ(cx, obj2);
+ if (sprop) {
+ TRACE_2(SetPropHit, entry, sprop);
+ break;
+ }
+ }
+ }
+
+ if (!atom)
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (entry) {
+ if (!js_SetPropertyHelper(cx, obj, id, &rval, &entry))
+ goto error;
+#ifdef JS_TRACER
+ if (entry)
+ TRACE_1(SetPropMiss, entry);
+#endif
+ } else {
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ }
+#ifdef JS_TRACER
+ if (!entry && TRACE_RECORDER(cx)) {
+ js_AbortRecording(cx, "SetPropUncached");
+ ENABLE_TRACER(0);
+ }
+#endif
+ } while (0);
+ END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2);
+
+ BEGIN_CASE(JSOP_GETELEM)
+ /* Open-coded ELEMENT_OP optimized for strings and dense arrays. */
+ lval = FETCH_OPND(-2);
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(rval)) {
+ str = JSVAL_TO_STRING(lval);
+ i = JSVAL_TO_INT(rval);
+ if ((size_t)i < JSSTRING_LENGTH(str)) {
+ str = js_GetUnitString(cx, str, (size_t)i);
+ if (!str)
+ goto error;
+ rval = STRING_TO_JSVAL(str);
+ goto end_getelem;
+ }
+ }
+
+ VALUE_TO_OBJECT(cx, -2, lval, obj);
+ if (JSVAL_IS_INT(rval)) {
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ jsuint length;
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ i = JSVAL_TO_INT(rval);
+ if ((jsuint)i < length &&
+ i < obj->fslots[JSSLOT_ARRAY_LENGTH]) {
+ rval = obj->dslots[i];
+ if (rval != JSVAL_HOLE)
+ goto end_getelem;
+
+ /* Reload rval from the stack in the rare hole case. */
+ rval = FETCH_OPND(-1);
+ }
+ }
+ id = INT_JSVAL_TO_JSID(rval);
+ } else {
+ if (!js_InternNonIntElementId(cx, obj, rval, &id))
+ goto error;
+ }
+
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ end_getelem:
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_GETELEM)
+
+ BEGIN_CASE(JSOP_CALLELEM)
+ /*
+ * FIXME: JSOP_CALLELEM should call getMethod on XML objects as
+ * CALLPROP does. See bug 362910.
+ */
+ ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));
+#if JS_HAS_NO_SUCH_METHOD
+ if (JS_UNLIKELY(JSVAL_IS_VOID(rval))) {
+ regs.sp[-2] = regs.sp[-1];
+ regs.sp[-1] = OBJECT_TO_JSVAL(obj);
+ if (!js_OnUnknownMethod(cx, regs.sp - 2))
+ goto error;
+ } else
+#endif
+ {
+ STORE_OPND(-2, rval);
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ }
+ END_CASE(JSOP_CALLELEM)
+
+ BEGIN_CASE(JSOP_SETELEM)
+ rval = FETCH_OPND(-1);
+ FETCH_OBJECT(cx, -3, lval, obj);
+ FETCH_ELEMENT_ID(obj, -2, id);
+ do {
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) {
+ jsuint length;
+
+ length = ARRAY_DENSE_LENGTH(obj);
+ i = JSID_TO_INT(id);
+ if ((jsuint)i < length) {
+ if (obj->dslots[i] == JSVAL_HOLE) {
+ if (rt->anyArrayProtoHasElement)
+ break;
+ if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])
+ obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;
+ obj->fslots[JSSLOT_ARRAY_COUNT]++;
+ }
+ obj->dslots[i] = rval;
+ goto end_setelem;
+ }
+ }
+ } while (0);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ end_setelem:
+ END_SET_CASE_STORE_RVAL(JSOP_SETELEM, 3)
+
+ BEGIN_CASE(JSOP_ENUMELEM)
+ /* Funky: the value to set is under the [obj, id] pair. */
+ rval = FETCH_OPND(-3);
+ FETCH_OBJECT(cx, -2, lval, obj);
+ FETCH_ELEMENT_ID(obj, -1, id);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ regs.sp -= 3;
+ END_CASE(JSOP_ENUMELEM)
+
+ BEGIN_CASE(JSOP_NEW)
+ /* Get immediate argc and find the constructor function. */
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - (2 + argc);
+ JS_ASSERT(vp >= StackBase(fp));
+
+ /*
+ * Assign lval, obj, and fun exactly as the code at inline_call:
+ * expects to find them, to avoid nesting a js_Interpret call via
+ * js_InvokeConstructor.
+ */
+ lval = *vp;
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ obj = JSVAL_TO_OBJECT(lval);
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+ if (FUN_INTERPRETED(fun)) {
+ /* Root as we go using vp[1]. */
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &vp[1])) {
+ goto error;
+ }
+ rval = vp[1];
+ obj2 = js_NewObject(cx, &js_ObjectClass,
+ JSVAL_IS_OBJECT(rval)
+ ? JSVAL_TO_OBJECT(rval)
+ : NULL,
+ OBJ_GET_PARENT(cx, obj),
+ 0);
+ if (!obj2)
+ goto error;
+ vp[1] = OBJECT_TO_JSVAL(obj2);
+ flags = JSFRAME_CONSTRUCTING;
+ goto inline_call;
+ }
+ }
+
+ if (!js_InvokeConstructor(cx, argc, JS_FALSE, vp))
+ goto error;
+ regs.sp = vp + 1;
+ LOAD_INTERRUPT_HANDLER(cx);
+ END_CASE(JSOP_NEW)
+
+ BEGIN_CASE(JSOP_APPLY)
+ {
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - (argc + 2);
+ lval = *vp;
+ if (!VALUE_IS_FUNCTION(cx, lval))
+ goto do_call;
+ obj = JSVAL_TO_OBJECT(lval);
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+ if (FUN_INTERPRETED(fun))
+ goto do_call;
+
+ bool apply = (JSFastNative)fun->u.n.native == js_fun_apply;
+ if (!apply && (JSFastNative)fun->u.n.native != js_fun_call)
+ goto do_call;
+
+ /*
+ * If the second arg to apply is null or void, treat it as an empty
+ * array.
+ */
+ jsuint applylen = 0;
+ if (apply && argc >= 2 &&
+ !JSVAL_IS_VOID(vp[3]) && !JSVAL_IS_NULL(vp[3])) {
+ /*
+ * Fall back on js_Invoke when the array argument has a wrong
+ * type or when it has too many elements to fit into the
+ * current stack chunk.
+ */
+ if (!JSVAL_IS_OBJECT(vp[3]))
+ goto do_call;
+
+ JSBool arraylike;
+ JSObject* aobj = JSVAL_TO_OBJECT(vp[3]);
+ if (!js_IsArrayLike(cx, aobj, &arraylike, &applylen))
+ goto error;
+ if (!arraylike || applylen > ARGC_LIMIT)
+ goto do_call;
+
+ JSArena *a = cx->stackPool.current;
+ JS_ASSERT(jsuword(vp + 2) <= a->limit);
+
+ /*
+ * We need space for applylen elements plus an extra slot to
+ * temporary root the array object when we unpack its elements
+ * using OBJ_GET_PROPERTY below.
+ */
+ if (a->limit - jsuword(vp + 2) < (applylen + 1) * sizeof(jsval))
+ goto do_call;
+ }
+
+ if (!VALUE_IS_FUNCTION(cx, vp[1]))
+ goto do_call;
+ vp[0] = vp[1];
+
+ if (argc == 0) {
+ /*
+ * Call fun with its global object as the 'this' param if
+ * no args.
+ */
+ obj = NULL;
+ } else {
+ /* Convert the first arg to 'this'. */
+ if (!JSVAL_IS_PRIMITIVE(vp[2]))
+ obj = JSVAL_TO_OBJECT(vp[2]);
+ else if (!js_ValueToObject(cx, vp[2], &obj))
+ goto error;
+ }
+ vp[1] = OBJECT_TO_JSVAL(obj);
+
+ if (!apply) {
+ if (argc != 0) {
+ --argc;
+ memmove(vp + 2, vp + 3, argc * sizeof *vp);
+ }
+ } else if (applylen == 0) {
+ argc = 0;
+ } else {
+ /*
+ * Make room for missing arguments to the right including the
+ * temporary root nulling any extra stack slots for GC safety.
+ */
+ jsval* newsp = vp + 2 + applylen + 1;
+ if (newsp > regs.sp) {
+ JSArena *a = cx->stackPool.current;
+ JS_ASSERT(jsuword(newsp) <= a->limit); /* see above */
+ if ((jsuword) newsp > a->avail)
+ a->avail = (jsuword) newsp;
+ memset(vp + 2 + argc, 0, (applylen - argc) * sizeof(jsval));
+ }
+
+ JSObject *aobj = JSVAL_TO_OBJECT(vp[3]);
+ newsp[-1] = vp[3];
+ regs.sp = newsp;
+
+ /* Expand array content onto the stack. */
+ for (i = 0; i < jsint(applylen); i++) {
+ id = INT_TO_JSID(i);
+ if (!OBJ_GET_PROPERTY(cx, aobj, id, &vp[2 + i])) {
+ /*
+ * There is no good way to restore the original stack
+ * state here, but it is in a reasonable state with
+ * either original elements or nulls for all arguments
+ * we didn't unpack yet, so we leave it at that.
+ */
+ goto error;
+ }
+ }
+ argc = applylen;
+ }
+ regs.sp = vp + 2 + argc;
+ goto do_call_with_specified_vp_and_argc;
+ }
+
+ BEGIN_CASE(JSOP_CALL)
+ BEGIN_CASE(JSOP_EVAL)
+ do_call:
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - (argc + 2);
+
+ do_call_with_specified_vp_and_argc:
+ lval = *vp;
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ obj = JSVAL_TO_OBJECT(lval);
+ fun = GET_FUNCTION_PRIVATE(cx, obj);
+
+ /* Clear frame flags since this is not a constructor call. */
+ flags = 0;
+ if (FUN_INTERPRETED(fun))
+ inline_call:
+ {
+ uintN nframeslots, nvars, missing;
+ JSArena *a;
+ jsuword nbytes;
+ void *newmark;
+ jsval *newsp;
+ JSInlineFrame *newifp;
+ JSInterpreterHook hook;
+
+ /* Restrict recursion of lightweight functions. */
+ if (inlineCallCount == MAX_INLINE_CALL_COUNT) {
+ js_ReportOverRecursed(cx);
+ goto error;
+ }
+
+ /* Compute the total number of stack slots needed by fun. */
+ nframeslots = JS_HOWMANY(sizeof(JSInlineFrame),
+ sizeof(jsval));
+ script = fun->u.i.script;
+ atoms = script->atomMap.vector;
+ nbytes = (nframeslots + script->nslots) * sizeof(jsval);
+
+ /* Allocate missing expected args adjacent to actuals. */
+ a = cx->stackPool.current;
+ newmark = (void *) a->avail;
+ if (fun->nargs <= argc) {
+ missing = 0;
+ } else {
+ newsp = vp + 2 + fun->nargs;
+ JS_ASSERT(newsp > regs.sp);
+ if ((jsuword) newsp <= a->limit) {
+ if ((jsuword) newsp > a->avail)
+ a->avail = (jsuword) newsp;
+ jsval *argsp = newsp;
+ do {
+ *--argsp = JSVAL_VOID;
+ } while (argsp != regs.sp);
+ missing = 0;
+ } else {
+ missing = fun->nargs - argc;
+ nbytes += (2 + fun->nargs) * sizeof(jsval);
+ }
+ }
+
+ /* Allocate the inline frame with its slots and operands. */
+ if (a->avail + nbytes <= a->limit) {
+ newsp = (jsval *) a->avail;
+ a->avail += nbytes;
+ JS_ASSERT(missing == 0);
+ } else {
+ JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool,
+ nbytes);
+ if (!newsp) {
+ js_ReportOutOfScriptQuota(cx);
+ goto bad_inline_call;
+ }
+
+ /*
+ * Move args if the missing ones overflow arena a, then
+ * push undefined for the missing args.
+ */
+ if (missing) {
+ memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
+ vp = newsp;
+ newsp = vp + 2 + argc;
+ do {
+ *newsp++ = JSVAL_VOID;
+ } while (--missing != 0);
+ }
+ }
+
+ /* Claim space for the stack frame and initialize it. */
+ newifp = (JSInlineFrame *) newsp;
+ newsp += nframeslots;
+ newifp->frame.callobj = NULL;
+ newifp->frame.argsobj = NULL;
+ newifp->frame.varobj = NULL;
+ newifp->frame.script = script;
+ newifp->frame.callee = obj;
+ newifp->frame.fun = fun;
+ newifp->frame.argc = argc;
+ newifp->frame.argv = vp + 2;
+ newifp->frame.rval = JSVAL_VOID;
+ newifp->frame.down = fp;
+ newifp->frame.annotation = NULL;
+ newifp->frame.scopeChain = parent = OBJ_GET_PARENT(cx, obj);
+ newifp->frame.sharpDepth = 0;
+ newifp->frame.sharpArray = NULL;
+ newifp->frame.flags = flags;
+ newifp->frame.dormantNext = NULL;
+ newifp->frame.xmlNamespace = NULL;
+ newifp->frame.blockChain = NULL;
+ if (script->staticDepth < JS_DISPLAY_SIZE) {
+ JSStackFrame **disp = &cx->display[script->staticDepth];
+ newifp->frame.displaySave = *disp;
+ *disp = &newifp->frame;
+ }
+#ifdef DEBUG
+ newifp->frame.pcDisabledSave =
+ JS_PROPERTY_CACHE(cx).disabled;
+#endif
+ newifp->mark = newmark;
+
+ /* Compute the 'this' parameter now that argv is set. */
+ JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
+ JS_ASSERT(JSVAL_IS_OBJECT(vp[1]));
+ newifp->frame.thisp = (JSObject *)vp[1];
+
+ newifp->frame.regs = NULL;
+ newifp->frame.imacpc = NULL;
+ newifp->frame.slots = newsp;
+
+ /* Push void to initialize local variables. */
+ nvars = fun->u.i.nvars;
+ while (nvars--)
+ *newsp++ = JSVAL_VOID;
+
+ /* Call the debugger hook if present. */
+ hook = cx->debugHooks->callHook;
+ if (hook) {
+ newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
+ cx->debugHooks->callHookData);
+ LOAD_INTERRUPT_HANDLER(cx);
+ } else {
+ newifp->hookData = NULL;
+ }
+
+ /* Scope with a call object parented by callee's parent. */
+ if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&
+ !js_GetCallObject(cx, &newifp->frame, parent)) {
+ goto bad_inline_call;
+ }
+
+ /* Switch version if currentVersion wasn't overridden. */
+ newifp->callerVersion = (JSVersion) cx->version;
+ if (JS_LIKELY(cx->version == currentVersion)) {
+ currentVersion = (JSVersion) script->version;
+ if (currentVersion != cx->version)
+ js_SetVersion(cx, currentVersion);
+ }
+
+ /* Push the frame and set interpreter registers. */
+ newifp->callerRegs = regs;
+ fp->regs = &newifp->callerRegs;
+ regs.sp = newsp;
+ regs.pc = script->code;
+ newifp->frame.regs = &regs;
+ cx->fp = fp = &newifp->frame;
+
+ TRACE_0(EnterFrame);
+
+ inlineCallCount++;
+ JS_RUNTIME_METER(rt, inlineCalls);
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function entry, inlines */
+ if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
+ jsdtrace_function_entry(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
+ jsdtrace_function_info(cx, fp, fp->down, fun);
+ if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
+ jsdtrace_function_args(cx, fp, fun);
+#endif
+
+ /* Load first op and dispatch it (safe since JSOP_STOP). */
+ op = (JSOp) *regs.pc;
+ DO_OP();
+
+ bad_inline_call:
+ JS_ASSERT(fp->regs == &regs);
+ script = fp->script;
+ atoms = script->atomMap.vector;
+ js_FreeRawStack(cx, newmark);
+ goto error;
+ }
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function entry, non-inlines */
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
+ jsdtrace_function_entry(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
+ jsdtrace_function_info(cx, fp, fp, fun);
+ if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
+ jsdtrace_function_args(cx, fp, fun);
+ }
+#endif
+
+ if (fun->flags & JSFUN_FAST_NATIVE) {
+ JS_ASSERT(fun->u.n.extra == 0);
+ JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
+ PRIMITIVE_THIS_TEST(fun, vp[1]));
+ ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
+ jsdtrace_function_rval(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
+ jsdtrace_function_return(cx, fp, fun);
+ }
+#endif
+ regs.sp = vp + 1;
+ if (!ok)
+ goto error;
+ TRACE_0(FastNativeCallComplete);
+ goto end_call;
+ }
+ }
+
+ ok = js_Invoke(cx, argc, vp, 0);
+#ifdef INCLUDE_MOZILLA_DTRACE
+ /* DTrace function return, non-inlines */
+ if (VALUE_IS_FUNCTION(cx, lval)) {
+ if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
+ jsdtrace_function_rval(cx, fp, fun);
+ if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
+ jsdtrace_function_return(cx, fp, fun);
+ }
+#endif
+ regs.sp = vp + 1;
+ LOAD_INTERRUPT_HANDLER(cx);
+ if (!ok)
+ goto error;
+ JS_RUNTIME_METER(rt, nonInlineCalls);
+
+ end_call:
+#if JS_HAS_LVALUE_RETURN
+ if (cx->rval2set) {
+ /*
+ * Use the stack depth we didn't claim in our budget, but that
+ * we know is there on account of [fun, this] already having
+ * been pushed, at a minimum (if no args). Those two slots
+ * have been popped and [rval] has been pushed, which leaves
+ * one more slot for rval2 before we might overflow.
+ *
+ * NB: rval2 must be the property identifier, and rval the
+ * object from which to get the property. The pair form an
+ * ECMA "reference type", which can be used on the right- or
+ * left-hand side of assignment ops. Note well: only native
+ * methods can return reference types. See JSOP_SETCALL just
+ * below for the left-hand-side case.
+ */
+ PUSH_OPND(cx->rval2);
+ ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));
+
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ cx->rval2set = JS_FALSE;
+ }
+#endif /* JS_HAS_LVALUE_RETURN */
+ END_CASE(JSOP_CALL)
+
+#if JS_HAS_LVALUE_RETURN
+ BEGIN_CASE(JSOP_SETCALL)
+ argc = GET_ARGC(regs.pc);
+ vp = regs.sp - argc - 2;
+ ok = js_Invoke(cx, argc, vp, 0);
+ regs.sp = vp + 1;
+ LOAD_INTERRUPT_HANDLER(cx);
+ if (!ok)
+ goto error;
+ if (!cx->rval2set) {
+ op2 = (JSOp) regs.pc[JSOP_SETCALL_LENGTH];
+ if (op2 != JSOP_DELELEM) {
+ JS_ASSERT(!(js_CodeSpec[op2].format & JOF_DEL));
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_LEFTSIDE_OF_ASS);
+ goto error;
+ }
+
+ /*
+ * Store true as the result of the emulated delete of a
+ * non-existent property. NB: We don't METER_OP_PAIR here;
+ * it doesn't seem worth the code for this obscure case.
+ */
+ *vp = JSVAL_TRUE;
+ regs.pc += JSOP_SETCALL_LENGTH + JSOP_DELELEM_LENGTH;
+ op = (JSOp) *regs.pc;
+ DO_OP();
+ }
+ PUSH_OPND(cx->rval2);
+ cx->rval2set = JS_FALSE;
+ END_CASE(JSOP_SETCALL)
+#endif
+
+ BEGIN_CASE(JSOP_NAME)
+ BEGIN_CASE(JSOP_CALLNAME)
+ {
+ JSPropCacheEntry *entry;
+
+ obj = fp->scopeChain;
+ if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {
+ PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);
+ if (!atom) {
+ ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);
+ if (PCVAL_IS_OBJECT(entry->vword)) {
+ rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);
+ JS_UNLOCK_OBJ(cx, obj2);
+ goto do_push_rval;
+ }
+
+ if (PCVAL_IS_SLOT(entry->vword)) {
+ slot = PCVAL_TO_SLOT(entry->vword);
+ JS_ASSERT(slot < obj2->map->freeslot);
+ rval = LOCKED_OBJ_GET_SLOT(obj2, slot);
+ JS_UNLOCK_OBJ(cx, obj2);
+ goto do_push_rval;
+ }
+
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ goto do_native_get;
+ }
+ } else {
+ entry = NULL;
+ LOAD_ATOM(0);
+ }
+
+ id = ATOM_TO_JSID(atom);
+ if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
+ goto error;
+ if (!prop) {
+ /* Kludge to allow (typeof foo == "undefined") tests. */
+ endpc = script->code + script->length;
+ op2 = (JSOp) regs.pc[JSOP_NAME_LENGTH];
+ if (op2 == JSOP_TYPEOF) {
+ PUSH_OPND(JSVAL_VOID);
+ len = JSOP_NAME_LENGTH;
+ DO_NEXT_OP(len);
+ }
+ goto atom_not_defined;
+ }
+
+ /* Take the slow path if prop was not found in a native object. */
+ if (!OBJ_IS_NATIVE(obj) || !OBJ_IS_NATIVE(obj2)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ entry = NULL;
+ } else {
+ sprop = (JSScopeProperty *)prop;
+ do_native_get:
+ NATIVE_GET(cx, obj, obj2, sprop, &rval);
+ OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *) sprop);
+ }
+
+ do_push_rval:
+ PUSH_OPND(rval);
+ if (op == JSOP_CALLNAME)
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ }
+ END_CASE(JSOP_NAME)
+
+ BEGIN_CASE(JSOP_UINT16)
+ i = (jsint) GET_UINT16(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_UINT16)
+
+ BEGIN_CASE(JSOP_UINT24)
+ i = (jsint) GET_UINT24(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_UINT24)
+
+ BEGIN_CASE(JSOP_INT8)
+ i = GET_INT8(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_INT8)
+
+ BEGIN_CASE(JSOP_INT32)
+ i = GET_INT32(regs.pc);
+ rval = INT_TO_JSVAL(i);
+ PUSH_OPND(rval);
+ END_CASE(JSOP_INT32)
+
+ BEGIN_CASE(JSOP_INDEXBASE)
+ /*
+ * Here atoms can exceed script->atomMap.length as we use atoms
+ * as a segment register for object literals as well.
+ */
+ atoms += GET_INDEXBASE(regs.pc);
+ END_CASE(JSOP_INDEXBASE)
+
+ BEGIN_CASE(JSOP_INDEXBASE1)
+ BEGIN_CASE(JSOP_INDEXBASE2)
+ BEGIN_CASE(JSOP_INDEXBASE3)
+ atoms += (op - JSOP_INDEXBASE1 + 1) << 16;
+ END_CASE(JSOP_INDEXBASE3)
+
+ BEGIN_CASE(JSOP_RESETBASE0)
+ BEGIN_CASE(JSOP_RESETBASE)
+ atoms = script->atomMap.vector;
+ END_CASE(JSOP_RESETBASE)
+
+ BEGIN_CASE(JSOP_DOUBLE)
+ BEGIN_CASE(JSOP_STRING)
+ LOAD_ATOM(0);
+ PUSH_OPND(ATOM_KEY(atom));
+ END_CASE(JSOP_DOUBLE)
+
+ BEGIN_CASE(JSOP_OBJECT)
+ LOAD_OBJECT(0);
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_OBJECT)
+
+ BEGIN_CASE(JSOP_REGEXP)
+ {
+ JSObject *funobj;
+
+ /*
+ * Push a regexp object for the atom mapped by the bytecode at pc,
+ * cloning the literal's regexp object if necessary, to simulate in
+ * the pre-compile/execute-later case what ECMA specifies for the
+ * compile-and-go case: that scanning each regexp literal creates
+ * a single corresponding RegExp object.
+ *
+ * To support pre-compilation transparently, we must handle the
+ * case where a regexp object literal is used in a different global
+ * at execution time from the global with which it was scanned at
+ * compile time. We do this by re-wrapping the JSRegExp private
+ * data struct with a cloned object having the right prototype and
+ * parent, and having its own lastIndex property value storage.
+ *
+ * Unlike JSOP_DEFFUN and other prolog bytecodes that may clone
+ * literal objects, we don't want to pay a script prolog execution
+ * price for all regexp literals in a script (many may not be used
+ * by a particular execution of that script, depending on control
+ * flow), so we initialize lazily here.
+ *
+ * XXX This code is specific to regular expression objects. If we
+ * need a similar op for other kinds of object literals, we should
+ * push cloning down under JSObjectOps and reuse code here.
+ */
+ index = GET_FULL_INDEX(0);
+ JS_ASSERT(index < JS_SCRIPT_REGEXPS(script)->length);
+
+ slot = index;
+ if (fp->fun) {
+ /*
+ * We're in function code, not global or eval code (in eval
+ * code, JSOP_REGEXP is never emitted). The cloned funobj
+ * contains JS_SCRIPT_REGEXPS(script)->length reserved slots
+ * for the cloned regexps; see fun_reserveSlots, jsfun.c.
+ */
+ funobj = fp->callee;
+ slot += JSCLASS_RESERVED_SLOTS(&js_FunctionClass);
+ if (script->upvarsOffset != 0)
+ slot += JS_SCRIPT_UPVARS(script)->length;
+ if (!JS_GetReservedSlot(cx, funobj, slot, &rval))
+ goto error;
+ if (JSVAL_IS_VOID(rval))
+ rval = JSVAL_NULL;
+ } else {
+ /*
+ * We're in global code. The code generator reserved a slot
+ * for the regexp among script->nfixed slots. All such slots
+ * are initialized to null, not void, for faster testing in
+ * JSOP_*GVAR cases. To simplify index calculations we count
+ * regexps in the reverse order down from script->nslots - 1.
+ */
+ JS_ASSERT(slot < script->nfixed);
+ slot = script->nfixed - slot - 1;
+ rval = fp->slots[slot];
+#ifdef __GNUC__
+ funobj = NULL; /* suppress bogus gcc warnings */
+#endif
+ }
+
+ if (JSVAL_IS_NULL(rval)) {
+ /* Compute the current global object in obj2. */
+ obj2 = fp->scopeChain;
+ while ((parent = OBJ_GET_PARENT(cx, obj2)) != NULL)
+ obj2 = parent;
+
+ /*
+ * If obj's parent is not obj2, we must clone obj so that it
+ * has the right parent, and therefore, the right prototype.
+ *
+ * Yes, this means we assume that the correct RegExp.prototype
+ * to which regexp instances (including literals) delegate can
+ * be distinguished solely by the instance's parent, which was
+ * set to the parent of the RegExp constructor function object
+ * when the instance was created. In other words,
+ *
+ * (/x/.__parent__ == RegExp.__parent__) implies
+ * (/x/.__proto__ == RegExp.prototype)
+ *
+ * (unless you assign a different object to RegExp.prototype
+ * at runtime, in which case, ECMA doesn't specify operation,
+ * and you get what you deserve).
+ *
+ * This same coupling between instance parent and constructor
+ * parent turns up everywhere (see jsobj.c's FindClassObject,
+ * js_ConstructObject, and js_NewObject). It's fundamental to
+ * the design of the language when you consider multiple global
+ * objects and separate compilation and execution, even though
+ * it is not specified fully in ECMA.
+ */
+ JS_GET_SCRIPT_REGEXP(script, index, obj);
+ if (OBJ_GET_PARENT(cx, obj) != obj2) {
+ obj = js_CloneRegExpObject(cx, obj, obj2);
+ if (!obj)
+ goto error;
+ }
+ rval = OBJECT_TO_JSVAL(obj);
+
+ /* Store the regexp object value in its cloneIndex slot. */
+ if (fp->fun) {
+ if (!JS_SetReservedSlot(cx, funobj, slot, rval))
+ goto error;
+ } else {
+ fp->slots[slot] = rval;
+ }
+ }
+
+ PUSH_OPND(rval);
+ }
+ END_CASE(JSOP_REGEXP)
+
+ BEGIN_CASE(JSOP_ZERO)
+ PUSH_OPND(JSVAL_ZERO);
+ END_CASE(JSOP_ZERO)
+
+ BEGIN_CASE(JSOP_ONE)
+ PUSH_OPND(JSVAL_ONE);
+ END_CASE(JSOP_ONE)
+
+ BEGIN_CASE(JSOP_NULL)
+ BEGIN_CASE(JSOP_NULLTHIS)
+ PUSH_OPND(JSVAL_NULL);
+ END_CASE(JSOP_NULL)
+
+ BEGIN_CASE(JSOP_FALSE)
+ PUSH_OPND(JSVAL_FALSE);
+ END_CASE(JSOP_FALSE)
+
+ BEGIN_CASE(JSOP_TRUE)
+ PUSH_OPND(JSVAL_TRUE);
+ END_CASE(JSOP_TRUE)
+
+ BEGIN_CASE(JSOP_TABLESWITCH)
+ pc2 = regs.pc;
+ len = GET_JUMP_OFFSET(pc2);
+
+ /*
+ * ECMAv2+ forbids conversion of discriminant, so we will skip to
+ * the default case if the discriminant isn't already an int jsval.
+ * (This opcode is emitted only for dense jsint-domain switches.)
+ */
+ rval = POP_OPND();
+ if (JSVAL_IS_INT(rval)) {
+ i = JSVAL_TO_INT(rval);
+ } else if (JSVAL_IS_DOUBLE(rval) && *JSVAL_TO_DOUBLE(rval) == 0) {
+ /* Treat -0 (double) as 0. */
+ i = 0;
+ } else {
+ DO_NEXT_OP(len);
+ }
+
+ pc2 += JUMP_OFFSET_LEN;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+
+ i -= low;
+ if ((jsuint)i < (jsuint)(high - low + 1)) {
+ pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
+ off = (jsint) GET_JUMP_OFFSET(pc2);
+ if (off)
+ len = off;
+ }
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_TABLESWITCHX)
+ pc2 = regs.pc;
+ len = GET_JUMPX_OFFSET(pc2);
+
+ /*
+ * ECMAv2+ forbids conversion of discriminant, so we will skip to
+ * the default case if the discriminant isn't already an int jsval.
+ * (This opcode is emitted only for dense jsint-domain switches.)
+ */
+ rval = POP_OPND();
+ if (JSVAL_IS_INT(rval)) {
+ i = JSVAL_TO_INT(rval);
+ } else if (JSVAL_IS_DOUBLE(rval) && *JSVAL_TO_DOUBLE(rval) == 0) {
+ /* Treat -0 (double) as 0. */
+ i = 0;
+ } else {
+ DO_NEXT_OP(len);
+ }
+
+ pc2 += JUMPX_OFFSET_LEN;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+
+ i -= low;
+ if ((jsuint)i < (jsuint)(high - low + 1)) {
+ pc2 += JUMP_OFFSET_LEN + JUMPX_OFFSET_LEN * i;
+ off = (jsint) GET_JUMPX_OFFSET(pc2);
+ if (off)
+ len = off;
+ }
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_LOOKUPSWITCHX)
+ off = JUMPX_OFFSET_LEN;
+ goto do_lookup_switch;
+
+ BEGIN_CASE(JSOP_LOOKUPSWITCH)
+ off = JUMP_OFFSET_LEN;
+
+ do_lookup_switch:
+ /*
+ * JSOP_LOOKUPSWITCH and JSOP_LOOKUPSWITCHX are never used if
+ * any atom index in it would exceed 64K limit.
+ */
+ JS_ASSERT(atoms == script->atomMap.vector);
+ pc2 = regs.pc;
+ lval = POP_OPND();
+
+ if (!JSVAL_IS_NUMBER(lval) &&
+ !JSVAL_IS_STRING(lval) &&
+ !JSVAL_IS_BOOLEAN(lval)) {
+ goto end_lookup_switch;
+ }
+
+ pc2 += off;
+ npairs = (jsint) GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+ JS_ASSERT(npairs); /* empty switch uses JSOP_TABLESWITCH */
+
+#define SEARCH_PAIRS(MATCH_CODE) \
+ for (;;) { \
+ JS_ASSERT(GET_INDEX(pc2) < script->atomMap.length); \
+ atom = atoms[GET_INDEX(pc2)]; \
+ rval = ATOM_KEY(atom); \
+ MATCH_CODE \
+ pc2 += INDEX_LEN; \
+ if (match) \
+ break; \
+ pc2 += off; \
+ if (--npairs == 0) { \
+ pc2 = regs.pc; \
+ break; \
+ } \
+ }
+ if (JSVAL_IS_STRING(lval)) {
+ str = JSVAL_TO_STRING(lval);
+ SEARCH_PAIRS(
+ match = (JSVAL_IS_STRING(rval) &&
+ ((str2 = JSVAL_TO_STRING(rval)) == str ||
+ js_EqualStrings(str2, str)));
+ )
+ } else if (JSVAL_IS_DOUBLE(lval)) {
+ d = *JSVAL_TO_DOUBLE(lval);
+ SEARCH_PAIRS(
+ match = (JSVAL_IS_DOUBLE(rval) &&
+ *JSVAL_TO_DOUBLE(rval) == d);
+ )
+ } else {
+ SEARCH_PAIRS(
+ match = (lval == rval);
+ )
+ }
+#undef SEARCH_PAIRS
+
+ end_lookup_switch:
+ len = (op == JSOP_LOOKUPSWITCH)
+ ? GET_JUMP_OFFSET(pc2)
+ : GET_JUMPX_OFFSET(pc2);
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_TRAP)
+ {
+ JSTrapStatus status;
+
+ status = JS_HandleTrap(cx, script, regs.pc, &rval);
+ switch (status) {
+ case JSTRAP_ERROR:
+ goto error;
+ case JSTRAP_RETURN:
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ default:;
+ break;
+ }
+ JS_ASSERT(status == JSTRAP_CONTINUE);
+ LOAD_INTERRUPT_HANDLER(cx);
+ JS_ASSERT(JSVAL_IS_INT(rval));
+ op = (JSOp) JSVAL_TO_INT(rval);
+ JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);
+ DO_OP();
+ }
+
+ BEGIN_CASE(JSOP_ARGUMENTS)
+ if (!js_GetArgsValue(cx, fp, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ARGUMENTS)
+
+ BEGIN_CASE(JSOP_ARGSUB)
+ id = INT_TO_JSID(GET_ARGNO(regs.pc));
+ if (!js_GetArgsProperty(cx, fp, id, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ARGSUB)
+
+ BEGIN_CASE(JSOP_ARGCNT)
+ id = ATOM_TO_JSID(rt->atomState.lengthAtom);
+ if (!js_GetArgsProperty(cx, fp, id, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ARGCNT)
+
+ BEGIN_CASE(JSOP_GETARG)
+ BEGIN_CASE(JSOP_CALLARG)
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ METER_SLOT_OP(op, slot);
+ PUSH_OPND(fp->argv[slot]);
+ if (op == JSOP_CALLARG)
+ PUSH_OPND(JSVAL_NULL);
+ END_CASE(JSOP_GETARG)
+
+ BEGIN_CASE(JSOP_SETARG)
+ slot = GET_ARGNO(regs.pc);
+ JS_ASSERT(slot < fp->fun->nargs);
+ METER_SLOT_OP(op, slot);
+ vp = &fp->argv[slot];
+ GC_POKE(cx, *vp);
+ *vp = FETCH_OPND(-1);
+ END_SET_CASE(JSOP_SETARG)
+
+ BEGIN_CASE(JSOP_GETLOCAL)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ PUSH_OPND(fp->slots[slot]);
+ END_CASE(JSOP_GETLOCAL)
+
+ BEGIN_CASE(JSOP_CALLLOCAL)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ PUSH_OPND(fp->slots[slot]);
+ PUSH_OPND(JSVAL_NULL);
+ END_CASE(JSOP_CALLLOCAL)
+
+ BEGIN_CASE(JSOP_SETLOCAL)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < script->nslots);
+ vp = &fp->slots[slot];
+ GC_POKE(cx, *vp);
+ *vp = FETCH_OPND(-1);
+ END_SET_CASE(JSOP_SETLOCAL)
+
+ BEGIN_CASE(JSOP_GETUPVAR)
+ BEGIN_CASE(JSOP_CALLUPVAR)
+ {
+ JSUpvarArray *uva;
+ uint32 skip;
+ JSStackFrame *fp2;
+
+ index = GET_UINT16(regs.pc);
+ uva = JS_SCRIPT_UPVARS(script);
+ JS_ASSERT(index < uva->length);
+ skip = UPVAR_FRAME_SKIP(uva->vector[index]);
+ fp2 = cx->display[script->staticDepth - skip];
+ JS_ASSERT(fp2->fun && fp2->script);
+
+ slot = UPVAR_FRAME_SLOT(uva->vector[index]);
+ if (slot < fp2->fun->nargs) {
+ vp = fp2->argv;
+ } else {
+ slot -= fp2->fun->nargs;
+ JS_ASSERT(slot < fp2->script->nslots);
+ vp = fp2->slots;
+ }
+
+ PUSH_OPND(vp[slot]);
+ if (op == JSOP_CALLUPVAR)
+ PUSH_OPND(JSVAL_NULL);
+ }
+ END_CASE(JSOP_GETUPVAR)
+
+ BEGIN_CASE(JSOP_GETGVAR)
+ BEGIN_CASE(JSOP_CALLGVAR)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < GlobalVarCount(fp));
+ METER_SLOT_OP(op, slot);
+ lval = fp->slots[slot];
+ if (JSVAL_IS_NULL(lval)) {
+ op = (op == JSOP_GETGVAR) ? JSOP_NAME : JSOP_CALLNAME;
+ DO_OP();
+ }
+ obj = fp->varobj;
+ slot = JSVAL_TO_INT(lval);
+ rval = OBJ_GET_SLOT(cx, obj, slot);
+ PUSH_OPND(rval);
+ if (op == JSOP_CALLGVAR)
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_GETGVAR)
+
+ BEGIN_CASE(JSOP_SETGVAR)
+ slot = GET_SLOTNO(regs.pc);
+ JS_ASSERT(slot < GlobalVarCount(fp));
+ METER_SLOT_OP(op, slot);
+ rval = FETCH_OPND(-1);
+ obj = fp->varobj;
+ lval = fp->slots[slot];
+ if (JSVAL_IS_NULL(lval)) {
+ /*
+ * Inline-clone and deoptimize JSOP_SETNAME code here because
+ * JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval]
+ * as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME.
+ */
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ } else {
+ slot = JSVAL_TO_INT(lval);
+ JS_LOCK_OBJ(cx, obj);
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, rval);
+ JS_UNLOCK_OBJ(cx, obj);
+ }
+ END_SET_CASE(JSOP_SETGVAR)
+
+ BEGIN_CASE(JSOP_DEFCONST)
+ BEGIN_CASE(JSOP_DEFVAR)
+ index = GET_INDEX(regs.pc);
+ atom = atoms[index];
+
+ /*
+ * index is relative to atoms at this point but for global var
+ * code below we need the absolute value.
+ */
+ index += atoms - script->atomMap.vector;
+ obj = fp->varobj;
+ attrs = JSPROP_ENUMERATE;
+ if (!(fp->flags & JSFRAME_EVAL))
+ attrs |= JSPROP_PERMANENT;
+ if (op == JSOP_DEFCONST)
+ attrs |= JSPROP_READONLY;
+
+ /* Lookup id in order to check for redeclaration problems. */
+ id = ATOM_TO_JSID(atom);
+ if (!js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))
+ goto error;
+
+ /* Bind a variable only if it's not yet defined. */
+ if (!prop) {
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
+ JS_PropertyStub, JS_PropertyStub,
+ attrs, &prop)) {
+ goto error;
+ }
+ JS_ASSERT(prop);
+ obj2 = obj;
+ }
+
+ /*
+ * Try to optimize a property we either just created, or found
+ * directly in the global object, that is permanent, has a slot,
+ * and has stub getter and setter, into a "fast global" accessed
+ * by the JSOP_*GVAR opcodes.
+ */
+ if (!fp->fun &&
+ index < GlobalVarCount(fp) &&
+ (attrs & JSPROP_PERMANENT) &&
+ obj2 == obj &&
+ OBJ_IS_NATIVE(obj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&
+ SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_STUB_SETTER(sprop)) {
+ /*
+ * Fast globals use frame variables to map the global
+ * name's atom index to the permanent fp->varobj slot
+ * number, tagged as a jsval. The atom index for the
+ * global's name literal is identical to its variable
+ * index.
+ */
+ fp->slots[index] = INT_TO_JSVAL(sprop->slot);
+ }
+ }
+
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ END_CASE(JSOP_DEFVAR)
+
+ BEGIN_CASE(JSOP_DEFFUN)
+ /*
+ * A top-level function defined in Global or Eval code (see
+ * ECMA-262 Ed. 3), or else a SpiderMonkey extension: a named
+ * function statement in a compound statement (not at the top
+ * statement level of global code, or at the top level of a
+ * function body).
+ */
+ LOAD_FUNCTION(0);
+
+ if (!fp->blockChain) {
+ obj2 = fp->scopeChain;
+ } else {
+ obj2 = js_GetScopeChain(cx, fp);
+ if (!obj2)
+ goto error;
+ }
+
+ /*
+ * If static link is not current scope, clone fun's object to link
+ * to the current scope via parent. This clause exists to enable
+ * sharing of compiled functions among multiple equivalent scopes,
+ * splitting the cost of compilation evenly among the scopes and
+ * amortizing it over a number of executions. Examples include XUL
+ * scripts and event handlers shared among Mozilla chrome windows,
+ * and server-side JS user-defined functions shared among requests.
+ */
+ obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != obj2) {
+ obj = js_CloneFunctionObject(cx, fun, obj2);
+ if (!obj)
+ goto error;
+ }
+
+ /*
+ * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All
+ * paths from here must flow through the "Restore fp->scopeChain"
+ * code below the OBJ_DEFINE_PROPERTY call.
+ */
+ MUST_FLOW_THROUGH("restore");
+ fp->scopeChain = obj;
+ rval = OBJECT_TO_JSVAL(obj);
+
+ /*
+ * ECMA requires functions defined when entering Eval code to be
+ * impermanent.
+ */
+ attrs = (fp->flags & JSFRAME_EVAL)
+ ? JSPROP_ENUMERATE
+ : JSPROP_ENUMERATE | JSPROP_PERMANENT;
+
+ /*
+ * Load function flags that are also property attributes. Getters
+ * and setters do not need a slot, their value is stored elsewhere
+ * in the property itself, not in obj slots.
+ */
+ flags = JSFUN_GSFLAG2ATTR(fun->flags);
+ if (flags) {
+ attrs |= flags | JSPROP_SHARED;
+ rval = JSVAL_VOID;
+ }
+
+ /*
+ * We define the function as a property of the variable object and
+ * not the current scope chain even for the case of function
+ * expression statements and functions defined by eval inside let
+ * or with blocks.
+ */
+ parent = fp->varobj;
+ JS_ASSERT(parent);
+
+ /*
+ * Check for a const property of the same name -- or any kind
+ * of property if executing with the strict option. We check
+ * here at runtime as well as at compile-time, to handle eval
+ * as well as multiple HTML script tags.
+ */
+ id = ATOM_TO_JSID(fun->atom);
+ ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL);
+ if (ok) {
+ if (attrs == JSPROP_ENUMERATE) {
+ JS_ASSERT(fp->flags & JSFRAME_EVAL);
+ ok = OBJ_SET_PROPERTY(cx, parent, id, &rval);
+ } else {
+ JS_ASSERT(attrs & JSPROP_PERMANENT);
+
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, id, rval,
+ (flags & JSPROP_GETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ (flags & JSPROP_SETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ attrs,
+ NULL);
+ }
+ }
+
+ /* Restore fp->scopeChain now that obj is defined in fp->varobj. */
+ MUST_FLOW_LABEL(restore)
+ fp->scopeChain = obj2;
+ if (!ok) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ goto error;
+ }
+ END_CASE(JSOP_DEFFUN)
+
+ BEGIN_CASE(JSOP_DEFLOCALFUN)
+ LOAD_FUNCTION(SLOTNO_LEN);
+
+ /*
+ * Define a local function (i.e., one nested at the top level of
+ * another function), parented by the current scope chain, and
+ * stored in a local variable slot that the compiler allocated.
+ * This is an optimization over JSOP_DEFFUN that avoids requiring
+ * a call object for the outer function's activation.
+ */
+ slot = GET_SLOTNO(regs.pc);
+
+ parent = js_GetScopeChain(cx, fp);
+ if (!parent)
+ goto error;
+
+ obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
+ obj = js_CloneFunctionObject(cx, fun, parent);
+ if (!obj)
+ goto error;
+ }
+
+ TRACE_2(DefLocalFunSetSlot, slot, obj);
+
+ fp->slots[slot] = OBJECT_TO_JSVAL(obj);
+ END_CASE(JSOP_DEFLOCALFUN)
+
+ BEGIN_CASE(JSOP_ANONFUNOBJ)
+ /* Load the specified function object literal. */
+ LOAD_FUNCTION(0);
+
+ /* If re-parenting, push a clone of the function object. */
+ parent = js_GetScopeChain(cx, fp);
+ if (!parent)
+ goto error;
+ obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != parent) {
+ obj = js_CloneFunctionObject(cx, fun, parent);
+ if (!obj)
+ goto error;
+ }
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_ANONFUNOBJ)
+
+ BEGIN_CASE(JSOP_NAMEDFUNOBJ)
+ LOAD_FUNCTION(0);
+
+ /*
+ * ECMA ed. 3 FunctionExpression: function Identifier [etc.].
+ *
+ * 1. Create a new object as if by the expression new Object().
+ * 2. Add Result(1) to the front of the scope chain.
+ *
+ * Step 2 is achieved by making the new object's parent be the
+ * current scope chain, and then making the new object the parent
+ * of the Function object clone.
+ */
+ obj2 = js_GetScopeChain(cx, fp);
+ if (!obj2)
+ goto error;
+ parent = js_NewObject(cx, &js_ObjectClass, NULL, obj2, 0);
+ if (!parent)
+ goto error;
+
+ /*
+ * 3. Create a new Function object as specified in section 13.2
+ * with [parameters and body specified by the function expression
+ * that was parsed by the compiler into a Function object, and
+ * saved in the script's atom map].
+ *
+ * Protect parent from the GC.
+ */
+ fp->scopeChain = parent;
+ obj = js_CloneFunctionObject(cx, fun, parent);
+ if (!obj)
+ goto error;
+
+ /*
+ * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY. All
+ * paths from here must flow through the "Restore fp->scopeChain"
+ * code below the OBJ_DEFINE_PROPERTY call.
+ */
+ MUST_FLOW_THROUGH("restore2");
+ fp->scopeChain = obj;
+ rval = OBJECT_TO_JSVAL(obj);
+
+ /*
+ * 4. Create a property in the object Result(1). The property's
+ * name is [fun->atom, the identifier parsed by the compiler],
+ * value is Result(3), and attributes are { DontDelete, ReadOnly }.
+ */
+ attrs = JSFUN_GSFLAG2ATTR(fun->flags);
+ if (attrs) {
+ attrs |= JSPROP_SHARED;
+ rval = JSVAL_VOID;
+ }
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, ATOM_TO_JSID(fun->atom), rval,
+ (attrs & JSPROP_GETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ (attrs & JSPROP_SETTER)
+ ? JS_EXTENSION (JSPropertyOp) obj
+ : JS_PropertyStub,
+ attrs |
+ JSPROP_ENUMERATE | JSPROP_PERMANENT |
+ JSPROP_READONLY,
+ NULL);
+
+ /* Restore fp->scopeChain now that obj is defined in parent. */
+ MUST_FLOW_LABEL(restore2)
+ fp->scopeChain = obj2;
+ if (!ok) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ goto error;
+ }
+
+ /*
+ * 5. Remove Result(1) from the front of the scope chain [no-op].
+ * 6. Return Result(3).
+ */
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_NAMEDFUNOBJ)
+
+#if JS_HAS_GETTER_SETTER
+ BEGIN_CASE(JSOP_GETTER)
+ BEGIN_CASE(JSOP_SETTER)
+ do_getter_setter:
+ op2 = (JSOp) *++regs.pc;
+ switch (op2) {
+ case JSOP_INDEXBASE:
+ atoms += GET_INDEXBASE(regs.pc);
+ regs.pc += JSOP_INDEXBASE_LENGTH - 1;
+ goto do_getter_setter;
+ case JSOP_INDEXBASE1:
+ case JSOP_INDEXBASE2:
+ case JSOP_INDEXBASE3:
+ atoms += (op2 - JSOP_INDEXBASE1 + 1) << 16;
+ goto do_getter_setter;
+
+ case JSOP_SETNAME:
+ case JSOP_SETPROP:
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ rval = FETCH_OPND(-1);
+ i = -1;
+ goto gs_pop_lval;
+
+ case JSOP_SETELEM:
+ rval = FETCH_OPND(-1);
+ id = 0;
+ i = -2;
+ gs_pop_lval:
+ FETCH_OBJECT(cx, i - 1, lval, obj);
+ break;
+
+ case JSOP_INITPROP:
+ JS_ASSERT(regs.sp - StackBase(fp) >= 2);
+ rval = FETCH_OPND(-1);
+ i = -1;
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+ goto gs_get_lval;
+
+ default:
+ JS_ASSERT(op2 == JSOP_INITELEM);
+
+ JS_ASSERT(regs.sp - StackBase(fp) >= 3);
+ rval = FETCH_OPND(-1);
+ id = 0;
+ i = -2;
+ gs_get_lval:
+ lval = FETCH_OPND(i-1);
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
+ obj = JSVAL_TO_OBJECT(lval);
+ break;
+ }
+
+ /* Ensure that id has a type suitable for use with obj. */
+ if (id == 0)
+ FETCH_ELEMENT_ID(obj, i, id);
+
+ if (JS_TypeOfValue(cx, rval) != JSTYPE_FUNCTION) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ (op == JSOP_GETTER)
+ ? js_getter_str
+ : js_setter_str);
+ goto error;
+ }
+
+ /*
+ * Getters and setters are just like watchpoints from an access
+ * control point of view.
+ */
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &rtmp, &attrs))
+ goto error;
+
+ if (op == JSOP_GETTER) {
+ getter = JS_EXTENSION (JSPropertyOp) JSVAL_TO_OBJECT(rval);
+ setter = JS_PropertyStub;
+ attrs = JSPROP_GETTER;
+ } else {
+ getter = JS_PropertyStub;
+ setter = JS_EXTENSION (JSPropertyOp) JSVAL_TO_OBJECT(rval);
+ attrs = JSPROP_SETTER;
+ }
+ attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;
+
+ /* Check for a readonly or permanent property of the same name. */
+ if (!js_CheckRedeclaration(cx, obj, id, attrs, NULL, NULL))
+ goto error;
+
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, getter, setter,
+ attrs, NULL)) {
+ goto error;
+ }
+
+ regs.sp += i;
+ if (js_CodeSpec[op2].ndefs)
+ STORE_OPND(-1, rval);
+ len = js_CodeSpec[op2].length;
+ DO_NEXT_OP(len);
+#endif /* JS_HAS_GETTER_SETTER */
+
+ BEGIN_CASE(JSOP_HOLE)
+ PUSH_OPND(JSVAL_HOLE);
+ END_CASE(JSOP_HOLE)
+
+ BEGIN_CASE(JSOP_NEWARRAY)
+ len = GET_UINT24(regs.pc);
+ JS_ASSERT(len <= regs.sp - StackBase(fp));
+ obj = js_NewArrayObject(cx, len, regs.sp - len, JS_TRUE);
+ if (!obj)
+ goto error;
+ regs.sp -= len - 1;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_NEWARRAY)
+
+ BEGIN_CASE(JSOP_NEWINIT)
+ i = GET_INT8(regs.pc);
+ JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
+ obj = (i == JSProto_Array)
+ ? js_NewArrayObject(cx, 0, NULL)
+ : js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ fp->sharpDepth++;
+ LOAD_INTERRUPT_HANDLER(cx);
+ END_CASE(JSOP_NEWINIT)
+
+ BEGIN_CASE(JSOP_ENDINIT)
+ if (--fp->sharpDepth == 0)
+ fp->sharpArray = NULL;
+
+ /* Re-set the newborn root to the top of this object tree. */
+ JS_ASSERT(regs.sp - StackBase(fp) >= 1);
+ lval = FETCH_OPND(-1);
+ JS_ASSERT(JSVAL_IS_OBJECT(lval));
+ cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);
+ END_CASE(JSOP_ENDINIT)
+
+ BEGIN_CASE(JSOP_INITPROP)
+ /* Load the property's initial value into rval. */
+ JS_ASSERT(regs.sp - StackBase(fp) >= 2);
+ rval = FETCH_OPND(-1);
+
+ /* Load the object being initialized into lval/obj. */
+ lval = FETCH_OPND(-2);
+ obj = JSVAL_TO_OBJECT(lval);
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_ASSERT(!OBJ_GET_CLASS(cx, obj)->reserveSlots);
+ JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &
+ JSCLASS_SHARE_ALL_PROPERTIES));
+
+ do {
+ JSScope *scope;
+ uint32 kshape;
+ JSPropertyCache *cache;
+ JSPropCacheEntry *entry;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(!SCOPE_IS_SEALED(scope));
+ kshape = scope->shape;
+ cache = &JS_PROPERTY_CACHE(cx);
+ entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];
+ PCMETER(cache->tests++);
+ PCMETER(cache->initests++);
+
+ if (entry->kpc == regs.pc && entry->kshape == kshape) {
+ PCMETER(cache->pchits++);
+ PCMETER(cache->inipchits++);
+
+ JS_ASSERT(PCVAL_IS_SPROP(entry->vword));
+ sprop = PCVAL_TO_SPROP(entry->vword);
+ JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));
+
+ /*
+ * If this property has a non-stub setter, it must be
+ * __proto__, __parent__, or another "shared prototype"
+ * built-in. Force a miss to save code size here and let
+ * the standard code path take care of business.
+ */
+ if (!SPROP_HAS_STUB_SETTER(sprop))
+ goto do_initprop_miss;
+
+ if (scope->object != obj) {
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ goto error;
+ }
+ }
+
+ /*
+ * Detect a repeated property name and force a miss to
+ * share the strict warning code and cope with complexity
+ * managed by js_AddScopeProperty.
+ */
+ if (sprop->parent != scope->lastProp)
+ goto do_initprop_miss;
+
+ TRACE_2(SetPropHit, entry, sprop);
+
+ /*
+ * Otherwise this entry must be for a direct property of
+ * obj, not a proto-property, and there cannot have been
+ * any deletions of prior properties.
+ */
+ JS_ASSERT(PCVCAP_MAKE(sprop->shape, 0, 0) == entry->vcap);
+ JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
+ JS_ASSERT(!scope->table ||
+ !SCOPE_HAS_PROPERTY(scope, sprop));
+
+ slot = sprop->slot;
+ JS_ASSERT(slot == scope->map.freeslot);
+ if (slot < STOBJ_NSLOTS(obj)) {
+ ++scope->map.freeslot;
+ } else {
+ if (!js_AllocSlot(cx, obj, &slot)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ JS_ASSERT(slot == sprop->slot);
+ }
+
+ JS_ASSERT(!scope->lastProp ||
+ scope->shape == scope->lastProp->shape);
+ if (scope->table) {
+ JSScopeProperty *sprop2 =
+ js_AddScopeProperty(cx, scope, sprop->id,
+ sprop->getter, sprop->setter,
+ slot, sprop->attrs,
+ sprop->flags, sprop->shortid);
+ if (!sprop2) {
+ js_FreeSlot(cx, obj, slot);
+ JS_UNLOCK_SCOPE(cx, scope);
+ goto error;
+ }
+ JS_ASSERT(sprop2 == sprop);
+ } else {
+ scope->shape = sprop->shape;
+ ++scope->entryCount;
+ scope->lastProp = sprop;
+ }
+
+ GC_WRITE_BARRIER(cx, scope,
+ LOCKED_OBJ_GET_SLOT(obj, slot),
+ rval);
+ LOCKED_OBJ_SET_SLOT(obj, slot, rval);
+ JS_UNLOCK_SCOPE(cx, scope);
+ break;
+ }
+
+ do_initprop_miss:
+ PCMETER(cache->inipcmisses++);
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /* Get the immediate property name into id. */
+ LOAD_ATOM(0);
+ id = ATOM_TO_JSID(atom);
+
+ /* Set the property named by obj[id] to rval. */
+ if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER,
+ NULL, NULL)) {
+ goto error;
+ }
+ if (!js_SetPropertyHelper(cx, obj, id, &rval, &entry))
+ goto error;
+#ifdef JS_TRACER
+ if (entry)
+ TRACE_1(SetPropMiss, entry);
+#endif
+ } while (0);
+
+ /* Common tail for property cache hit and miss cases. */
+ regs.sp--;
+ END_CASE(JSOP_INITPROP);
+
+ BEGIN_CASE(JSOP_INITELEM)
+ /* Pop the element's value into rval. */
+ JS_ASSERT(regs.sp - StackBase(fp) >= 3);
+ rval = FETCH_OPND(-1);
+
+ /* Find the object being initialized at top of stack. */
+ lval = FETCH_OPND(-3);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval));
+ obj = JSVAL_TO_OBJECT(lval);
+
+ /* Fetch id now that we have obj. */
+ FETCH_ELEMENT_ID(obj, -2, id);
+
+ /*
+ * Check for property redeclaration strict warning (we may be in
+ * an object initialiser, not an array initialiser).
+ */
+ if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER, NULL,
+ NULL)) {
+ goto error;
+ }
+
+ /*
+ * If rval is a hole, do not call OBJ_SET_PROPERTY. In this case,
+ * obj must be an array, so if the current op is the last element
+ * initialiser, set the array length to one greater than id.
+ */
+ if (rval == JSVAL_HOLE) {
+ JS_ASSERT(OBJ_IS_ARRAY(cx, obj));
+ JS_ASSERT(JSID_IS_INT(id));
+ JS_ASSERT((jsuint) JSID_TO_INT(id) < ARRAY_INIT_LIMIT);
+ if ((JSOp) regs.pc[JSOP_INITELEM_LENGTH] == JSOP_ENDINIT &&
+ !js_SetLengthProperty(cx, obj,
+ (jsuint) (JSID_TO_INT(id) + 1))) {
+ goto error;
+ }
+ } else {
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ }
+ regs.sp -= 2;
+ END_CASE(JSOP_INITELEM)
+
+#if JS_HAS_SHARP_VARS
+ BEGIN_CASE(JSOP_DEFSHARP)
+ obj = fp->sharpArray;
+ if (!obj) {
+ obj = js_NewArrayObject(cx, 0, NULL);
+ if (!obj)
+ goto error;
+ fp->sharpArray = obj;
+ }
+ i = (jsint) GET_UINT16(regs.pc);
+ id = INT_TO_JSID(i);
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_PRIMITIVE(rval)) {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SHARP_DEF, numBuf);
+ goto error;
+ }
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ END_CASE(JSOP_DEFSHARP)
+
+ BEGIN_CASE(JSOP_USESHARP)
+ i = (jsint) GET_UINT16(regs.pc);
+ id = INT_TO_JSID(i);
+ obj = fp->sharpArray;
+ if (!obj) {
+ rval = JSVAL_VOID;
+ } else {
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ }
+ if (!JSVAL_IS_OBJECT(rval)) {
+ char numBuf[12];
+
+ JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SHARP_USE, numBuf);
+ goto error;
+ }
+ PUSH_OPND(rval);
+ END_CASE(JSOP_USESHARP)
+#endif /* JS_HAS_SHARP_VARS */
+
+ BEGIN_CASE(JSOP_GOSUB)
+ PUSH(JSVAL_FALSE);
+ i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH;
+ PUSH(INT_TO_JSVAL(i));
+ len = GET_JUMP_OFFSET(regs.pc);
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_GOSUBX)
+ PUSH(JSVAL_FALSE);
+ i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUBX_LENGTH;
+ len = GET_JUMPX_OFFSET(regs.pc);
+ PUSH(INT_TO_JSVAL(i));
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_RETSUB)
+ /* Pop [exception or hole, retsub pc-index]. */
+ rval = POP();
+ lval = POP();
+ JS_ASSERT(JSVAL_IS_BOOLEAN(lval));
+ if (JSVAL_TO_BOOLEAN(lval)) {
+ /*
+ * Exception was pending during finally, throw it *before* we
+ * adjust pc, because pc indexes into script->trynotes. This
+ * turns out not to be necessary, but it seems clearer. And
+ * it points out a FIXME: 350509, due to Igor Bukanov.
+ */
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ }
+ JS_ASSERT(JSVAL_IS_INT(rval));
+ len = JSVAL_TO_INT(rval);
+ regs.pc = script->main;
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_EXCEPTION)
+ JS_ASSERT(cx->throwing);
+ PUSH(cx->exception);
+ cx->throwing = JS_FALSE;
+ END_CASE(JSOP_EXCEPTION)
+
+ BEGIN_CASE(JSOP_THROWING)
+ JS_ASSERT(!cx->throwing);
+ cx->throwing = JS_TRUE;
+ cx->exception = POP_OPND();
+ END_CASE(JSOP_THROWING)
+
+ BEGIN_CASE(JSOP_THROW)
+ JS_ASSERT(!cx->throwing);
+ cx->throwing = JS_TRUE;
+ cx->exception = POP_OPND();
+ /* let the code at error try to catch the exception. */
+ goto error;
+
+ BEGIN_CASE(JSOP_SETLOCALPOP)
+ /*
+ * The stack must have a block with at least one local slot below
+ * the exception object.
+ */
+ JS_ASSERT((size_t) (regs.sp - StackBase(fp)) >= 2);
+ slot = GET_UINT16(regs.pc);
+ JS_ASSERT(slot + 1 < script->nslots);
+ fp->slots[slot] = POP_OPND();
+ END_CASE(JSOP_SETLOCALPOP)
+
+ BEGIN_CASE(JSOP_INSTANCEOF)
+ rval = FETCH_OPND(-1);
+ if (JSVAL_IS_PRIMITIVE(rval) ||
+ !(obj = JSVAL_TO_OBJECT(rval))->map->ops->hasInstance) {
+ js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
+ -1, rval, NULL);
+ goto error;
+ }
+ lval = FETCH_OPND(-2);
+ cond = JS_FALSE;
+ if (!obj->map->ops->hasInstance(cx, obj, lval, &cond))
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));
+ END_CASE(JSOP_INSTANCEOF)
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ BEGIN_CASE(JSOP_DEBUGGER)
+ {
+ JSTrapHandler handler = cx->debugHooks->debuggerHandler;
+ if (handler) {
+ switch (handler(cx, script, regs.pc, &rval,
+ cx->debugHooks->debuggerHandlerData)) {
+ case JSTRAP_ERROR:
+ goto error;
+ case JSTRAP_CONTINUE:
+ break;
+ case JSTRAP_RETURN:
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = rval;
+ goto error;
+ default:;
+ }
+ LOAD_INTERRUPT_HANDLER(cx);
+ }
+ }
+ END_CASE(JSOP_DEBUGGER)
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ BEGIN_CASE(JSOP_DEFXMLNS)
+ rval = POP();
+ if (!js_SetDefaultXMLNamespace(cx, rval))
+ goto error;
+ END_CASE(JSOP_DEFXMLNS)
+
+ BEGIN_CASE(JSOP_ANYNAME)
+ if (!js_GetAnyName(cx, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_ANYNAME)
+
+ BEGIN_CASE(JSOP_QNAMEPART)
+ LOAD_ATOM(0);
+ PUSH_OPND(ATOM_KEY(atom));
+ END_CASE(JSOP_QNAMEPART)
+
+ BEGIN_CASE(JSOP_QNAMECONST)
+ LOAD_ATOM(0);
+ rval = ATOM_KEY(atom);
+ lval = FETCH_OPND(-1);
+ obj = js_ConstructXMLQNameObject(cx, lval, rval);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_QNAMECONST)
+
+ BEGIN_CASE(JSOP_QNAME)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+ obj = js_ConstructXMLQNameObject(cx, lval, rval);
+ if (!obj)
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_QNAME)
+
+ BEGIN_CASE(JSOP_TOATTRNAME)
+ rval = FETCH_OPND(-1);
+ if (!js_ToAttributeName(cx, &rval))
+ goto error;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_TOATTRNAME)
+
+ BEGIN_CASE(JSOP_TOATTRVAL)
+ rval = FETCH_OPND(-1);
+ JS_ASSERT(JSVAL_IS_STRING(rval));
+ str = js_EscapeAttributeValue(cx, JSVAL_TO_STRING(rval), JS_FALSE);
+ if (!str)
+ goto error;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_TOATTRVAL)
+
+ BEGIN_CASE(JSOP_ADDATTRNAME)
+ BEGIN_CASE(JSOP_ADDATTRVAL)
+ rval = FETCH_OPND(-1);
+ lval = FETCH_OPND(-2);
+ str = JSVAL_TO_STRING(lval);
+ str2 = JSVAL_TO_STRING(rval);
+ str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);
+ if (!str)
+ goto error;
+ regs.sp--;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_ADDATTRNAME)
+
+ BEGIN_CASE(JSOP_BINDXMLNAME)
+ lval = FETCH_OPND(-1);
+ if (!js_FindXMLProperty(cx, lval, &obj, &id))
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ PUSH_OPND(ID_TO_VALUE(id));
+ END_CASE(JSOP_BINDXMLNAME)
+
+ BEGIN_CASE(JSOP_SETXMLNAME)
+ obj = JSVAL_TO_OBJECT(FETCH_OPND(-3));
+ rval = FETCH_OPND(-1);
+ FETCH_ELEMENT_ID(obj, -2, id);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ rval = FETCH_OPND(-1);
+ regs.sp -= 2;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_SETXMLNAME)
+
+ BEGIN_CASE(JSOP_CALLXMLNAME)
+ BEGIN_CASE(JSOP_XMLNAME)
+ lval = FETCH_OPND(-1);
+ if (!js_FindXMLProperty(cx, lval, &obj, &id))
+ goto error;
+ if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ STORE_OPND(-1, rval);
+ if (op == JSOP_CALLXMLNAME)
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLNAME)
+
+ BEGIN_CASE(JSOP_DESCENDANTS)
+ BEGIN_CASE(JSOP_DELDESC)
+ FETCH_OBJECT(cx, -2, lval, obj);
+ rval = FETCH_OPND(-1);
+ if (!js_GetXMLDescendants(cx, obj, rval, &rval))
+ goto error;
+
+ if (op == JSOP_DELDESC) {
+ regs.sp[-1] = rval; /* set local root */
+ if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))
+ goto error;
+ rval = JSVAL_TRUE; /* always succeed */
+ }
+
+ regs.sp--;
+ STORE_OPND(-1, rval);
+ END_CASE(JSOP_DESCENDANTS)
+
+ BEGIN_CASE(JSOP_FILTER)
+ /*
+ * We push the hole value before jumping to [enditer] so we can
+ * detect the first iteration and direct js_StepXMLListFilter to
+ * initialize filter's state.
+ */
+ PUSH_OPND(JSVAL_HOLE);
+ len = GET_JUMP_OFFSET(regs.pc);
+ JS_ASSERT(len > 0);
+ END_VARLEN_CASE
+
+ BEGIN_CASE(JSOP_ENDFILTER)
+ cond = (regs.sp[-1] != JSVAL_HOLE);
+ if (cond) {
+ /* Exit the "with" block left from the previous iteration. */
+ js_LeaveWith(cx);
+ }
+ if (!js_StepXMLListFilter(cx, cond))
+ goto error;
+ if (regs.sp[-1] != JSVAL_NULL) {
+ /*
+ * Decrease sp after EnterWith returns as we use sp[-1] there
+ * to root temporaries.
+ */
+ JS_ASSERT(VALUE_IS_XML(cx, regs.sp[-1]));
+ if (!js_EnterWith(cx, -2))
+ goto error;
+ regs.sp--;
+ len = GET_JUMP_OFFSET(regs.pc);
+ JS_ASSERT(len < 0);
+ BRANCH(len);
+ }
+ regs.sp--;
+ END_CASE(JSOP_ENDFILTER);
+
+ BEGIN_CASE(JSOP_TOXML)
+ rval = FETCH_OPND(-1);
+ obj = js_ValueToXMLObject(cx, rval);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_TOXML)
+
+ BEGIN_CASE(JSOP_TOXMLLIST)
+ rval = FETCH_OPND(-1);
+ obj = js_ValueToXMLListObject(cx, rval);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_TOXMLLIST)
+
+ BEGIN_CASE(JSOP_XMLTAGEXPR)
+ rval = FETCH_OPND(-1);
+ str = js_ValueToString(cx, rval);
+ if (!str)
+ goto error;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_XMLTAGEXPR)
+
+ BEGIN_CASE(JSOP_XMLELTEXPR)
+ rval = FETCH_OPND(-1);
+ if (VALUE_IS_XML(cx, rval)) {
+ str = js_ValueToXMLString(cx, rval);
+ } else {
+ str = js_ValueToString(cx, rval);
+ if (str)
+ str = js_EscapeElementValue(cx, str);
+ }
+ if (!str)
+ goto error;
+ STORE_OPND(-1, STRING_TO_JSVAL(str));
+ END_CASE(JSOP_XMLELTEXPR)
+
+ BEGIN_CASE(JSOP_XMLOBJECT)
+ LOAD_OBJECT(0);
+ obj = js_CloneXMLObject(cx, obj);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLOBJECT)
+
+ BEGIN_CASE(JSOP_XMLCDATA)
+ LOAD_ATOM(0);
+ str = ATOM_TO_STRING(atom);
+ obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLCDATA)
+
+ BEGIN_CASE(JSOP_XMLCOMMENT)
+ LOAD_ATOM(0);
+ str = ATOM_TO_STRING(atom);
+ obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str);
+ if (!obj)
+ goto error;
+ PUSH_OPND(OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLCOMMENT)
+
+ BEGIN_CASE(JSOP_XMLPI)
+ LOAD_ATOM(0);
+ str = ATOM_TO_STRING(atom);
+ rval = FETCH_OPND(-1);
+ str2 = JSVAL_TO_STRING(rval);
+ obj = js_NewXMLSpecialObject(cx,
+ JSXML_CLASS_PROCESSING_INSTRUCTION,
+ str, str2);
+ if (!obj)
+ goto error;
+ STORE_OPND(-1, OBJECT_TO_JSVAL(obj));
+ END_CASE(JSOP_XMLPI)
+
+ BEGIN_CASE(JSOP_GETFUNNS)
+ if (!js_GetFunctionNamespace(cx, &rval))
+ goto error;
+ PUSH_OPND(rval);
+ END_CASE(JSOP_GETFUNNS)
+#endif /* JS_HAS_XML_SUPPORT */
+
+ BEGIN_CASE(JSOP_ENTERBLOCK)
+ LOAD_OBJECT(0);
+ JS_ASSERT(!OBJ_IS_CLONED_BLOCK(obj));
+ JS_ASSERT(StackBase(fp) + OBJ_BLOCK_DEPTH(cx, obj) == regs.sp);
+ vp = regs.sp + OBJ_BLOCK_COUNT(cx, obj);
+ JS_ASSERT(regs.sp < vp);
+ JS_ASSERT(vp <= fp->slots + script->nslots);
+ while (regs.sp < vp) {
+ STORE_OPND(0, JSVAL_VOID);
+ regs.sp++;
+ }
+
+ /*
+ * If this frame had to reflect the compile-time block chain into
+ * the runtime scope chain, we can't optimize block scopes out of
+ * runtime any longer, because an outer block that parents obj has
+ * been cloned onto the scope chain. To avoid re-cloning such a
+ * parent and accumulating redundant clones via js_GetScopeChain,
+ * we must clone each block eagerly on entry, and push it on the
+ * scope chain, until this frame pops.
+ */
+ if (fp->flags & JSFRAME_POP_BLOCKS) {
+ JS_ASSERT(!fp->blockChain);
+ obj = js_CloneBlockObject(cx, obj, fp->scopeChain, fp);
+ if (!obj)
+ goto error;
+ fp->scopeChain = obj;
+ } else {
+ JS_ASSERT(!fp->blockChain ||
+ OBJ_GET_PARENT(cx, obj) == fp->blockChain);
+ fp->blockChain = obj;
+ }
+ END_CASE(JSOP_ENTERBLOCK)
+
+ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
+ BEGIN_CASE(JSOP_LEAVEBLOCK)
+ {
+#ifdef DEBUG
+ uintN blockDepth = OBJ_BLOCK_DEPTH(cx,
+ fp->blockChain
+ ? fp->blockChain
+ : fp->scopeChain);
+
+ JS_ASSERT(blockDepth <= StackDepth(script));
+#endif
+ if (fp->blockChain) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, fp->blockChain) == &js_BlockClass);
+ fp->blockChain = OBJ_GET_PARENT(cx, fp->blockChain);
+ } else {
+ /*
+ * This block was cloned into fp->scopeChain, so clear its
+ * private data and sync its locals to their property slots.
+ */
+ if (!js_PutBlockObject(cx, JS_TRUE))
+ goto error;
+ }
+
+ /*
+ * We will move the result of the expression to the new topmost
+ * stack slot.
+ */
+ if (op == JSOP_LEAVEBLOCKEXPR)
+ rval = FETCH_OPND(-1);
+ regs.sp -= GET_UINT16(regs.pc);
+ if (op == JSOP_LEAVEBLOCKEXPR) {
+ JS_ASSERT(StackBase(fp) + blockDepth == regs.sp - 1);
+ STORE_OPND(-1, rval);
+ } else {
+ JS_ASSERT(StackBase(fp) + blockDepth == regs.sp);
+ }
+ }
+ END_CASE(JSOP_LEAVEBLOCK)
+
+#if JS_HAS_GENERATORS
+ BEGIN_CASE(JSOP_GENERATOR)
+ ASSERT_NOT_THROWING(cx);
+ regs.pc += JSOP_GENERATOR_LENGTH;
+ obj = js_NewGenerator(cx, fp);
+ if (!obj)
+ goto error;
+ JS_ASSERT(!fp->callobj && !fp->argsobj);
+ fp->rval = OBJECT_TO_JSVAL(obj);
+ ok = JS_TRUE;
+ if (inlineCallCount != 0)
+ goto inline_return;
+ goto exit;
+
+ BEGIN_CASE(JSOP_YIELD)
+ ASSERT_NOT_THROWING(cx);
+ if (FRAME_TO_GENERATOR(fp)->state == JSGEN_CLOSING) {
+ js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD,
+ JSDVG_SEARCH_STACK, fp->argv[-2], NULL);
+ goto error;
+ }
+ fp->rval = FETCH_OPND(-1);
+ fp->flags |= JSFRAME_YIELDING;
+ regs.pc += JSOP_YIELD_LENGTH;
+ ok = JS_TRUE;
+ goto exit;
+
+ BEGIN_CASE(JSOP_ARRAYPUSH)
+ slot = GET_UINT16(regs.pc);
+ JS_ASSERT(script->nfixed <= slot);
+ JS_ASSERT(slot < script->nslots);
+ lval = fp->slots[slot];
+ obj = JSVAL_TO_OBJECT(lval);
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
+ rval = FETCH_OPND(-1);
+
+ /*
+ * We know that the array is created with only a 'length' private
+ * data slot at JSSLOT_ARRAY_LENGTH, and that previous iterations
+ * of the comprehension have added the only properties directly in
+ * the array object.
+ */
+ i = obj->fslots[JSSLOT_ARRAY_LENGTH];
+ if (i == ARRAY_INIT_LIMIT) {
+ JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
+ JSMSG_ARRAY_INIT_TOO_BIG);
+ goto error;
+ }
+ id = INT_TO_JSID(i);
+ if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))
+ goto error;
+ regs.sp--;
+ END_CASE(JSOP_ARRAYPUSH)
+#endif /* JS_HAS_GENERATORS */
+
+#if JS_THREADED_INTERP
+ L_JSOP_BACKPATCH:
+ L_JSOP_BACKPATCH_POP:
+
+# if !JS_HAS_GENERATORS
+ L_JSOP_GENERATOR:
+ L_JSOP_YIELD:
+ L_JSOP_ARRAYPUSH:
+# endif
+
+# if !JS_HAS_DESTRUCTURING
+ L_JSOP_ENUMCONSTELEM:
+# endif
+
+# if !JS_HAS_XML_SUPPORT
+ L_JSOP_CALLXMLNAME:
+ L_JSOP_STARTXMLEXPR:
+ L_JSOP_STARTXML:
+ L_JSOP_DELDESC:
+ L_JSOP_GETFUNNS:
+ L_JSOP_XMLPI:
+ L_JSOP_XMLCOMMENT:
+ L_JSOP_XMLCDATA:
+ L_JSOP_XMLOBJECT:
+ L_JSOP_XMLELTEXPR:
+ L_JSOP_XMLTAGEXPR:
+ L_JSOP_TOXMLLIST:
+ L_JSOP_TOXML:
+ L_JSOP_ENDFILTER:
+ L_JSOP_FILTER:
+ L_JSOP_DESCENDANTS:
+ L_JSOP_XMLNAME:
+ L_JSOP_SETXMLNAME:
+ L_JSOP_BINDXMLNAME:
+ L_JSOP_ADDATTRVAL:
+ L_JSOP_ADDATTRNAME:
+ L_JSOP_TOATTRVAL:
+ L_JSOP_TOATTRNAME:
+ L_JSOP_QNAME:
+ L_JSOP_QNAMECONST:
+ L_JSOP_QNAMEPART:
+ L_JSOP_ANYNAME:
+ L_JSOP_DEFXMLNS:
+# endif
+
+ L_JSOP_UNUSED131:
+ L_JSOP_UNUSED201:
+ L_JSOP_UNUSED202:
+ L_JSOP_UNUSED203:
+ L_JSOP_UNUSED204:
+ L_JSOP_UNUSED205:
+ L_JSOP_UNUSED206:
+ L_JSOP_UNUSED207:
+ L_JSOP_UNUSED208:
+ L_JSOP_UNUSED209:
+ L_JSOP_UNUSED219:
+ L_JSOP_UNUSED226:
+
+#else /* !JS_THREADED_INTERP */
+ default:
+#endif
+ {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%d", op);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_BYTECODE, numBuf);
+ goto error;
+ }
+
+#ifdef JS_TRACER
+
+#if JS_THREADED_INTERP
+# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \
+ R_##x: RECORD(x); goto L_##x;
+#else
+# define OPDEF(x,val,name,token,length,nuses,ndefs,prec,format) \
+ case 256 + x: RECORD(x); op = x; switchOp = x; goto do_switch;
+#endif
+#include "jsopcode.tbl"
+#undef OPDEF
+
+#endif /* JS_TRACER */
+
+#if !JS_THREADED_INTERP
+
+ } /* switch (op) */
+ }
+#endif /* !JS_THREADED_INTERP */
+
+ error:
+ if (fp->imacpc && cx->throwing) {
+ // To keep things simple, we hard-code imacro exception handlers here.
+ if (*fp->imacpc == JSOP_NEXTITER) {
+ JS_ASSERT(*regs.pc == JSOP_CALL);
+ if (js_ValueIsStopIteration(cx->exception)) {
+ cx->throwing = JS_FALSE;
+ cx->exception = JSVAL_VOID;
+ regs.sp[-1] = JSVAL_HOLE;
+ PUSH(JSVAL_FALSE);
+ goto end_imacro;
+ }
+ }
+
+ // Handle other exceptions as if they came from the imacro-calling pc.
+ regs.pc = fp->imacpc;
+ fp->imacpc = NULL;
+ atoms = script->atomMap.vector;
+ }
+
+ JS_ASSERT((size_t)(regs.pc - script->code) < script->length);
+ if (!cx->throwing) {
+ /* This is an error, not a catchable exception, quit the frame ASAP. */
+ ok = JS_FALSE;
+ } else {
+ JSTrapHandler handler;
+ JSTryNote *tn, *tnlimit;
+ uint32 offset;
+
+ /* Call debugger throw hook if set. */
+ handler = cx->debugHooks->throwHook;
+ if (handler) {
+ switch (handler(cx, script, regs.pc, &rval,
+ cx->debugHooks->throwHookData)) {
+ case JSTRAP_ERROR:
+ cx->throwing = JS_FALSE;
+ goto error;
+ case JSTRAP_RETURN:
+ cx->throwing = JS_FALSE;
+ fp->rval = rval;
+ ok = JS_TRUE;
+ goto forced_return;
+ case JSTRAP_THROW:
+ cx->exception = rval;
+ case JSTRAP_CONTINUE:
+ default:;
+ }
+ LOAD_INTERRUPT_HANDLER(cx);
+ }
+
+ /*
+ * Look for a try block in script that can catch this exception.
+ */
+ if (script->trynotesOffset == 0)
+ goto no_catch;
+
+ offset = (uint32)(regs.pc - script->main);
+ tn = JS_SCRIPT_TRYNOTES(script)->vector;
+ tnlimit = tn + JS_SCRIPT_TRYNOTES(script)->length;
+ do {
+ if (offset - tn->start >= tn->length)
+ continue;
+
+ /*
+ * We have a note that covers the exception pc but we must check
+ * whether the interpreter has already executed the corresponding
+ * handler. This is possible when the executed bytecode
+ * implements break or return from inside a for-in loop.
+ *
+ * In this case the emitter generates additional [enditer] and
+ * [gosub] opcodes to close all outstanding iterators and execute
+ * the finally blocks. If such an [enditer] throws an exception,
+ * its pc can still be inside several nested for-in loops and
+ * try-finally statements even if we have already closed the
+ * corresponding iterators and invoked the finally blocks.
+ *
+ * To address this, we make [enditer] always decrease the stack
+ * even when its implementation throws an exception. Thus already
+ * executed [enditer] and [gosub] opcodes will have try notes
+ * with the stack depth exceeding the current one and this
+ * condition is what we use to filter them out.
+ */
+ if (tn->stackDepth > regs.sp - StackBase(fp))
+ continue;
+
+ /*
+ * Set pc to the first bytecode after the the try note to point
+ * to the beginning of catch or finally or to [enditer] closing
+ * the for-in loop.
+ */
+ regs.pc = (script)->main + tn->start + tn->length;
+
+ ok = js_UnwindScope(cx, fp, tn->stackDepth, JS_TRUE);
+ JS_ASSERT(fp->regs->sp == StackBase(fp) + tn->stackDepth);
+ if (!ok) {
+ /*
+ * Restart the handler search with updated pc and stack depth
+ * to properly notify the debugger.
+ */
+ goto error;
+ }
+
+ switch (tn->kind) {
+ case JSTRY_CATCH:
+ JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK);
+
+#if JS_HAS_GENERATORS
+ /* Catch cannot intercept the closing of a generator. */
+ if (JS_UNLIKELY(cx->exception == JSVAL_ARETURN))
+ break;
+#endif
+
+ /*
+ * Don't clear cx->throwing to save cx->exception from GC
+ * until it is pushed to the stack via [exception] in the
+ * catch block.
+ */
+ len = 0;
+ DO_NEXT_OP(len);
+
+ case JSTRY_FINALLY:
+ /*
+ * Push (true, exception) pair for finally to indicate that
+ * [retsub] should rethrow the exception.
+ */
+ PUSH(JSVAL_TRUE);
+ PUSH(cx->exception);
+ cx->throwing = JS_FALSE;
+ len = 0;
+ DO_NEXT_OP(len);
+
+ case JSTRY_ITER:
+ /*
+ * This is similar to JSOP_ENDITER in the interpreter loop,
+ * except the code now uses the stack slot normally used by
+ * JSOP_NEXTITER, namely regs.sp[-1] before the regs.sp -= 2
+ * adjustment and regs.sp[1] after, to save and restore the
+ * pending exception.
+ */
+ JS_ASSERT(*regs.pc == JSOP_ENDITER);
+ regs.sp[-1] = cx->exception;
+ cx->throwing = JS_FALSE;
+ ok = js_CloseIterator(cx, regs.sp[-2]);
+ regs.sp -= 2;
+ if (!ok)
+ goto error;
+ cx->throwing = JS_TRUE;
+ cx->exception = regs.sp[1];
+ }
+ } while (++tn != tnlimit);
+
+ no_catch:
+ /*
+ * Propagate the exception or error to the caller unless the exception
+ * is an asynchronous return from a generator.
+ */
+ ok = JS_FALSE;
+#if JS_HAS_GENERATORS
+ if (JS_UNLIKELY(cx->throwing && cx->exception == JSVAL_ARETURN)) {
+ cx->throwing = JS_FALSE;
+ ok = JS_TRUE;
+ fp->rval = JSVAL_VOID;
+ }
+#endif
+ }
+
+ forced_return:
+ /*
+ * Unwind the scope making sure that ok stays false even when UnwindScope
+ * returns true.
+ *
+ * When a trap handler returns JSTRAP_RETURN, we jump here with ok set to
+ * true bypassing any finally blocks.
+ */
+ ok &= js_UnwindScope(cx, fp, 0, ok || cx->throwing);
+ JS_ASSERT(regs.sp == StackBase(fp));
+
+ if (inlineCallCount)
+ goto inline_return;
+
+ exit:
+ /*
+ * At this point we are inevitably leaving an interpreted function or a
+ * top-level script, and returning to one of:
+ * (a) an "out of line" call made through js_Invoke;
+ * (b) a js_Execute activation;
+ * (c) a generator (SendToGenerator, jsiter.c).
+ *
+ * We must not be in an inline frame. The check above ensures that for the
+ * error case and for a normal return, the code jumps directly to parent's
+ * frame pc.
+ */
+ JS_ASSERT(inlineCallCount == 0);
+ JS_ASSERT(fp->regs == &regs);
+#ifdef JS_TRACER
+ if (TRACE_RECORDER(cx))
+ js_AbortRecording(cx, "recording out of js_Interpret");
+#endif
+#if JS_HAS_GENERATORS
+ if (JS_UNLIKELY(fp->flags & JSFRAME_YIELDING)) {
+ JSGenerator *gen;
+
+ gen = FRAME_TO_GENERATOR(fp);
+ gen->savedRegs = regs;
+ gen->frame.regs = &gen->savedRegs;
+ JS_PROPERTY_CACHE(cx).disabled -= js_CountWithBlocks(cx, fp);
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0);
+ } else
+#endif /* JS_HAS_GENERATORS */
+ {
+ JS_ASSERT(!fp->blockChain);
+ JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
+ fp->regs = NULL;
+ }
+
+ /* Undo the remaining effects committed on entry to js_Interpret. */
+ if (script->staticDepth < JS_DISPLAY_SIZE)
+ cx->display[script->staticDepth] = fp->displaySave;
+ JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled == fp->pcDisabledSave);
+ if (cx->version == currentVersion && currentVersion != originalVersion)
+ js_SetVersion(cx, originalVersion);
+ --cx->interpLevel;
+
+#ifdef JS_TRACER
+ if (tr) {
+ JS_TRACE_MONITOR(cx).onTrace = JS_TRUE;
+ SET_TRACE_RECORDER(cx, tr);
+ if (!tr->wasDeepAborted()) {
+ tr->popAbortStack();
+ tr->deepAbort();
+ }
+ }
+#endif
+ return ok;
+
+ atom_not_defined:
+ {
+ const char *printable;
+
+ printable = js_AtomToPrintableString(cx, atom);
+ if (printable)
+ js_ReportIsNotDefined(cx, printable);
+ goto error;
+ }
+}
+
+#endif /* !defined jsinvoke_cpp___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h
new file mode 100644
index 0000000..a016c47
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsinterp.h
@@ -0,0 +1,591 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsinterp_h___
+#define jsinterp_h___
+/*
+ * JS interpreter interface.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsfun.h"
+#include "jsopcode.h"
+#include "jsscript.h"
+
+JS_BEGIN_EXTERN_C
+
+typedef struct JSFrameRegs {
+ jsbytecode *pc; /* program counter */
+ jsval *sp; /* stack pointer */
+} JSFrameRegs;
+
+/*
+ * JS stack frame, may be allocated on the C stack by native callers. Always
+ * allocated on cx->stackPool for calls from the interpreter to an interpreted
+ * function.
+ *
+ * NB: This struct is manually initialized in jsinterp.c and jsiter.c. If you
+ * add new members, update both files. But first, try to remove members. The
+ * sharp* and xml* members should be moved onto the stack as local variables
+ * with well-known slots, if possible.
+ */
+struct JSStackFrame {
+ JSFrameRegs *regs;
+ jsbytecode *imacpc; /* null or interpreter macro call pc */
+ jsval *slots; /* variables, locals and operand stack */
+ JSObject *callobj; /* lazily created Call object */
+ JSObject *argsobj; /* lazily created arguments object */
+ JSObject *varobj; /* variables object, where vars go */
+ JSObject *callee; /* function or script object */
+ JSScript *script; /* script being interpreted */
+ JSFunction *fun; /* function being called or null */
+ JSObject *thisp; /* "this" pointer if in method */
+ uintN argc; /* actual argument count */
+ jsval *argv; /* base of argument stack slots */
+ jsval rval; /* function return value */
+ JSStackFrame *down; /* previous frame */
+ void *annotation; /* used by Java security */
+ JSObject *scopeChain; /* scope chain */
+ uintN sharpDepth; /* array/object initializer depth */
+ JSObject *sharpArray; /* scope for #n= initializer vars */
+ uint32 flags; /* frame flags -- see below */
+ JSStackFrame *dormantNext; /* next dormant frame chain */
+ JSObject *xmlNamespace; /* null or default xml namespace in E4X */
+ JSObject *blockChain; /* active compile-time block scopes */
+ JSStackFrame *displaySave; /* previous value of display entry for
+ script->staticDepth */
+#ifdef DEBUG
+ jsrefcount pcDisabledSave; /* for balanced property cache control */
+#endif
+};
+
+#ifdef DEBUG
+#ifdef __cplusplus
+static JS_INLINE uintN
+FramePCOffset(JSStackFrame* fp)
+{
+ return uintN((fp->imacpc ? fp->imacpc : fp->regs->pc) - fp->script->code);
+}
+#endif
+#endif
+
+static JS_INLINE jsval *
+StackBase(JSStackFrame *fp)
+{
+ return fp->slots + fp->script->nfixed;
+}
+
+static JS_INLINE uintN
+GlobalVarCount(JSStackFrame *fp)
+{
+ uintN n;
+
+ JS_ASSERT(!fp->fun);
+ n = fp->script->nfixed;
+ if (fp->script->regexpsOffset != 0)
+ n -= JS_SCRIPT_REGEXPS(fp->script)->length;
+ return n;
+}
+
+typedef struct JSInlineFrame {
+ JSStackFrame frame; /* base struct */
+ JSFrameRegs callerRegs; /* parent's frame registers */
+ void *mark; /* mark before inline frame */
+ void *hookData; /* debugger call hook data */
+ JSVersion callerVersion; /* dynamic version of calling script */
+} JSInlineFrame;
+
+/* JS stack frame flags. */
+#define JSFRAME_CONSTRUCTING 0x01 /* frame is for a constructor invocation */
+#define JSFRAME_COMPUTED_THIS 0x02 /* frame.thisp was computed already */
+#define JSFRAME_ASSIGNING 0x04 /* a complex (not simplex JOF_ASSIGNING) op
+ is currently assigning to a property */
+#define JSFRAME_DEBUGGER 0x08 /* frame for JS_EvaluateInStackFrame */
+#define JSFRAME_EVAL 0x10 /* frame for obj_eval */
+#define JSFRAME_ROOTED_ARGV 0x20 /* frame.argv is rooted by the caller */
+#define JSFRAME_YIELDING 0x40 /* js_Interpret dispatched JSOP_YIELD */
+#define JSFRAME_ITERATOR 0x80 /* trying to get an iterator for for-in */
+#define JSFRAME_POP_BLOCKS 0x100 /* scope chain contains blocks to pop */
+#define JSFRAME_GENERATOR 0x200 /* frame belongs to generator-iterator */
+#define JSFRAME_IMACRO_START 0x400 /* imacro starting -- see jstracer.h */
+
+#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */
+#define JSFRAME_OVERRIDE_BITS 8
+
+#define JSFRAME_SPECIAL (JSFRAME_DEBUGGER | JSFRAME_EVAL)
+
+/*
+ * Property cache with structurally typed capabilities for invalidation, for
+ * polymorphic callsite method/get/set speedups.
+ *
+ * See bug https://bugzilla.mozilla.org/show_bug.cgi?id=365851.
+ */
+#define PROPERTY_CACHE_LOG2 12
+#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2)
+#define PROPERTY_CACHE_MASK JS_BITMASK(PROPERTY_CACHE_LOG2)
+
+/*
+ * Add kshape rather than xor it to avoid collisions between nearby bytecode
+ * that are evolving an object by setting successive properties, incrementing
+ * the object's scope->shape on each set.
+ */
+#define PROPERTY_CACHE_HASH(pc,kshape) \
+ (((((jsuword)(pc) >> PROPERTY_CACHE_LOG2) ^ (jsuword)(pc)) + (kshape)) & \
+ PROPERTY_CACHE_MASK)
+
+#define PROPERTY_CACHE_HASH_PC(pc,kshape) \
+ PROPERTY_CACHE_HASH(pc, kshape)
+
+#define PROPERTY_CACHE_HASH_ATOM(atom,obj,pobj) \
+ PROPERTY_CACHE_HASH((jsuword)(atom) >> 2, OBJ_SHAPE(obj))
+
+/*
+ * Property cache value capability macros.
+ */
+#define PCVCAP_PROTOBITS 4
+#define PCVCAP_PROTOSIZE JS_BIT(PCVCAP_PROTOBITS)
+#define PCVCAP_PROTOMASK JS_BITMASK(PCVCAP_PROTOBITS)
+
+#define PCVCAP_SCOPEBITS 4
+#define PCVCAP_SCOPESIZE JS_BIT(PCVCAP_SCOPEBITS)
+#define PCVCAP_SCOPEMASK JS_BITMASK(PCVCAP_SCOPEBITS)
+
+#define PCVCAP_TAGBITS (PCVCAP_PROTOBITS + PCVCAP_SCOPEBITS)
+#define PCVCAP_TAGMASK JS_BITMASK(PCVCAP_TAGBITS)
+#define PCVCAP_TAG(t) ((t) & PCVCAP_TAGMASK)
+
+#define PCVCAP_MAKE(t,s,p) (((t) << PCVCAP_TAGBITS) | \
+ ((s) << PCVCAP_PROTOBITS) | \
+ (p))
+#define PCVCAP_SHAPE(t) ((t) >> PCVCAP_TAGBITS)
+
+#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS)
+
+/*
+ * When sprop is not null and the shape generation triggers the GC due to a
+ * shape overflow, the functions roots sprop.
+ */
+extern uint32
+js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop);
+
+struct JSPropCacheEntry {
+ jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */
+ jsuword kshape; /* key shape if pc, else obj for atom */
+ jsuword vcap; /* value capability, see above */
+ jsuword vword; /* value word, see PCVAL_* below */
+};
+
+#if defined DEBUG_brendan || defined DEBUG_brendaneich
+#define JS_PROPERTY_CACHE_METERING 1
+#endif
+
+typedef struct JSPropertyCache {
+ JSPropCacheEntry table[PROPERTY_CACHE_SIZE];
+ JSBool empty;
+ jsrefcount disabled; /* signed for anti-underflow asserts */
+#ifdef JS_PROPERTY_CACHE_METERING
+ uint32 fills; /* number of cache entry fills */
+ uint32 nofills; /* couldn't fill (e.g. default get) */
+ uint32 rofills; /* set on read-only prop can't fill */
+ uint32 disfills; /* fill attempts on disabled cache */
+ uint32 oddfills; /* fill attempt after setter deleted */
+ uint32 modfills; /* fill that rehashed to a new entry */
+ uint32 brandfills; /* scope brandings to type structural
+ method fills */
+ uint32 noprotos; /* resolve-returned non-proto pobj */
+ uint32 longchains; /* overlong scope and/or proto chain */
+ uint32 recycles; /* cache entries recycled by fills */
+ uint32 pcrecycles; /* pc-keyed entries recycled by atom-
+ keyed fills */
+ uint32 tests; /* cache probes */
+ uint32 pchits; /* fast-path polymorphic op hits */
+ uint32 protopchits; /* pchits hitting immediate prototype */
+ uint32 initests; /* cache probes from JSOP_INITPROP */
+ uint32 inipchits; /* init'ing next property pchit case */
+ uint32 inipcmisses; /* init'ing next property pc misses */
+ uint32 settests; /* cache probes from JOF_SET opcodes */
+ uint32 addpchits; /* adding next property pchit case */
+ uint32 setpchits; /* setting existing property pchit */
+ uint32 setpcmisses; /* setting/adding property pc misses */
+ uint32 slotchanges; /* clasp->reserveSlots result variance-
+ induced slot changes */
+ uint32 setmisses; /* JSOP_SET{NAME,PROP} total misses */
+ uint32 idmisses; /* slow-path key id == atom misses */
+ uint32 komisses; /* slow-path key object misses */
+ uint32 vcmisses; /* value capability misses */
+ uint32 misses; /* cache misses */
+ uint32 flushes; /* cache flushes */
+ uint32 pcpurges; /* shadowing purges on proto chain */
+# define PCMETER(x) x
+#else
+# define PCMETER(x) ((void)0)
+#endif
+} JSPropertyCache;
+
+/*
+ * Property cache value tagging/untagging macros.
+ */
+#define PCVAL_OBJECT 0
+#define PCVAL_SLOT 1
+#define PCVAL_SPROP 2
+
+#define PCVAL_TAGBITS 2
+#define PCVAL_TAGMASK JS_BITMASK(PCVAL_TAGBITS)
+#define PCVAL_TAG(v) ((v) & PCVAL_TAGMASK)
+#define PCVAL_CLRTAG(v) ((v) & ~(jsuword)PCVAL_TAGMASK)
+#define PCVAL_SETTAG(v,t) ((jsuword)(v) | (t))
+
+#define PCVAL_NULL 0
+#define PCVAL_IS_NULL(v) ((v) == PCVAL_NULL)
+
+#define PCVAL_IS_OBJECT(v) (PCVAL_TAG(v) == PCVAL_OBJECT)
+#define PCVAL_TO_OBJECT(v) ((JSObject *) (v))
+#define OBJECT_TO_PCVAL(obj) ((jsuword) (obj))
+
+#define PCVAL_OBJECT_TO_JSVAL(v) OBJECT_TO_JSVAL(PCVAL_TO_OBJECT(v))
+#define JSVAL_OBJECT_TO_PCVAL(v) OBJECT_TO_PCVAL(JSVAL_TO_OBJECT(v))
+
+#define PCVAL_IS_SLOT(v) ((v) & PCVAL_SLOT)
+#define PCVAL_TO_SLOT(v) ((jsuint)(v) >> 1)
+#define SLOT_TO_PCVAL(i) (((jsuword)(i) << 1) | PCVAL_SLOT)
+
+#define PCVAL_IS_SPROP(v) (PCVAL_TAG(v) == PCVAL_SPROP)
+#define PCVAL_TO_SPROP(v) ((JSScopeProperty *) PCVAL_CLRTAG(v))
+#define SPROP_TO_PCVAL(sprop) PCVAL_SETTAG(sprop, PCVAL_SPROP)
+
+/*
+ * Fill property cache entry for key cx->fp->pc, optimized value word computed
+ * from obj and sprop, and entry capability forged from 24-bit OBJ_SHAPE(obj),
+ * 4-bit scopeIndex, and 4-bit protoIndex.
+ */
+extern void
+js_FillPropertyCache(JSContext *cx, JSObject *obj, jsuword kshape,
+ uintN scopeIndex, uintN protoIndex,
+ JSObject *pobj, JSScopeProperty *sprop,
+ JSPropCacheEntry **entryp);
+
+/*
+ * Property cache lookup macros. PROPERTY_CACHE_TEST is designed to inline the
+ * fast path in js_Interpret, so it makes "just-so" restrictions on parameters,
+ * e.g. pobj and obj should not be the same variable, since for JOF_PROP-mode
+ * opcodes, obj must not be changed because of a cache miss.
+ *
+ * On return from PROPERTY_CACHE_TEST, if atom is null then obj points to the
+ * scope chain element in which the property was found, pobj is locked, and
+ * entry is valid. If atom is non-null then no object is locked but entry is
+ * still set correctly for use, e.g., by js_FillPropertyCache and atom should
+ * be used as the id to find.
+ *
+ * We must lock pobj on a hit in order to close races with threads that might
+ * be deleting a property from its scope, or otherwise invalidating property
+ * caches (on all threads) by re-generating scope->shape.
+ */
+#define PROPERTY_CACHE_TEST(cx, pc, obj, pobj, entry, atom) \
+ do { \
+ JSPropertyCache *cache_ = &JS_PROPERTY_CACHE(cx); \
+ uint32 kshape_ = (JS_ASSERT(OBJ_IS_NATIVE(obj)), OBJ_SHAPE(obj)); \
+ entry = &cache_->table[PROPERTY_CACHE_HASH_PC(pc, kshape_)]; \
+ PCMETER(cache_->tests++); \
+ JS_ASSERT(&obj != &pobj); \
+ if (entry->kpc == pc && entry->kshape == kshape_) { \
+ JSObject *tmp_; \
+ pobj = obj; \
+ JS_LOCK_OBJ(cx, pobj); \
+ JS_ASSERT(PCVCAP_TAG(entry->vcap) <= 1); \
+ if (PCVCAP_TAG(entry->vcap) == 1 && \
+ (tmp_ = LOCKED_OBJ_GET_PROTO(pobj)) != NULL && \
+ OBJ_IS_NATIVE(tmp_)) { \
+ JS_UNLOCK_OBJ(cx, pobj); \
+ pobj = tmp_; \
+ JS_LOCK_OBJ(cx, pobj); \
+ } \
+ if (PCVCAP_SHAPE(entry->vcap) == OBJ_SHAPE(pobj)) { \
+ PCMETER(cache_->pchits++); \
+ PCMETER(!PCVCAP_TAG(entry->vcap) || cache_->protopchits++); \
+ pobj = OBJ_SCOPE(pobj)->object; \
+ atom = NULL; \
+ break; \
+ } \
+ JS_UNLOCK_OBJ(cx, pobj); \
+ } \
+ atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, &entry); \
+ if (atom) \
+ PCMETER(cache_->misses++); \
+ } while (0)
+
+extern JSAtom *
+js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc,
+ JSObject **objp, JSObject **pobjp,
+ JSPropCacheEntry **entryp);
+
+extern void
+js_FlushPropertyCache(JSContext *cx);
+
+extern void
+js_FlushPropertyCacheForScript(JSContext *cx, JSScript *script);
+
+extern void
+js_DisablePropertyCache(JSContext *cx);
+
+extern void
+js_EnablePropertyCache(JSContext *cx);
+
+/*
+ * Interpreter stack arena-pool alloc and free functions.
+ */
+extern JS_FRIEND_API(jsval *)
+js_AllocStack(JSContext *cx, uintN nslots, void **markp);
+
+extern JS_FRIEND_API(void)
+js_FreeStack(JSContext *cx, void *mark);
+
+/*
+ * Refresh and return fp->scopeChain. It may be stale if block scopes are
+ * active but not yet reflected by objects in the scope chain. If a block
+ * scope contains a with, eval, XML filtering predicate, or similar such
+ * dynamically scoped construct, then compile-time block scope at fp->blocks
+ * must reflect at runtime.
+ */
+extern JSObject *
+js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Given a context and a vector of [callee, this, args...] for a function that
+ * was specified with a JSFUN_THISP_PRIMITIVE flag, get the primitive value of
+ * |this| into *thisvp. In doing so, if |this| is an object, insist it is an
+ * instance of clasp and extract its private slot value to return via *thisvp.
+ *
+ * NB: this function loads and uses *vp before storing *thisvp, so the two may
+ * alias the same jsval.
+ */
+extern JSBool
+js_GetPrimitiveThis(JSContext *cx, jsval *vp, JSClass *clasp, jsval *thisvp);
+
+/*
+ * For a call with arguments argv including argv[-1] (nominal |this|) and
+ * argv[-2] (callee) replace null |this| with callee's parent, replace
+ * primitive values with the equivalent wrapper objects and censor activation
+ * objects as, per ECMA-262, they may not be referred to by |this|. argv[-1]
+ * must not be a JSVAL_VOID.
+ */
+extern JSObject *
+js_ComputeThis(JSContext *cx, JSBool lazy, jsval *argv);
+
+extern const uint16 js_PrimitiveTestFlags[];
+
+#define PRIMITIVE_THIS_TEST(fun,thisv) \
+ (JS_ASSERT(!JSVAL_IS_VOID(thisv)), \
+ JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \
+ js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1]))
+
+/*
+ * NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp
+ * is non-null), and that vp points to the callee, |this| parameter, and
+ * actual arguments of the call. [vp .. vp + 2 + argc) must belong to the last
+ * JS stack segment that js_AllocStack allocated. The function may use the
+ * space available after vp + 2 + argc in the stack segment for temporaries,
+ * so the caller should not use that space for values that must be preserved
+ * across the call.
+ */
+extern JS_FRIEND_API(JSBool)
+js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags);
+
+/*
+ * Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
+ * we can share bits stored in JSStackFrame.flags and passed to:
+ *
+ * js_Invoke
+ * js_InternalInvoke
+ * js_ValueToFunction
+ * js_ValueToFunctionObject
+ * js_ValueToCallableObject
+ * js_ReportIsNotFunction
+ *
+ * See jsfun.h for the latter four and flag renaming macros.
+ */
+#define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING
+#define JSINVOKE_ITERATOR JSFRAME_ITERATOR
+
+/*
+ * Mask to isolate construct and iterator flags for use with jsfun.h functions.
+ */
+#define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR)
+
+/*
+ * "Internal" calls may come from C or C++ code using a JSContext on which no
+ * JS is running (!cx->fp), so they may need to push a dummy JSStackFrame.
+ */
+#define js_InternalCall(cx,obj,fval,argc,argv,rval) \
+ js_InternalInvoke(cx, obj, fval, 0, argc, argv, rval)
+
+#define js_InternalConstruct(cx,obj,fval,argc,argv,rval) \
+ js_InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval)
+
+extern JSBool
+js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
+ uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
+ JSAccessMode mode, uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
+ JSStackFrame *down, uintN flags, jsval *result);
+
+extern JSBool
+js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp);
+
+extern JSBool
+js_Interpret(JSContext *cx);
+
+#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
+
+extern JSBool
+js_CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
+ JSObject **objp, JSProperty **propp);
+
+extern JSBool
+js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval);
+
+/*
+ * JS_LONE_INTERPRET indicates that the compiler should see just the code for
+ * the js_Interpret function when compiling jsinterp.cpp. The rest of the code
+ * from the file should be visible only when compiling jsinvoke.cpp. It allows
+ * platform builds to optimize selectively js_Interpret when the granularity
+ * of the optimizations with the given compiler is a compilation unit.
+ *
+ * JS_STATIC_INTERPRET is the modifier for functions defined in jsinterp.cpp
+ * that only js_Interpret calls. When JS_LONE_INTERPRET is true all such
+ * functions are declared below.
+ */
+#ifndef JS_LONE_INTERPRET
+# ifdef _MSC_VER
+# define JS_LONE_INTERPRET 0
+# else
+# define JS_LONE_INTERPRET 1
+# endif
+#endif
+
+#if !JS_LONE_INTERPRET
+# define JS_STATIC_INTERPRET static
+#else
+# define JS_STATIC_INTERPRET
+
+extern jsval *
+js_AllocRawStack(JSContext *cx, uintN nslots, void **markp);
+
+extern void
+js_FreeRawStack(JSContext *cx, void *mark);
+
+/*
+ * ECMA requires "the global object", but in embeddings such as the browser,
+ * which have multiple top-level objects (windows, frames, etc. in the DOM),
+ * we prefer fun's parent. An example that causes this code to run:
+ *
+ * // in window w1
+ * function f() { return this }
+ * function g() { return f }
+ *
+ * // in window w2
+ * var h = w1.g()
+ * alert(h() == w1)
+ *
+ * The alert should display "true".
+ */
+extern JSObject *
+js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv);
+
+extern JSBool
+js_EnterWith(JSContext *cx, jsint stackIndex);
+
+extern void
+js_LeaveWith(JSContext *cx);
+
+extern JSClass *
+js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
+
+extern jsint
+js_CountWithBlocks(JSContext *cx, JSStackFrame *fp);
+
+/*
+ * Unwind block and scope chains to match the given depth. The function sets
+ * fp->sp on return to stackDepth.
+ */
+extern JSBool
+js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth,
+ JSBool normalUnwind);
+
+extern JSBool
+js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp);
+
+extern JSBool
+js_OnUnknownMethod(JSContext *cx, jsval *vp);
+
+/*
+ * Find the results of incrementing or decrementing *vp. For pre-increments,
+ * both *vp and *vp2 will contain the result on return. For post-increments,
+ * vp will contain the original value converted to a number and vp2 will get
+ * the result. Both vp and vp2 must be roots.
+ */
+extern JSBool
+js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2);
+
+/*
+ * Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
+ * previous opcode.
+ */
+extern void
+js_TraceOpcode(JSContext *cx, jsint len);
+
+/*
+ * JS_OPMETER helper functions.
+ */
+extern void
+js_MeterOpcodePair(JSOp op1, JSOp op2);
+
+extern void
+js_MeterSlotOpcode(JSOp op, uint32 slot);
+
+#endif /* JS_LONE_INTERPRET */
+
+JS_END_EXTERN_C
+
+#endif /* jsinterp_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp
new file mode 100644
index 0000000..893813e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsinvoke.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.8 code, released
+ * March 4, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Igor Bukanov <igor@mir2.org>
+ *
+ * Contributor(s):
+ * Brendan Eich <brendan@mozilla.org
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define jsinvoke_cpp___
+
+#include "jsinterp.cpp"
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp
new file mode 100644
index 0000000..c662045
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.cpp
@@ -0,0 +1,1050 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript iterators.
+ */
+#include "jsstddef.h"
+#include <string.h> /* for memcpy */
+#include "jstypes.h"
+#include "jsutil.h"
+#include "jsarena.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsexn.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#if JSSLOT_ITER_FLAGS >= JS_INITIAL_NSLOTS
+#error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS.
+#endif
+
+#if JS_HAS_GENERATORS
+
+static JSBool
+CloseGenerator(JSContext *cx, JSObject *genobj);
+
+#endif
+
+/*
+ * Shared code to close iterator's state either through an explicit call or
+ * when GC detects that the iterator is no longer reachable.
+ */
+void
+js_CloseNativeIterator(JSContext *cx, JSObject *iterobj)
+{
+ jsval state;
+ JSObject *iterable;
+
+ JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);
+
+ /* Avoid double work if js_CloseNativeIterator was called on obj. */
+ state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE);
+ if (JSVAL_IS_NULL(state))
+ return;
+
+ /* Protect against failure to fully initialize obj. */
+ iterable = STOBJ_GET_PARENT(iterobj);
+ if (iterable) {
+#if JS_HAS_XML_SUPPORT
+ uintN flags = JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
+ if ((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, iterable)) {
+ ((JSXMLObjectOps *) iterable->map->ops)->
+ enumerateValues(cx, iterable, JSENUMERATE_DESTROY, &state,
+ NULL, NULL);
+ } else
+#endif
+ OBJ_ENUMERATE(cx, iterable, JSENUMERATE_DESTROY, &state, NULL);
+ }
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, JSVAL_NULL);
+}
+
+JSClass js_IteratorClass = {
+ "Iterator",
+ JSCLASS_HAS_RESERVED_SLOTS(2) | /* slots for state and flags */
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+InitNativeIterator(JSContext *cx, JSObject *iterobj, JSObject *obj, uintN flags)
+{
+ jsval state;
+ JSBool ok;
+
+ JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);
+
+ /* Initialize iterobj in case of enumerate hook failure. */
+ STOBJ_SET_PARENT(iterobj, obj);
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, JSVAL_NULL);
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_FLAGS, INT_TO_JSVAL(flags));
+ if (!js_RegisterCloseableIterator(cx, iterobj))
+ return JS_FALSE;
+ if (!obj)
+ return JS_TRUE;
+
+ ok =
+#if JS_HAS_XML_SUPPORT
+ ((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, obj))
+ ? ((JSXMLObjectOps *) obj->map->ops)->
+ enumerateValues(cx, obj, JSENUMERATE_INIT, &state, NULL, NULL)
+ :
+#endif
+ OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL);
+ if (!ok)
+ return JS_FALSE;
+
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (flags & JSITER_ENUMERATE) {
+ /*
+ * The enumerating iterator needs the original object to suppress
+ * enumeration of deleted or shadowed prototype properties. Since the
+ * enumerator never escapes to scripts, we use the prototype slot to
+ * store the original object.
+ */
+ JS_ASSERT(obj != iterobj);
+ STOBJ_SET_PROTO(iterobj, obj);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+Iterator(JSContext *cx, JSObject *iterobj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSBool keyonly;
+ uintN flags;
+ JSObject *obj;
+
+ keyonly = js_ValueToBoolean(argv[1]);
+ flags = keyonly ? 0 : JSITER_FOREACH;
+
+ if (cx->fp->flags & JSFRAME_CONSTRUCTING) {
+ /* XXX work around old valueOf call hidden beneath js_ValueToObject */
+ if (!JSVAL_IS_PRIMITIVE(argv[0])) {
+ obj = JSVAL_TO_OBJECT(argv[0]);
+ } else {
+ obj = js_ValueToNonNullObject(cx, argv[0]);
+ if (!obj)
+ return JS_FALSE;
+ argv[0] = OBJECT_TO_JSVAL(obj);
+ }
+ return InitNativeIterator(cx, iterobj, obj, flags);
+ }
+
+ *rval = argv[0];
+ return js_ValueToIterator(cx, flags, rval);
+}
+
+static JSBool
+NewKeyValuePair(JSContext *cx, jsid key, jsval val, jsval *rval)
+{
+ jsval vec[2];
+ JSTempValueRooter tvr;
+ JSObject *aobj;
+
+ vec[0] = ID_TO_VALUE(key);
+ vec[1] = val;
+
+ JS_PUSH_TEMP_ROOT(cx, 2, vec, &tvr);
+ aobj = js_NewArrayObject(cx, 2, vec);
+ *rval = OBJECT_TO_JSVAL(aobj);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+
+ return aobj != NULL;
+}
+
+static JSBool
+IteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval)
+{
+ JSObject *iterable;
+ jsval state;
+ uintN flags;
+ JSBool foreach, ok;
+ jsid id;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_IteratorClass);
+
+ iterable = OBJ_GET_PARENT(cx, obj);
+ JS_ASSERT(iterable);
+ state = STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+
+ flags = JSVAL_TO_INT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_FLAGS));
+ JS_ASSERT(!(flags & JSITER_ENUMERATE));
+ foreach = (flags & JSITER_FOREACH) != 0;
+ ok =
+#if JS_HAS_XML_SUPPORT
+ (foreach && OBJECT_IS_XML(cx, iterable))
+ ? ((JSXMLObjectOps *) iterable->map->ops)->
+ enumerateValues(cx, iterable, JSENUMERATE_NEXT, &state,
+ &id, rval)
+ :
+#endif
+ OBJ_ENUMERATE(cx, iterable, JSENUMERATE_NEXT, &state, &id);
+ if (!ok)
+ return JS_FALSE;
+
+ STOBJ_SET_SLOT(obj, JSSLOT_ITER_STATE, state);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+
+ if (foreach) {
+#if JS_HAS_XML_SUPPORT
+ if (!OBJECT_IS_XML(cx, iterable) &&
+ !OBJ_GET_PROPERTY(cx, iterable, id, rval)) {
+ return JS_FALSE;
+ }
+#endif
+ if (!NewKeyValuePair(cx, id, *rval, rval))
+ return JS_FALSE;
+ } else {
+ *rval = ID_TO_VALUE(id);
+ }
+ return JS_TRUE;
+
+ stop:
+ JS_ASSERT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE) == JSVAL_NULL);
+ *rval = JSVAL_HOLE;
+ return JS_TRUE;
+}
+
+JSBool
+js_ThrowStopIteration(JSContext *cx)
+{
+ jsval v;
+
+ JS_ASSERT(!JS_IsExceptionPending(cx));
+ if (js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_StopIteration), &v))
+ JS_SetPendingException(cx, v);
+ return JS_FALSE;
+}
+
+static JSBool
+iterator_next(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_IteratorClass, vp + 2))
+ return JS_FALSE;
+
+ if (!IteratorNextImpl(cx, obj, vp))
+ return JS_FALSE;
+
+ if (*vp == JSVAL_HOLE) {
+ *vp = JSVAL_NULL;
+ js_ThrowStopIteration(cx);
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+iterator_self(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = JS_THIS(cx, vp);
+ return !JSVAL_IS_NULL(*vp);
+}
+
+#define JSPROP_ROPERM (JSPROP_READONLY | JSPROP_PERMANENT)
+
+static JSFunctionSpec iterator_methods[] = {
+ JS_FN(js_iterator_str, iterator_self, 0,JSPROP_ROPERM),
+ JS_FN(js_next_str, iterator_next, 0,JSPROP_ROPERM),
+ JS_FS_END
+};
+
+uintN
+js_GetNativeIteratorFlags(JSContext *cx, JSObject *iterobj)
+{
+ if (OBJ_GET_CLASS(cx, iterobj) != &js_IteratorClass)
+ return 0;
+ return JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
+}
+
+/*
+ * Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists.
+ * Otherwise construct the default iterator.
+ */
+JS_FRIEND_API(JSBool)
+js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
+{
+ JSObject *obj;
+ JSTempValueRooter tvr;
+ JSAtom *atom;
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSBool ok;
+ JSObject *iterobj;
+ jsval arg;
+
+ JS_ASSERT(!(flags & ~(JSITER_ENUMERATE |
+ JSITER_FOREACH |
+ JSITER_KEYVALUE)));
+
+ /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
+ JS_ASSERT(!(flags & JSITER_KEYVALUE) || (flags & JSITER_FOREACH));
+
+ /* XXX work around old valueOf call hidden beneath js_ValueToObject */
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ obj = JSVAL_TO_OBJECT(*vp);
+ } else {
+ /*
+ * Enumerating over null and undefined gives an empty enumerator.
+ * This is contrary to ECMA-262 9.9 ToObject, invoked from step 3 of
+ * the first production in 12.6.4 and step 4 of the second production,
+ * but it's "web JS" compatible.
+ */
+ if ((flags & JSITER_ENUMERATE)) {
+ if (!js_ValueToObject(cx, *vp, &obj))
+ return JS_FALSE;
+ if (!obj)
+ goto default_iter;
+ } else {
+ obj = js_ValueToNonNullObject(cx, *vp);
+ if (!obj)
+ return JS_FALSE;
+ }
+ }
+
+ JS_ASSERT(obj);
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if ((clasp->flags & JSCLASS_IS_EXTENDED) &&
+ (xclasp = (JSExtendedClass *) clasp)->iteratorObject) {
+ iterobj = xclasp->iteratorObject(cx, obj, !(flags & JSITER_FOREACH));
+ if (!iterobj)
+ goto bad;
+ *vp = OBJECT_TO_JSVAL(iterobj);
+ } else {
+ atom = cx->runtime->atomState.iteratorAtom;
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ if (!js_GetXMLFunction(cx, obj, ATOM_TO_JSID(atom), vp))
+ goto bad;
+ } else
+#endif
+ {
+ if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp))
+ goto bad;
+ }
+
+ if (JSVAL_IS_VOID(*vp)) {
+ default_iter:
+ /*
+ * Fail over to the default enumerating native iterator.
+ *
+ * Create iterobj with a NULL parent to ensure that we use the
+ * correct scope chain to lookup the iterator's constructor. Since
+ * we use the parent slot to keep track of the iterable, we must
+ * fix it up after.
+ */
+ iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL, 0);
+ if (!iterobj)
+ goto bad;
+
+ /* Store in *vp to protect it from GC (callers must root vp). */
+ *vp = OBJECT_TO_JSVAL(iterobj);
+
+ if (!InitNativeIterator(cx, iterobj, obj, flags))
+ goto bad;
+ } else {
+ arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
+ if (!js_InternalInvoke(cx, obj, *vp, JSINVOKE_ITERATOR, 1, &arg,
+ vp)) {
+ goto bad;
+ }
+ if (JSVAL_IS_PRIMITIVE(*vp)) {
+ const char *printable = js_AtomToPrintableString(cx, atom);
+ if (printable) {
+ js_ReportValueError2(cx, JSMSG_BAD_ITERATOR_RETURN,
+ JSDVG_SEARCH_STACK, *vp, NULL,
+ printable);
+ }
+ goto bad;
+ }
+ }
+ }
+
+ ok = JS_TRUE;
+ out:
+ if (obj)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+ bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+JS_FRIEND_API(JSBool) JS_FASTCALL
+js_CloseIterator(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSClass *clasp;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ obj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, obj);
+
+ if (clasp == &js_IteratorClass) {
+ js_CloseNativeIterator(cx, obj);
+ }
+#if JS_HAS_GENERATORS
+ else if (clasp == &js_GeneratorClass) {
+ if (!CloseGenerator(cx, obj))
+ return JS_FALSE;
+ }
+#endif
+ return JS_TRUE;
+}
+
+static JSBool
+CallEnumeratorNext(JSContext *cx, JSObject *iterobj, uintN flags, jsval *rval)
+{
+ JSObject *obj, *origobj;
+ jsval state;
+ JSBool foreach;
+ jsid id;
+ JSObject *obj2;
+ JSBool cond;
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSProperty *prop;
+ JSString *str;
+
+ JS_ASSERT(flags & JSITER_ENUMERATE);
+ JS_ASSERT(STOBJ_GET_CLASS(iterobj) == &js_IteratorClass);
+
+ obj = STOBJ_GET_PARENT(iterobj);
+ origobj = STOBJ_GET_PROTO(iterobj);
+ state = STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+
+ foreach = (flags & JSITER_FOREACH) != 0;
+#if JS_HAS_XML_SUPPORT
+ /*
+ * Treat an XML object specially only when it starts the prototype chain.
+ * Otherwise we need to do the usual deleted and shadowed property checks.
+ */
+ if (obj == origobj && OBJECT_IS_XML(cx, obj)) {
+ if (foreach) {
+ JSXMLObjectOps *xmlops = (JSXMLObjectOps *) obj->map->ops;
+
+ if (!xmlops->enumerateValues(cx, obj, JSENUMERATE_NEXT, &state,
+ &id, rval)) {
+ return JS_FALSE;
+ }
+ } else {
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &state, &id))
+ return JS_FALSE;
+ }
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (JSVAL_IS_NULL(state))
+ goto stop;
+ } else
+#endif
+ {
+ restart:
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_NEXT, &state, &id))
+ return JS_FALSE;
+
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (JSVAL_IS_NULL(state)) {
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ /*
+ * We just finished enumerating an XML obj that is present on
+ * the prototype chain of a non-XML origobj. Stop further
+ * prototype chain searches because XML objects don't
+ * enumerate prototypes.
+ */
+ JS_ASSERT(origobj != obj);
+ JS_ASSERT(!OBJECT_IS_XML(cx, origobj));
+ } else
+#endif
+ {
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (obj) {
+ STOBJ_SET_PARENT(iterobj, obj);
+ if (!OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL))
+ return JS_FALSE;
+ STOBJ_SET_SLOT(iterobj, JSSLOT_ITER_STATE, state);
+ if (!JSVAL_IS_NULL(state))
+ goto restart;
+ }
+ }
+ goto stop;
+ }
+
+ /* Skip properties not in obj when looking from origobj. */
+ if (!OBJ_LOOKUP_PROPERTY(cx, origobj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop)
+ goto restart;
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+
+ /*
+ * If the id was found in a prototype object or an unrelated object
+ * (specifically, not in an inner object for obj), skip it. This step
+ * means that all OBJ_LOOKUP_PROPERTY implementations must return an
+ * object further along on the prototype chain, or else possibly an
+ * object returned by the JSExtendedClass.outerObject optional hook.
+ */
+ if (obj != obj2) {
+ cond = JS_FALSE;
+ clasp = OBJ_GET_CLASS(cx, obj2);
+ if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ xclasp = (JSExtendedClass *) clasp;
+ cond = xclasp->outerObject &&
+ xclasp->outerObject(cx, obj2) == obj;
+ }
+ if (!cond)
+ goto restart;
+ }
+
+ if (foreach) {
+ /* Get property querying the original object. */
+ if (!OBJ_GET_PROPERTY(cx, origobj, id, rval))
+ return JS_FALSE;
+ }
+ }
+
+ if (foreach) {
+ if (flags & JSITER_KEYVALUE) {
+ if (!NewKeyValuePair(cx, id, *rval, rval))
+ return JS_FALSE;
+ }
+ } else {
+ /* Make rval a string for uniformity and compatibility. */
+ str = js_ValueToString(cx, ID_TO_VALUE(id));
+ if (!str)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL(str);
+ }
+ return JS_TRUE;
+
+ stop:
+ JS_ASSERT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_STATE) == JSVAL_NULL);
+ *rval = JSVAL_HOLE;
+ return JS_TRUE;
+}
+
+JS_FRIEND_API(JSBool)
+js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval)
+{
+ uintN flags;
+
+ /* Fast path for native iterators */
+ if (OBJ_GET_CLASS(cx, iterobj) == &js_IteratorClass) {
+ flags = JSVAL_TO_INT(STOBJ_GET_SLOT(iterobj, JSSLOT_ITER_FLAGS));
+ if (flags & JSITER_ENUMERATE)
+ return CallEnumeratorNext(cx, iterobj, flags, rval);
+
+ /*
+ * Call next directly as all the methods of the native iterator are
+ * read-only and permanent.
+ */
+ if (!IteratorNextImpl(cx, iterobj, rval))
+ return JS_FALSE;
+ } else {
+ jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);
+
+ if (!JS_GetMethodById(cx, iterobj, id, &iterobj, rval))
+ return JS_FALSE;
+ if (!js_InternalCall(cx, iterobj, *rval, 0, NULL, rval)) {
+ /* Check for StopIteration. */
+ if (!cx->throwing || !js_ValueIsStopIteration(cx->exception))
+ return JS_FALSE;
+
+ /* Inline JS_ClearPendingException(cx). */
+ cx->throwing = JS_FALSE;
+ cx->exception = JSVAL_VOID;
+ *rval = JSVAL_HOLE;
+ return JS_TRUE;
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+stopiter_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ *bp = js_ValueIsStopIteration(v);
+ return JS_TRUE;
+}
+
+JSClass js_StopIterationClass = {
+ js_StopIteration_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_StopIteration),
+ JS_PropertyStub, JS_PropertyStub,
+ JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub,
+ JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, stopiter_hasInstance,
+ NULL, NULL
+};
+
+#if JS_HAS_GENERATORS
+
+static void
+generator_finalize(JSContext *cx, JSObject *obj)
+{
+ JSGenerator *gen;
+
+ gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+ if (gen) {
+ /*
+ * gen can be open on shutdown when close hooks are ignored or when
+ * the embedding cancels scheduled close hooks.
+ */
+ JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_CLOSED ||
+ gen->state == JSGEN_OPEN);
+ JS_free(cx, gen);
+ }
+}
+
+static void
+generator_trace(JSTracer *trc, JSObject *obj)
+{
+ JSGenerator *gen;
+
+ gen = (JSGenerator *) JS_GetPrivate(trc->context, obj);
+ if (!gen)
+ return;
+
+ /*
+ * js_TraceStackFrame does not recursively trace the down-linked frame
+ * chain, so we insist that gen->frame has no parent to trace when the
+ * generator is not running.
+ */
+ JS_ASSERT_IF(gen->state != JSGEN_RUNNING && gen->state != JSGEN_CLOSING,
+ !gen->frame.down);
+
+ /*
+ * FIXME be 390950. Generator's frame is a part of the JS stack when the
+ * generator is running or closing. Thus tracing the frame in this case
+ * here duplicates the work done in js_TraceContext.
+ */
+ js_TraceStackFrame(trc, &gen->frame);
+}
+
+JSClass js_GeneratorClass = {
+ js_Generator_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_IS_ANONYMOUS |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Generator),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, generator_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(generator_trace), NULL
+};
+
+/*
+ * Called from the JSOP_GENERATOR case in the interpreter, with fp referring
+ * to the frame by which the generator function was activated. Create a new
+ * JSGenerator object, which contains its own JSStackFrame that we populate
+ * from *fp. We know that upon return, the JSOP_GENERATOR opcode will return
+ * from the activation in fp, so we can steal away fp->callobj and fp->argsobj
+ * if they are non-null.
+ */
+JSObject *
+js_NewGenerator(JSContext *cx, JSStackFrame *fp)
+{
+ JSObject *obj;
+ uintN argc, nargs, nslots;
+ JSGenerator *gen;
+ jsval *slots;
+
+ /* After the following return, failing control flow must goto bad. */
+ obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+
+ /* Load and compute stack slot counts. */
+ argc = fp->argc;
+ nargs = JS_MAX(argc, fp->fun->nargs);
+ nslots = 2 + nargs + fp->script->nslots;
+
+ /* Allocate obj's private data struct. */
+ gen = (JSGenerator *)
+ JS_malloc(cx, sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval));
+ if (!gen)
+ goto bad;
+
+ gen->obj = obj;
+
+ /* Steal away objects reflecting fp and point them at gen->frame. */
+ gen->frame.callobj = fp->callobj;
+ if (fp->callobj) {
+ JS_SetPrivate(cx, fp->callobj, &gen->frame);
+ fp->callobj = NULL;
+ }
+ gen->frame.argsobj = fp->argsobj;
+ if (fp->argsobj) {
+ JS_SetPrivate(cx, fp->argsobj, &gen->frame);
+ fp->argsobj = NULL;
+ }
+
+ /* These two references can be shared with fp until it goes away. */
+ gen->frame.varobj = fp->varobj;
+ gen->frame.thisp = fp->thisp;
+
+ /* Copy call-invariant script and function references. */
+ gen->frame.script = fp->script;
+ gen->frame.callee = fp->callee;
+ gen->frame.fun = fp->fun;
+
+ /* Use slots to carve space out of gen->slots. */
+ slots = gen->slots;
+ gen->arena.next = NULL;
+ gen->arena.base = (jsuword) slots;
+ gen->arena.limit = gen->arena.avail = (jsuword) (slots + nslots);
+
+ /* Copy rval, argv and vars. */
+ gen->frame.rval = fp->rval;
+ memcpy(slots, fp->argv - 2, (2 + nargs) * sizeof(jsval));
+ gen->frame.argc = nargs;
+ gen->frame.argv = slots + 2;
+ slots += 2 + nargs;
+ memcpy(slots, fp->slots, fp->script->nfixed * sizeof(jsval));
+
+ /* Initialize or copy virtual machine state. */
+ gen->frame.down = NULL;
+ gen->frame.annotation = NULL;
+ gen->frame.scopeChain = fp->scopeChain;
+
+ gen->frame.imacpc = NULL;
+ gen->frame.slots = slots;
+ JS_ASSERT(StackBase(fp) == fp->regs->sp);
+ gen->savedRegs.sp = slots + fp->script->nfixed;
+ gen->savedRegs.pc = fp->regs->pc;
+ gen->frame.regs = &gen->savedRegs;
+
+ /* Copy remaining state (XXX sharp* and xml* should be local vars). */
+ gen->frame.sharpDepth = 0;
+ gen->frame.sharpArray = NULL;
+ gen->frame.flags = (fp->flags & ~JSFRAME_ROOTED_ARGV) | JSFRAME_GENERATOR;
+ gen->frame.dormantNext = NULL;
+ gen->frame.xmlNamespace = NULL;
+ gen->frame.blockChain = NULL;
+
+ /* Note that gen is newborn. */
+ gen->state = JSGEN_NEWBORN;
+
+ if (!JS_SetPrivate(cx, obj, gen)) {
+ JS_free(cx, gen);
+ goto bad;
+ }
+ return obj;
+
+ bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+}
+
+typedef enum JSGeneratorOp {
+ JSGENOP_NEXT,
+ JSGENOP_SEND,
+ JSGENOP_THROW,
+ JSGENOP_CLOSE
+} JSGeneratorOp;
+
+/*
+ * Start newborn or restart yielding generator and perform the requested
+ * operation inside its frame.
+ */
+static JSBool
+SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
+ JSGenerator *gen, jsval arg)
+{
+ JSStackFrame *fp;
+ JSArena *arena;
+ JSBool ok;
+
+ if (gen->state == JSGEN_RUNNING || gen->state == JSGEN_CLOSING) {
+ js_ReportValueError(cx, JSMSG_NESTING_GENERATOR,
+ JSDVG_SEARCH_STACK, OBJECT_TO_JSVAL(obj),
+ JS_GetFunctionId(gen->frame.fun));
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
+ switch (op) {
+ case JSGENOP_NEXT:
+ case JSGENOP_SEND:
+ if (gen->state == JSGEN_OPEN) {
+ /*
+ * Store the argument to send as the result of the yield
+ * expression.
+ */
+ gen->savedRegs.sp[-1] = arg;
+ }
+ gen->state = JSGEN_RUNNING;
+ break;
+
+ case JSGENOP_THROW:
+ JS_SetPendingException(cx, arg);
+ gen->state = JSGEN_RUNNING;
+ break;
+
+ default:
+ JS_ASSERT(op == JSGENOP_CLOSE);
+ JS_SetPendingException(cx, JSVAL_ARETURN);
+ gen->state = JSGEN_CLOSING;
+ break;
+ }
+
+ /* Extend the current stack pool with gen->arena. */
+ arena = cx->stackPool.current;
+ JS_ASSERT(!arena->next);
+ JS_ASSERT(!gen->arena.next);
+ JS_ASSERT(cx->stackPool.current != &gen->arena);
+ cx->stackPool.current = arena->next = &gen->arena;
+
+ /* Push gen->frame around the interpreter activation. */
+ fp = cx->fp;
+ cx->fp = &gen->frame;
+ gen->frame.down = fp;
+ ok = js_Interpret(cx);
+ cx->fp = fp;
+ gen->frame.down = NULL;
+
+ /* Retract the stack pool and sanitize gen->arena. */
+ JS_ASSERT(!gen->arena.next);
+ JS_ASSERT(arena->next == &gen->arena);
+ JS_ASSERT(cx->stackPool.current == &gen->arena);
+ cx->stackPool.current = arena;
+ arena->next = NULL;
+
+ if (gen->frame.flags & JSFRAME_YIELDING) {
+ /* Yield cannot fail, throw or be called on closing. */
+ JS_ASSERT(ok);
+ JS_ASSERT(!cx->throwing);
+ JS_ASSERT(gen->state == JSGEN_RUNNING);
+ JS_ASSERT(op != JSGENOP_CLOSE);
+ gen->frame.flags &= ~JSFRAME_YIELDING;
+ gen->state = JSGEN_OPEN;
+ return JS_TRUE;
+ }
+
+ gen->frame.rval = JSVAL_VOID;
+ gen->state = JSGEN_CLOSED;
+ if (ok) {
+ /* Returned, explicitly or by falling off the end. */
+ if (op == JSGENOP_CLOSE)
+ return JS_TRUE;
+ return js_ThrowStopIteration(cx);
+ }
+
+ /*
+ * An error, silent termination by operation callback or an exception.
+ * Propagate the condition to the caller.
+ */
+ return JS_FALSE;
+}
+
+static JSBool
+CloseGenerator(JSContext *cx, JSObject *obj)
+{
+ JSGenerator *gen;
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_GeneratorClass);
+ gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+ if (!gen) {
+ /* Generator prototype object. */
+ return JS_TRUE;
+ }
+
+ if (gen->state == JSGEN_CLOSED)
+ return JS_TRUE;
+
+ return SendToGenerator(cx, JSGENOP_CLOSE, obj, gen, JSVAL_VOID);
+}
+
+/*
+ * Common subroutine of generator_(next|send|throw|close) methods.
+ */
+static JSBool
+generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp, uintN argc)
+{
+ JSObject *obj;
+ JSGenerator *gen;
+ jsval arg;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
+ return JS_FALSE;
+
+ gen = (JSGenerator *) JS_GetPrivate(cx, obj);
+ if (gen == NULL) {
+ /* This happens when obj is the generator prototype. See bug 352885. */
+ goto closed_generator;
+ }
+
+ if (gen->state == JSGEN_NEWBORN) {
+ switch (op) {
+ case JSGENOP_NEXT:
+ case JSGENOP_THROW:
+ break;
+
+ case JSGENOP_SEND:
+ if (argc >= 1 && !JSVAL_IS_VOID(vp[2])) {
+ js_ReportValueError(cx, JSMSG_BAD_GENERATOR_SEND,
+ JSDVG_SEARCH_STACK, vp[2], NULL);
+ return JS_FALSE;
+ }
+ break;
+
+ default:
+ JS_ASSERT(op == JSGENOP_CLOSE);
+ gen->state = JSGEN_CLOSED;
+ return JS_TRUE;
+ }
+ } else if (gen->state == JSGEN_CLOSED) {
+ closed_generator:
+ switch (op) {
+ case JSGENOP_NEXT:
+ case JSGENOP_SEND:
+ return js_ThrowStopIteration(cx);
+ case JSGENOP_THROW:
+ JS_SetPendingException(cx, argc >= 1 ? vp[2] : JSVAL_VOID);
+ return JS_FALSE;
+ default:
+ JS_ASSERT(op == JSGENOP_CLOSE);
+ return JS_TRUE;
+ }
+ }
+
+ arg = ((op == JSGENOP_SEND || op == JSGENOP_THROW) && argc != 0)
+ ? vp[2]
+ : JSVAL_VOID;
+ if (!SendToGenerator(cx, op, obj, gen, arg))
+ return JS_FALSE;
+ *vp = gen->frame.rval;
+ return JS_TRUE;
+}
+
+static JSBool
+generator_send(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_SEND, vp, argc);
+}
+
+static JSBool
+generator_next(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_NEXT, vp, argc);
+}
+
+static JSBool
+generator_throw(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_THROW, vp, argc);
+}
+
+static JSBool
+generator_close(JSContext *cx, uintN argc, jsval *vp)
+{
+ return generator_op(cx, JSGENOP_CLOSE, vp, argc);
+}
+
+static JSFunctionSpec generator_methods[] = {
+ JS_FN(js_iterator_str, iterator_self, 0,JSPROP_ROPERM),
+ JS_FN(js_next_str, generator_next, 0,JSPROP_ROPERM),
+ JS_FN(js_send_str, generator_send, 1,JSPROP_ROPERM),
+ JS_FN(js_throw_str, generator_throw, 1,JSPROP_ROPERM),
+ JS_FN(js_close_str, generator_close, 0,JSPROP_ROPERM),
+ JS_FS_END
+};
+
+#endif /* JS_HAS_GENERATORS */
+
+JSObject *
+js_InitIteratorClasses(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *stop;
+
+ /* Idempotency required: we initialize several things, possibly lazily. */
+ if (!js_GetClassObject(cx, obj, JSProto_StopIteration, &stop))
+ return NULL;
+ if (stop)
+ return stop;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2,
+ NULL, iterator_methods, NULL, NULL);
+ if (!proto)
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_ITER_STATE, JSVAL_NULL);
+
+#if JS_HAS_GENERATORS
+ /* Initialize the generator internals if configured. */
+ if (!JS_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0,
+ NULL, generator_methods, NULL, NULL)) {
+ return NULL;
+ }
+#endif
+
+ return JS_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0,
+ NULL, NULL, NULL, NULL);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsiter.h b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.h
new file mode 100644
index 0000000..2a7bb16
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsiter.h
@@ -0,0 +1,140 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsiter_h___
+#define jsiter_h___
+
+/*
+ * JavaScript iterators.
+ */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * NB: these flag bits are encoded into the bytecode stream in the immediate
+ * operand of JSOP_ITER, so don't change them without advancing jsxdrapi.h's
+ * JSXDR_BYTECODE_VERSION.
+ */
+#define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */
+#define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */
+#define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */
+
+/*
+ * Native iterator object slots, shared between jsiter.cpp and jstracer.cpp.
+ */
+#define JSSLOT_ITER_STATE (JSSLOT_PRIVATE)
+#define JSSLOT_ITER_FLAGS (JSSLOT_PRIVATE + 1)
+
+/*
+ * Convert the value stored in *vp to its iteration object. The flags should
+ * contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating
+ * for-in semantics are required, and when the caller can guarantee that the
+ * iterator will never be exposed to scripts.
+ */
+extern JS_FRIEND_API(JSBool)
+js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp);
+
+extern JS_FRIEND_API(JSBool) JS_FASTCALL
+js_CloseIterator(JSContext *cx, jsval v);
+
+/*
+ * Given iterobj, call iterobj.next(). If the iterator stopped, set *rval to
+ * JSVAL_HOLE. Otherwise set it to the result of the next call.
+ */
+extern JS_FRIEND_API(JSBool)
+js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval);
+
+/*
+ * Close iterobj, whose class must be js_IteratorClass.
+ */
+extern void
+js_CloseNativeIterator(JSContext *cx, JSObject *iterobj);
+
+extern JSBool
+js_ThrowStopIteration(JSContext *cx);
+
+#if JS_HAS_GENERATORS
+
+/*
+ * Generator state codes.
+ */
+typedef enum JSGeneratorState {
+ JSGEN_NEWBORN, /* not yet started */
+ JSGEN_OPEN, /* started by a .next() or .send(undefined) call */
+ JSGEN_RUNNING, /* currently executing via .next(), etc., call */
+ JSGEN_CLOSING, /* close method is doing asynchronous return */
+ JSGEN_CLOSED /* closed, cannot be started or closed again */
+} JSGeneratorState;
+
+struct JSGenerator {
+ JSObject *obj;
+ JSGeneratorState state;
+ JSStackFrame frame;
+ JSFrameRegs savedRegs;
+ JSArena arena;
+ jsval slots[1];
+};
+
+#define FRAME_TO_GENERATOR(fp) \
+ ((JSGenerator *) ((uint8 *)(fp) - offsetof(JSGenerator, frame)))
+
+extern JSObject *
+js_NewGenerator(JSContext *cx, JSStackFrame *fp);
+
+#endif
+
+extern JSClass js_GeneratorClass;
+extern JSClass js_IteratorClass;
+extern JSClass js_StopIterationClass;
+
+static inline bool
+js_ValueIsStopIteration(jsval v)
+{
+ return !JSVAL_IS_PRIMITIVE(v) &&
+ STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v)) == &js_StopIterationClass;
+}
+
+extern JSObject *
+js_InitIteratorClasses(JSContext *cx, JSObject *obj);
+
+JS_END_EXTERN_C
+
+#endif /* jsiter_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl
new file mode 100644
index 0000000..adcbf0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jskeyword.tbl
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+JS_KEYWORD(break, TOK_BREAK, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(case, TOK_CASE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(continue, TOK_CONTINUE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(default, TOK_DEFAULT, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(delete, TOK_DELETE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(do, TOK_DO, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(else, TOK_ELSE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(export, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(false, TOK_PRIMARY, JSOP_FALSE, JSVERSION_DEFAULT)
+JS_KEYWORD(for, TOK_FOR, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(function, TOK_FUNCTION, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(if, TOK_IF, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(in, TOK_IN, JSOP_IN, JSVERSION_DEFAULT)
+JS_KEYWORD(new, TOK_NEW, JSOP_NEW, JSVERSION_DEFAULT)
+JS_KEYWORD(null, TOK_PRIMARY, JSOP_NULL, JSVERSION_DEFAULT)
+JS_KEYWORD(return, TOK_RETURN, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(switch, TOK_SWITCH, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(this, TOK_PRIMARY, JSOP_THIS, JSVERSION_DEFAULT)
+JS_KEYWORD(true, TOK_PRIMARY, JSOP_TRUE, JSVERSION_DEFAULT)
+JS_KEYWORD(typeof, TOK_UNARYOP, JSOP_TYPEOF, JSVERSION_DEFAULT)
+JS_KEYWORD(var, TOK_VAR, JSOP_DEFVAR, JSVERSION_DEFAULT)
+JS_KEYWORD(void, TOK_UNARYOP, JSOP_VOID, JSVERSION_DEFAULT)
+JS_KEYWORD(while, TOK_WHILE, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(with, TOK_WITH, JSOP_NOP, JSVERSION_DEFAULT)
+#if JS_HAS_CONST
+JS_KEYWORD(const, TOK_VAR, JSOP_DEFCONST, JSVERSION_DEFAULT)
+#else
+JS_KEYWORD(const, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+JS_KEYWORD(try, TOK_TRY, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(catch, TOK_CATCH, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(finally, TOK_FINALLY, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(throw, TOK_THROW, JSOP_NOP, JSVERSION_DEFAULT)
+
+JS_KEYWORD(instanceof, TOK_INSTANCEOF, JSOP_INSTANCEOF,JSVERSION_DEFAULT)
+
+#if JS_HAS_RESERVED_JAVA_KEYWORDS
+JS_KEYWORD(abstract, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(boolean, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(byte, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(char, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(class, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(double, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(extends, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(final, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(float, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(goto, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(implements, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(import, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(int, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(interface, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(long, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(native, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(package, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(private, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(protected, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(public, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(short, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(static, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(super, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(synchronized,TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(throws, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(transient, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+JS_KEYWORD(volatile, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+#if JS_HAS_RESERVED_ECMA_KEYWORDS
+JS_KEYWORD(enum, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+#if JS_HAS_DEBUGGER_KEYWORD
+JS_KEYWORD(debugger, TOK_DEBUGGER, JSOP_NOP, JSVERSION_DEFAULT)
+#elif JS_HAS_RESERVED_ECMA_KEYWORDS
+JS_KEYWORD(debugger, TOK_RESERVED, JSOP_NOP, JSVERSION_DEFAULT)
+#endif
+
+#if JS_HAS_GENERATORS
+JS_KEYWORD(yield, TOK_YIELD, JSOP_NOP, JSVERSION_1_7)
+#endif
+
+#if JS_HAS_BLOCK_SCOPE
+JS_KEYWORD(let, TOK_LET, JSOP_NOP, JSVERSION_1_7)
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp
new file mode 100644
index 0000000..1d26c3d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jskwgen.cpp
@@ -0,0 +1,460 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Switch Generator for JavaScript Keywords,
+ * released 2005-12-09.
+ *
+ * The Initial Developer of the Original Code is
+ * Igor Bukanov.
+ * Portions created by the Initial Developer are Copyright (C) 2005-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+#include "jsversion.h"
+
+const char * const keyword_list[] = {
+#define JS_KEYWORD(keyword, type, op, version) #keyword,
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+};
+
+struct gen_opt {
+ FILE *output; /* output file for generated source */
+ unsigned use_if_threshold; /* max number of choices to generate
+ "if" selector instead of "switch" */
+ unsigned char_tail_test_threshold; /* max number of unprocessed columns
+ to use inlined char compare
+ for remaining chars and not generic
+ string compare code */
+ unsigned indent_level; /* current source identation level */
+};
+
+static unsigned column_to_compare;
+
+static int
+length_comparator(const void *a, const void *b)
+{
+ const char *str1 = keyword_list[*(unsigned *)a];
+ const char *str2 = keyword_list[*(unsigned *)b];
+ return (int)strlen(str1) - (int)strlen(str2);
+}
+
+static int
+column_comparator(const void *a, const void *b)
+{
+ const char *str1 = keyword_list[*(unsigned *)a];
+ const char *str2 = keyword_list[*(unsigned *)b];
+ return (int)str1[column_to_compare] - (int)str2[column_to_compare];
+}
+
+static unsigned
+count_different_lengths(unsigned indexes[], unsigned nelem)
+{
+ unsigned nlength, current_length, i, l;
+
+ current_length = 0;
+ nlength = 0;
+ for (i = 0; i != nelem; ++i) {
+ l = (unsigned)strlen(keyword_list[indexes[i]]);
+ assert(l != 0);
+ if (current_length != l) {
+ ++nlength;
+ current_length = l;
+ }
+ }
+ return nlength;
+}
+
+static void
+find_char_span_and_count(unsigned indexes[], unsigned nelem, unsigned column,
+ unsigned *span_result, unsigned *count_result)
+{
+ unsigned i, count;
+ unsigned char c, prev, minc, maxc;
+
+ assert(nelem != 0);
+ minc = maxc = prev = (unsigned char)keyword_list[indexes[0]][column];
+ count = 1;
+ for (i = 1; i != nelem; ++i) {
+ c = (unsigned char)keyword_list[indexes[i]][column];
+ if (prev != c) {
+ prev = c;
+ ++count;
+ if (minc > c) {
+ minc = c;
+ } else if (maxc < c) {
+ maxc = c;
+ }
+ }
+ }
+
+ *span_result = maxc - minc + 1;
+ *count_result = count;
+}
+
+static unsigned
+find_optimal_switch_column(struct gen_opt *opt,
+ unsigned indexes[], unsigned nelem,
+ unsigned columns[], unsigned unprocessed_columns,
+ int *use_if_result)
+{
+ unsigned i;
+ unsigned span, min_span, min_span_index;
+ unsigned nchar, min_nchar, min_nchar_index;
+
+ assert(unprocessed_columns != 0);
+ i = 0;
+ min_nchar = min_span = (unsigned)-1;
+ min_nchar_index = min_span_index = 0;
+ do {
+ column_to_compare = columns[i];
+ qsort(indexes, nelem, sizeof(indexes[0]), column_comparator);
+ find_char_span_and_count(indexes, nelem, column_to_compare,
+ &span, &nchar);
+ assert(span != 0);
+ if (span == 1) {
+ assert(nchar == 1);
+ *use_if_result = 1;
+ return 1;
+ }
+ assert(nchar != 1);
+ if (min_span > span) {
+ min_span = span;
+ min_span_index = i;
+ }
+ if (min_nchar > nchar) {
+ min_nchar = nchar;
+ min_nchar_index = i;
+ }
+ } while (++i != unprocessed_columns);
+
+ if (min_nchar <= opt->use_if_threshold) {
+ *use_if_result = 1;
+ i = min_nchar_index;
+ } else {
+ *use_if_result = 0;
+ i = min_span_index;
+ }
+
+ /*
+ * Restore order corresponding to i if it was destroyed by
+ * subsequent sort.
+ */
+ if (i != unprocessed_columns - 1) {
+ column_to_compare = columns[i];
+ qsort(indexes, nelem, sizeof(indexes[0]), column_comparator);
+ }
+
+ return i;
+}
+
+
+static void
+p(struct gen_opt *opt, const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf(opt->output, format, ap);
+ va_end(ap);
+}
+
+/* Size for '\xxx' where xxx is octal escape */
+#define MIN_QUOTED_CHAR_BUFFER 7
+
+static char *
+qchar(char c, char *quoted_buffer)
+{
+ char *s;
+
+ s = quoted_buffer;
+ *s++ = '\'';
+ switch (c) {
+ case '\n': c = 'n'; goto one_char_escape;
+ case '\r': c = 'r'; goto one_char_escape;
+ case '\t': c = 't'; goto one_char_escape;
+ case '\f': c = 't'; goto one_char_escape;
+ case '\0': c = '0'; goto one_char_escape;
+ case '\'': goto one_char_escape;
+ one_char_escape:
+ *s++ = '\\';
+ break;
+ default:
+ if (!isprint(c)) {
+ *s++ = '\\';
+ *s++ = (char)('0' + (0x3 & (((unsigned char)c) >> 6)));
+ *s++ = (char)('0' + (0x7 & (((unsigned char)c) >> 3)));
+ c = (char)('0' + (0x7 & ((unsigned char)c)));
+ }
+ }
+ *s++ = c;
+ *s++ = '\'';
+ *s = '\0';
+ assert(s + 1 <= quoted_buffer + MIN_QUOTED_CHAR_BUFFER);
+ return quoted_buffer;
+}
+
+static void
+nl(struct gen_opt *opt)
+{
+ putc('\n', opt->output);
+}
+
+static void
+indent(struct gen_opt *opt)
+{
+ unsigned n = opt->indent_level;
+ while (n != 0) {
+ --n;
+ fputs(" ", opt->output);
+ }
+}
+
+static void
+line(struct gen_opt *opt, const char *format, ...)
+{
+ va_list ap;
+
+ indent(opt);
+ va_start(ap, format);
+ vfprintf(opt->output, format, ap);
+ va_end(ap);
+ nl(opt);
+}
+
+static void
+generate_letter_switch_r(struct gen_opt *opt,
+ unsigned indexes[], unsigned nelem,
+ unsigned columns[], unsigned unprocessed_columns)
+{
+ char qbuf[MIN_QUOTED_CHAR_BUFFER];
+
+ assert(nelem != 0);
+ if (nelem == 1) {
+ unsigned kw_index = indexes[0];
+ const char *keyword = keyword_list[kw_index];
+
+ if (unprocessed_columns == 0) {
+ line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword);
+ } else if (unprocessed_columns > opt->char_tail_test_threshold) {
+ line(opt, "JSKW_TEST_GUESS(%u) /* %s */", kw_index, keyword);
+ } else {
+ unsigned i, column;
+
+ indent(opt); p(opt, "if (");
+ for (i = 0; i != unprocessed_columns; ++i) {
+ column = columns[i];
+ qchar(keyword[column], qbuf);
+ p(opt, "%sJSKW_AT(%u)==%s", (i == 0) ? "" : " && ",
+ column, qbuf);
+ }
+ p(opt, ") {"); nl(opt);
+ ++opt->indent_level;
+ line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword);
+ --opt->indent_level;
+ line(opt, "}");
+ line(opt, "JSKW_NO_MATCH()");
+ }
+ } else {
+ unsigned optimal_column_index, optimal_column;
+ unsigned i;
+ int use_if;
+ char current;
+
+ assert(unprocessed_columns != 0);
+ optimal_column_index = find_optimal_switch_column(opt, indexes, nelem,
+ columns,
+ unprocessed_columns,
+ &use_if);
+ optimal_column = columns[optimal_column_index];
+ columns[optimal_column_index] = columns[unprocessed_columns - 1];
+
+ if (!use_if)
+ line(opt, "switch (JSKW_AT(%u)) {", optimal_column);
+
+ current = keyword_list[indexes[0]][optimal_column];
+ for (i = 0; i != nelem;) {
+ unsigned same_char_begin = i;
+ char next = current;
+
+ for (++i; i != nelem; ++i) {
+ next = keyword_list[indexes[i]][optimal_column];
+ if (next != current)
+ break;
+ }
+ qchar(current, qbuf);
+ if (use_if) {
+ line(opt, "if (JSKW_AT(%u) == %s) {", optimal_column, qbuf);
+ } else {
+ line(opt, " case %s:", qbuf);
+ }
+ ++opt->indent_level;
+ generate_letter_switch_r(opt, indexes + same_char_begin,
+ i - same_char_begin,
+ columns, unprocessed_columns - 1);
+ --opt->indent_level;
+ if (use_if) {
+ line(opt, "}");
+ }
+ current = next;
+ }
+
+ if (!use_if) {
+ line(opt, "}");
+ }
+
+ columns[optimal_column_index] = optimal_column;
+
+ line(opt, "JSKW_NO_MATCH()");
+ }
+}
+
+static void
+generate_letter_switch(struct gen_opt *opt,
+ unsigned indexes[], unsigned nelem,
+ unsigned current_length)
+{
+ unsigned *columns;
+ unsigned i;
+
+ columns = (unsigned *) malloc(sizeof(columns[0]) * current_length);
+ if (!columns) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i != current_length; ++i) {
+ columns[i] = i;
+ }
+ generate_letter_switch_r(opt, indexes, nelem, columns, current_length);
+ free(columns);
+}
+
+
+static void
+generate_switch(struct gen_opt *opt)
+{
+ unsigned *indexes;
+ unsigned nlength;
+ unsigned i, current;
+ int use_if;
+ unsigned nelem;
+
+ nelem = sizeof(keyword_list)/sizeof(keyword_list[0]);
+
+ line(opt, "/*");
+ line(opt, " * Generating switch for the list of %u entries:", nelem);
+ for (i = 0; i != nelem; ++i) {
+ line(opt, " * %s", keyword_list[i]);
+ }
+ line(opt, " */");
+
+ indexes = (unsigned *) malloc(sizeof(indexes[0]) * nelem);
+ if (!indexes) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ for (i = 0; i != nelem; ++i)
+ indexes[i] = i;
+ qsort(indexes, nelem, sizeof(indexes[i]), length_comparator);
+ nlength = count_different_lengths(indexes, nelem);
+
+ use_if = (nlength <= opt->use_if_threshold);
+
+ if (!use_if)
+ line(opt, "switch (JSKW_LENGTH()) {");
+
+ current = (unsigned)strlen(keyword_list[indexes[0]]);
+ for (i = 0; i != nelem;) {
+ unsigned same_length_begin = i;
+ unsigned next = current;
+
+ for (++i; i != nelem; ++i) {
+ next = (unsigned)strlen(keyword_list[indexes[i]]);
+ if (next != current)
+ break;
+ }
+ if (use_if) {
+ line(opt, "if (JSKW_LENGTH() == %u) {", current);
+ } else {
+ line(opt, " case %u:", current);
+ }
+ ++opt->indent_level;
+ generate_letter_switch(opt, indexes + same_length_begin,
+ i - same_length_begin,
+ current);
+ --opt->indent_level;
+ if (use_if) {
+ line(opt, "}");
+ }
+ current = next;
+ }
+ if (!use_if)
+ line(opt, "}");
+ line(opt, "JSKW_NO_MATCH()");
+ free(indexes);
+}
+
+int main(int argc, char **argv)
+{
+ struct gen_opt opt;
+
+ if (argc < 2) {
+ opt.output = stdout;
+ } else {
+ opt.output = fopen(argv[1], "w");
+ if (!opt.output) {
+ perror("fopen");
+ exit(EXIT_FAILURE);
+ }
+ }
+ opt.indent_level = 1;
+ opt.use_if_threshold = 3;
+ opt.char_tail_test_threshold = 4;
+
+ generate_switch(&opt);
+
+ if (opt.output != stdout) {
+ if (fclose(opt.output)) {
+ perror("fclose");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h b/tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h
new file mode 100644
index 0000000..d90a04c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslibmath.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _LIBMATH_H
+#define _LIBMATH_H
+
+#include <math.h>
+#include "jsversion.h"
+
+/*
+ * Use system provided math routines.
+ */
+
+/* The right copysign function is not always named the same thing. */
+#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define js_copysign __builtin_copysign
+#elif defined WINCE
+#define js_copysign _copysign
+#elif defined _WIN32
+#if _MSC_VER < 1400
+/* Try to work around apparent _copysign bustage in VC6 and VC7. */
+#define js_copysign js_copysign
+extern double js_copysign(double, double);
+#else
+#define js_copysign _copysign
+#endif
+#else
+#define js_copysign copysign
+#endif
+
+#endif /* _LIBMATH_H */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp
new file mode 100644
index 0000000..f91f0ed
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslock.cpp
@@ -0,0 +1,1417 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef JS_THREADSAFE
+
+/*
+ * JS locking stubs.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jspubtd.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jscntxt.h"
+#include "jsdtoa.h"
+#include "jsgc.h"
+#include "jsfun.h" /* for VALUE_IS_FUNCTION used by *_WRITE_BARRIER */
+#include "jslock.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+#define ReadWord(W) (W)
+
+/* Implement NativeCompareAndSwap. */
+
+#if defined(_WIN32) && defined(_M_IX86)
+#pragma warning( disable : 4035 )
+JS_BEGIN_EXTERN_C
+extern long __cdecl
+_InterlockedCompareExchange(long *volatile dest, long exchange, long comp);
+JS_END_EXTERN_C
+#pragma intrinsic(_InterlockedCompareExchange)
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwapHelper(jsword *w, jsword ov, jsword nv)
+{
+ _InterlockedCompareExchange(w, nv, ov);
+ __asm {
+ sete al
+ }
+}
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return (NativeCompareAndSwapHelper(w, ov, nv) & 1);
+}
+
+#elif defined(XP_MACOSX) || defined(DARWIN)
+
+#include <libkern/OSAtomic.h>
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ /* Details on these functions available in the manpage for atomic */
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+ return OSAtomicCompareAndSwap64Barrier(ov, nv, (int64_t*) w);
+#else
+ return OSAtomicCompareAndSwap32Barrier(ov, nv, (int32_t*) w);
+#endif
+}
+
+#elif defined(__GNUC__) && defined(__i386__)
+
+/* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ unsigned int res;
+
+ __asm__ __volatile__ (
+ "lock\n"
+ "cmpxchgl %2, (%1)\n"
+ "sete %%al\n"
+ "andl $1, %%eax\n"
+ : "=a" (res)
+ : "r" (w), "r" (nv), "a" (ov)
+ : "cc", "memory");
+ return (int)res;
+}
+
+#elif defined(__GNUC__) && defined(__x86_64__)
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ unsigned int res;
+
+ __asm__ __volatile__ (
+ "lock\n"
+ "cmpxchgq %2, (%1)\n"
+ "sete %%al\n"
+ "movzbl %%al, %%eax\n"
+ : "=a" (res)
+ : "r" (w), "r" (nv), "a" (ov)
+ : "cc", "memory");
+ return (int)res;
+}
+
+#elif defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+#if defined(__GNUC__)
+ unsigned int res;
+ JS_ASSERT(ov != nv);
+ asm volatile ("\
+stbar\n\
+cas [%1],%2,%3\n\
+cmp %2,%3\n\
+be,a 1f\n\
+mov 1,%0\n\
+mov 0,%0\n\
+1:"
+ : "=r" (res)
+ : "r" (w), "r" (ov), "r" (nv));
+ return (int)res;
+#else /* !__GNUC__ */
+ extern int compare_and_swap(jsword*, jsword, jsword);
+ JS_ASSERT(ov != nv);
+ return compare_and_swap(w, ov, nv);
+#endif
+}
+
+#elif defined(AIX)
+
+#include <sys/atomic_op.h>
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return !_check_lock((atomic_p)w, ov, nv);
+}
+
+#elif defined(USE_ARM_KUSER)
+
+/* See https://bugzilla.mozilla.org/show_bug.cgi?id=429387 for a
+ * description of this ABI; this is a function provided at a fixed
+ * location by the kernel in the memory space of each process.
+ */
+typedef int (__kernel_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0)
+
+JS_STATIC_ASSERT(sizeof(jsword) == sizeof(int));
+
+static JS_ALWAYS_INLINE int
+NativeCompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ volatile int *vp = (volatile int *) w;
+ PRInt32 failed = 1;
+
+ /* Loop until a __kernel_cmpxchg succeeds. See bug 446169 */
+ do {
+ failed = __kernel_cmpxchg(ov, nv, vp);
+ } while (failed && *vp == ov);
+ return !failed;
+}
+
+#elif JS_HAS_NATIVE_COMPARE_AND_SWAP
+
+#error "JS_HAS_NATIVE_COMPARE_AND_SWAP should be 0 if your platform lacks a compare-and-swap instruction."
+
+#endif /* arch-tests */
+
+#if JS_HAS_NATIVE_COMPARE_AND_SWAP
+
+JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return !!NativeCompareAndSwap(w, ov, nv);
+}
+
+#elif defined(NSPR_LOCK)
+
+# ifdef __GNUC__
+# warning "js_CompareAndSwap is implemented using NSSP lock"
+# endif
+
+JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ int result;
+ static PRLock *CompareAndSwapLock = JS_NEW_LOCK();
+
+ JS_ACQUIRE_LOCK(CompareAndSwapLock);
+ result = (*w == ov);
+ if (result)
+ *w = nv;
+ JS_RELEASE_LOCK(CompareAndSwapLock);
+ return result;
+}
+
+#else /* !defined(NSPR_LOCK) */
+
+#error "NSPR_LOCK should be on when the platform lacks native compare-and-swap."
+
+#endif
+
+#ifndef NSPR_LOCK
+
+struct JSFatLock {
+ int susp;
+ PRLock *slock;
+ PRCondVar *svar;
+ JSFatLock *next;
+ JSFatLock **prevp;
+};
+
+typedef struct JSFatLockTable {
+ JSFatLock *free;
+ JSFatLock *taken;
+} JSFatLockTable;
+
+#define GLOBAL_LOCK_INDEX(id) (((uint32)(jsuword)(id)>>2) & global_locks_mask)
+
+static void
+js_Dequeue(JSThinLock *);
+
+static PRLock **global_locks;
+static uint32 global_lock_count = 1;
+static uint32 global_locks_log2 = 0;
+static uint32 global_locks_mask = 0;
+
+static void
+js_LockGlobal(void *id)
+{
+ uint32 i = GLOBAL_LOCK_INDEX(id);
+ PR_Lock(global_locks[i]);
+}
+
+static void
+js_UnlockGlobal(void *id)
+{
+ uint32 i = GLOBAL_LOCK_INDEX(id);
+ PR_Unlock(global_locks[i]);
+}
+
+#endif /* !NSPR_LOCK */
+
+void
+js_InitLock(JSThinLock *tl)
+{
+#ifdef NSPR_LOCK
+ tl->owner = 0;
+ tl->fat = (JSFatLock*)JS_NEW_LOCK();
+#else
+ memset(tl, 0, sizeof(JSThinLock));
+#endif
+}
+
+void
+js_FinishLock(JSThinLock *tl)
+{
+#ifdef NSPR_LOCK
+ tl->owner = 0xdeadbeef;
+ if (tl->fat)
+ JS_DESTROY_LOCK(((JSLock*)tl->fat));
+#else
+ JS_ASSERT(tl->owner == 0);
+ JS_ASSERT(tl->fat == NULL);
+#endif
+}
+
+#ifdef DEBUG_SCOPE_COUNT
+
+#include <stdio.h>
+#include "jsdhash.h"
+
+static FILE *logfp;
+static JSDHashTable logtbl;
+
+typedef struct logentry {
+ JSDHashEntryStub stub;
+ char op;
+ const char *file;
+ int line;
+} logentry;
+
+static void
+logit(JSScope *scope, char op, const char *file, int line)
+{
+ logentry *entry;
+
+ if (!logfp) {
+ logfp = fopen("/tmp/scope.log", "w");
+ if (!logfp)
+ return;
+ setvbuf(logfp, NULL, _IONBF, 0);
+ }
+ fprintf(logfp, "%p %c %s %d\n", scope, op, file, line);
+
+ if (!logtbl.entryStore &&
+ !JS_DHashTableInit(&logtbl, JS_DHashGetStubOps(), NULL,
+ sizeof(logentry), 100)) {
+ return;
+ }
+ entry = (logentry *) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_ADD);
+ if (!entry)
+ return;
+ entry->stub.key = scope;
+ entry->op = op;
+ entry->file = file;
+ entry->line = line;
+}
+
+void
+js_unlog_scope(JSScope *scope)
+{
+ if (!logtbl.entryStore)
+ return;
+ (void) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_REMOVE);
+}
+
+# define LOGIT(scope,op) logit(scope, op, __FILE__, __LINE__)
+
+#else
+
+# define LOGIT(scope,op) /* nothing */
+
+#endif /* DEBUG_SCOPE_COUNT */
+
+/*
+ * Return true if scope's ownercx, or the ownercx of a single-threaded scope
+ * for which ownercx is waiting to become multi-threaded and shared, is cx.
+ * That condition implies deadlock in ClaimScope if cx's thread were to wait
+ * to share scope.
+ *
+ * (i) rt->gcLock held
+ */
+static JSBool
+WillDeadlock(JSTitle *title, JSContext *cx)
+{
+ JSContext *ownercx;
+
+ do {
+ ownercx = title->ownercx;
+ if (ownercx == cx) {
+ JS_RUNTIME_METER(cx->runtime, deadlocksAvoided);
+ return JS_TRUE;
+ }
+ } while (ownercx && (title = ownercx->titleToShare) != NULL);
+ return JS_FALSE;
+}
+
+/*
+ * Make title multi-threaded, i.e. share its ownership among contexts in rt
+ * using a "thin" or (if necessary due to contention) "fat" lock. Called only
+ * from ClaimTitle, immediately below, when we detect deadlock were we to wait
+ * for title's lock, because its ownercx is waiting on a title owned by the
+ * calling cx.
+ *
+ * (i) rt->gcLock held
+ */
+static void
+ShareTitle(JSContext *cx, JSTitle *title)
+{
+ JSRuntime *rt;
+ JSTitle **todop;
+
+ rt = cx->runtime;
+ if (title->u.link) {
+ for (todop = &rt->titleSharingTodo; *todop != title;
+ todop = &(*todop)->u.link) {
+ JS_ASSERT(*todop != NO_TITLE_SHARING_TODO);
+ }
+ *todop = title->u.link;
+ title->u.link = NULL; /* null u.link for sanity ASAP */
+ JS_NOTIFY_ALL_CONDVAR(rt->titleSharingDone);
+ }
+ js_InitLock(&title->lock);
+ title->u.count = 0;
+ js_FinishSharingTitle(cx, title);
+}
+
+/*
+ * js_FinishSharingTitle is the tail part of ShareTitle, split out to become a
+ * subroutine of JS_EndRequest too. The bulk of the work here involves making
+ * mutable strings in the title's object's slots be immutable. We have to do
+ * this because such strings will soon be available to multiple threads, so
+ * their buffers can't be realloc'd any longer in js_ConcatStrings, and their
+ * members can't be modified by js_ConcatStrings, js_MinimizeDependentStrings,
+ * or js_UndependString.
+ *
+ * The last bit of work done by js_FinishSharingTitle nulls title->ownercx and
+ * updates rt->sharedTitles.
+ */
+
+void
+js_FinishSharingTitle(JSContext *cx, JSTitle *title)
+{
+ JSObjectMap *map;
+ JSScope *scope;
+ JSObject *obj;
+ uint32 nslots, i;
+ jsval v;
+
+ map = TITLE_TO_MAP(title);
+ if (!MAP_IS_NATIVE(map))
+ return;
+ scope = (JSScope *)map;
+
+ obj = scope->object;
+ if (obj) {
+ nslots = scope->map.freeslot;
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_STRING(v) &&
+ !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
+ /*
+ * FIXME bug 363059: The following error recovery changes
+ * runtime execution semantics, arbitrarily and silently
+ * ignoring errors except out-of-memory, which should have been
+ * reported through JS_ReportOutOfMemory at this point.
+ */
+ STOBJ_SET_SLOT(obj, i, JSVAL_VOID);
+ }
+ }
+ }
+
+ title->ownercx = NULL; /* NB: set last, after lock init */
+ JS_RUNTIME_METER(cx->runtime, sharedTitles);
+}
+
+/*
+ * Given a title with apparently non-null ownercx different from cx, try to
+ * set ownercx to cx, claiming exclusive (single-threaded) ownership of title.
+ * If we claim ownership, return true. Otherwise, we wait for ownercx to be
+ * set to null (indicating that title is multi-threaded); or if waiting would
+ * deadlock, we set ownercx to null ourselves via ShareTitle. In any case,
+ * once ownercx is null we return false.
+ */
+static JSBool
+ClaimTitle(JSTitle *title, JSContext *cx)
+{
+ JSRuntime *rt;
+ JSContext *ownercx;
+ jsrefcount saveDepth;
+ PRStatus stat;
+
+ rt = cx->runtime;
+ JS_RUNTIME_METER(rt, claimAttempts);
+ JS_LOCK_GC(rt);
+
+ /* Reload in case ownercx went away while we blocked on the lock. */
+ while ((ownercx = title->ownercx) != NULL) {
+ /*
+ * Avoid selflock if ownercx is dead, or is not running a request, or
+ * has the same thread as cx. Set title->ownercx to cx so that the
+ * matching JS_UNLOCK_SCOPE or JS_UNLOCK_OBJ macro call will take the
+ * fast path around the corresponding js_UnlockTitle or js_UnlockObj
+ * function call.
+ *
+ * If title->u.link is non-null, title has already been inserted on
+ * the rt->titleSharingTodo list, because another thread's context
+ * already wanted to lock title while ownercx was running a request.
+ * We can't claim any title whose u.link is non-null at this point,
+ * even if ownercx->requestDepth is 0 (see below where we suspend our
+ * request before waiting on rt->titleSharingDone).
+ */
+ if (!title->u.link &&
+ (!js_ValidContextPointer(rt, ownercx) ||
+ !ownercx->requestDepth ||
+ ownercx->thread == cx->thread)) {
+ JS_ASSERT(title->u.count == 0);
+ title->ownercx = cx;
+ JS_UNLOCK_GC(rt);
+ JS_RUNTIME_METER(rt, claimedTitles);
+ return JS_TRUE;
+ }
+
+ /*
+ * Avoid deadlock if title's owner context is waiting on a title that
+ * we own, by revoking title's ownership. This approach to deadlock
+ * avoidance works because the engine never nests title locks.
+ *
+ * If cx could hold locks on ownercx->titleToShare, or if ownercx could
+ * hold locks on title, we would need to keep reentrancy counts for all
+ * such "flyweight" (ownercx != NULL) locks, so that control would
+ * unwind properly once these locks became "thin" or "fat". The engine
+ * promotes a title from exclusive to shared access only when locking,
+ * never when holding or unlocking.
+ *
+ * Avoid deadlock before any of this title/context cycle detection if
+ * cx is on the active GC's thread, because in that case, no requests
+ * will run until the GC completes. Any title wanted by the GC (from
+ * a finalizer) that can't be claimed must become shared.
+ */
+ if (rt->gcThread == cx->thread ||
+ (ownercx->titleToShare &&
+ WillDeadlock(ownercx->titleToShare, cx))) {
+ ShareTitle(cx, title);
+ break;
+ }
+
+ /*
+ * Thanks to the non-zero NO_TITLE_SHARING_TODO link terminator, we
+ * can decide whether title is on rt->titleSharingTodo with a single
+ * non-null test, and avoid double-insertion bugs.
+ */
+ if (!title->u.link) {
+ title->u.link = rt->titleSharingTodo;
+ rt->titleSharingTodo = title;
+ js_HoldObjectMap(cx, TITLE_TO_MAP(title));
+ }
+
+ /*
+ * Inline JS_SuspendRequest before we wait on rt->titleSharingDone,
+ * saving and clearing cx->requestDepth so we don't deadlock if the
+ * GC needs to run on ownercx.
+ *
+ * Unlike JS_SuspendRequest and JS_EndRequest, we must take care not
+ * to decrement rt->requestCount if cx is active on the GC's thread,
+ * because the GC has already reduced rt->requestCount to exclude all
+ * such such contexts.
+ */
+ saveDepth = cx->requestDepth;
+ if (saveDepth) {
+ cx->requestDepth = 0;
+ if (rt->gcThread != cx->thread) {
+ JS_ASSERT(rt->requestCount > 0);
+ rt->requestCount--;
+ if (rt->requestCount == 0)
+ JS_NOTIFY_REQUEST_DONE(rt);
+ }
+ }
+
+ /*
+ * We know that some other thread's context owns title, which is now
+ * linked onto rt->titleSharingTodo, awaiting the end of that other
+ * thread's request. So it is safe to wait on rt->titleSharingDone.
+ */
+ cx->titleToShare = title;
+ stat = PR_WaitCondVar(rt->titleSharingDone, PR_INTERVAL_NO_TIMEOUT);
+ JS_ASSERT(stat != PR_FAILURE);
+
+ /*
+ * Inline JS_ResumeRequest after waiting on rt->titleSharingDone,
+ * restoring cx->requestDepth. Same note as above for the inlined,
+ * specialized JS_SuspendRequest code: beware rt->gcThread.
+ */
+ if (saveDepth) {
+ if (rt->gcThread != cx->thread) {
+ while (rt->gcLevel > 0)
+ JS_AWAIT_GC_DONE(rt);
+ rt->requestCount++;
+ }
+ cx->requestDepth = saveDepth;
+ }
+
+ /*
+ * Don't clear cx->titleToShare until after we're through waiting on
+ * all condition variables protected by rt->gcLock -- that includes
+ * rt->titleSharingDone *and* rt->gcDone (hidden in JS_AWAIT_GC_DONE,
+ * in the inlined JS_ResumeRequest code immediately above).
+ *
+ * Otherwise, the GC could easily deadlock with another thread that
+ * owns a title wanted by a finalizer. By keeping cx->titleToShare
+ * set till here, we ensure that such deadlocks are detected, which
+ * results in the finalized object's title being shared (it must, of
+ * course, have other, live objects sharing it).
+ */
+ cx->titleToShare = NULL;
+ }
+
+ JS_UNLOCK_GC(rt);
+ return JS_FALSE;
+}
+
+/* Exported to js.c, which calls it via OBJ_GET_* and JSVAL_IS_* macros. */
+JS_FRIEND_API(jsval)
+js_GetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot)
+{
+ jsval v;
+ JSScope *scope;
+ JSTitle *title;
+#ifndef NSPR_LOCK
+ JSThinLock *tl;
+ jsword me;
+#endif
+
+ /*
+ * We handle non-native objects via JSObjectOps.getRequiredSlot, treating
+ * all slots starting from 0 as required slots. A property definition or
+ * some prior arrangement must have allocated slot.
+ *
+ * Note once again (see jspubtd.h, before JSGetRequiredSlotOp's typedef)
+ * the crucial distinction between a |required slot number| that's passed
+ * to the get/setRequiredSlot JSObjectOps, and a |reserved slot index|
+ * passed to the JS_Get/SetReservedSlot APIs.
+ */
+ if (!OBJ_IS_NATIVE(obj))
+ return OBJ_GET_REQUIRED_SLOT(cx, obj, slot);
+
+ /*
+ * Native object locking is inlined here to optimize the single-threaded
+ * and contention-free multi-threaded cases.
+ */
+ scope = OBJ_SCOPE(obj);
+ title = &scope->title;
+ JS_ASSERT(title->ownercx != cx);
+ JS_ASSERT(slot < obj->map->freeslot);
+
+ /*
+ * Avoid locking if called from the GC. Also avoid locking an object
+ * owning a sealed scope. If neither of those special cases applies, try
+ * to claim scope's flyweight lock from whatever context may have had it in
+ * an earlier request.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx) ||
+ (SCOPE_IS_SEALED(scope) && scope->object == obj) ||
+ (title->ownercx && ClaimTitle(title, cx))) {
+ return STOBJ_GET_SLOT(obj, slot);
+ }
+
+#ifndef NSPR_LOCK
+ tl = &title->lock;
+ me = CX_THINLOCK_ID(cx);
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ if (NativeCompareAndSwap(&tl->owner, 0, me)) {
+ /*
+ * Got the lock with one compare-and-swap. Even so, someone else may
+ * have mutated obj so it now has its own scope and lock, which would
+ * require either a restart from the top of this routine, or a thin
+ * lock release followed by fat lock acquisition.
+ */
+ if (scope == OBJ_SCOPE(obj)) {
+ v = STOBJ_GET_SLOT(obj, slot);
+ if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
+ /* Assert that scope locks never revert to flyweight. */
+ JS_ASSERT(title->ownercx != cx);
+ LOGIT(scope, '1');
+ title->u.count = 1;
+ js_UnlockObj(cx, obj);
+ }
+ return v;
+ }
+ if (!NativeCompareAndSwap(&tl->owner, me, 0))
+ js_Dequeue(tl);
+ }
+ else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
+ return STOBJ_GET_SLOT(obj, slot);
+ }
+#endif
+
+ js_LockObj(cx, obj);
+ v = STOBJ_GET_SLOT(obj, slot);
+
+ /*
+ * Test whether cx took ownership of obj's scope during js_LockObj.
+ *
+ * This does not mean that a given scope reverted to flyweight from "thin"
+ * or "fat" -- it does mean that obj's map pointer changed due to another
+ * thread setting a property, requiring obj to cease sharing a prototype
+ * object's scope (whose lock was not flyweight, else we wouldn't be here
+ * in the first place!).
+ */
+ title = &OBJ_SCOPE(obj)->title;
+ if (title->ownercx != cx)
+ js_UnlockTitle(cx, title);
+ return v;
+}
+
+void
+js_SetSlotThreadSafe(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
+{
+ JSTitle *title;
+ JSScope *scope;
+#ifndef NSPR_LOCK
+ JSThinLock *tl;
+ jsword me;
+#endif
+
+ /* Any string stored in a thread-safe object must be immutable. */
+ if (JSVAL_IS_STRING(v) &&
+ !js_MakeStringImmutable(cx, JSVAL_TO_STRING(v))) {
+ /* FIXME bug 363059: See comments in js_FinishSharingScope. */
+ v = JSVAL_NULL;
+ }
+
+ /*
+ * We handle non-native objects via JSObjectOps.setRequiredSlot, as above
+ * for the Get case.
+ */
+ if (!OBJ_IS_NATIVE(obj)) {
+ OBJ_SET_REQUIRED_SLOT(cx, obj, slot, v);
+ return;
+ }
+
+ /*
+ * Native object locking is inlined here to optimize the single-threaded
+ * and contention-free multi-threaded cases.
+ */
+ scope = OBJ_SCOPE(obj);
+ title = &scope->title;
+ JS_ASSERT(title->ownercx != cx);
+ JS_ASSERT(slot < obj->map->freeslot);
+
+ /*
+ * Avoid locking if called from the GC. Also avoid locking an object
+ * owning a sealed scope. If neither of those special cases applies, try
+ * to claim scope's flyweight lock from whatever context may have had it in
+ * an earlier request.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx) ||
+ (SCOPE_IS_SEALED(scope) && scope->object == obj) ||
+ (title->ownercx && ClaimTitle(title, cx))) {
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+ return;
+ }
+
+#ifndef NSPR_LOCK
+ tl = &title->lock;
+ me = CX_THINLOCK_ID(cx);
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ if (NativeCompareAndSwap(&tl->owner, 0, me)) {
+ if (scope == OBJ_SCOPE(obj)) {
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+ if (!NativeCompareAndSwap(&tl->owner, me, 0)) {
+ /* Assert that scope locks never revert to flyweight. */
+ JS_ASSERT(title->ownercx != cx);
+ LOGIT(scope, '1');
+ title->u.count = 1;
+ js_UnlockObj(cx, obj);
+ }
+ return;
+ }
+ if (!NativeCompareAndSwap(&tl->owner, me, 0))
+ js_Dequeue(tl);
+ }
+ else if (Thin_RemoveWait(ReadWord(tl->owner)) == me) {
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+ return;
+ }
+#endif
+
+ js_LockObj(cx, obj);
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, v);
+
+ /*
+ * Same drill as above, in js_GetSlotThreadSafe.
+ */
+ title = &OBJ_SCOPE(obj)->title;
+ if (title->ownercx != cx)
+ js_UnlockTitle(cx, title);
+}
+
+#ifndef NSPR_LOCK
+
+static JSFatLock *
+NewFatlock()
+{
+ JSFatLock *fl = (JSFatLock *)malloc(sizeof(JSFatLock)); /* for now */
+ if (!fl) return NULL;
+ fl->susp = 0;
+ fl->next = NULL;
+ fl->prevp = NULL;
+ fl->slock = PR_NewLock();
+ fl->svar = PR_NewCondVar(fl->slock);
+ return fl;
+}
+
+static void
+DestroyFatlock(JSFatLock *fl)
+{
+ PR_DestroyLock(fl->slock);
+ PR_DestroyCondVar(fl->svar);
+ free(fl);
+}
+
+static JSFatLock *
+ListOfFatlocks(int listc)
+{
+ JSFatLock *m;
+ JSFatLock *m0;
+ int i;
+
+ JS_ASSERT(listc>0);
+ m0 = m = NewFatlock();
+ for (i=1; i<listc; i++) {
+ m->next = NewFatlock();
+ m = m->next;
+ }
+ return m0;
+}
+
+static void
+DeleteListOfFatlocks(JSFatLock *m)
+{
+ JSFatLock *m0;
+ for (; m; m=m0) {
+ m0 = m->next;
+ DestroyFatlock(m);
+ }
+}
+
+static JSFatLockTable *fl_list_table = NULL;
+static uint32 fl_list_table_len = 0;
+static uint32 fl_list_chunk_len = 0;
+
+static JSFatLock *
+GetFatlock(void *id)
+{
+ JSFatLock *m;
+
+ uint32 i = GLOBAL_LOCK_INDEX(id);
+ if (fl_list_table[i].free == NULL) {
+#ifdef DEBUG
+ if (fl_list_table[i].taken)
+ printf("Ran out of fat locks!\n");
+#endif
+ fl_list_table[i].free = ListOfFatlocks(fl_list_chunk_len);
+ }
+ m = fl_list_table[i].free;
+ fl_list_table[i].free = m->next;
+ m->susp = 0;
+ m->next = fl_list_table[i].taken;
+ m->prevp = &fl_list_table[i].taken;
+ if (fl_list_table[i].taken)
+ fl_list_table[i].taken->prevp = &m->next;
+ fl_list_table[i].taken = m;
+ return m;
+}
+
+static void
+PutFatlock(JSFatLock *m, void *id)
+{
+ uint32 i;
+ if (m == NULL)
+ return;
+
+ /* Unlink m from fl_list_table[i].taken. */
+ *m->prevp = m->next;
+ if (m->next)
+ m->next->prevp = m->prevp;
+
+ /* Insert m in fl_list_table[i].free. */
+ i = GLOBAL_LOCK_INDEX(id);
+ m->next = fl_list_table[i].free;
+ fl_list_table[i].free = m;
+}
+
+#endif /* !NSPR_LOCK */
+
+JSBool
+js_SetupLocks(int listc, int globc)
+{
+#ifndef NSPR_LOCK
+ uint32 i;
+
+ if (global_locks)
+ return JS_TRUE;
+#ifdef DEBUG
+ if (listc > 10000 || listc < 0) /* listc == fat lock list chunk length */
+ printf("Bad number %d in js_SetupLocks()!\n", listc);
+ if (globc > 100 || globc < 0) /* globc == number of global locks */
+ printf("Bad number %d in js_SetupLocks()!\n", listc);
+#endif
+ global_locks_log2 = JS_CeilingLog2(globc);
+ global_locks_mask = JS_BITMASK(global_locks_log2);
+ global_lock_count = JS_BIT(global_locks_log2);
+ global_locks = (PRLock **) malloc(global_lock_count * sizeof(PRLock*));
+ if (!global_locks)
+ return JS_FALSE;
+ for (i = 0; i < global_lock_count; i++) {
+ global_locks[i] = PR_NewLock();
+ if (!global_locks[i]) {
+ global_lock_count = i;
+ js_CleanupLocks();
+ return JS_FALSE;
+ }
+ }
+ fl_list_table = (JSFatLockTable *) malloc(i * sizeof(JSFatLockTable));
+ if (!fl_list_table) {
+ js_CleanupLocks();
+ return JS_FALSE;
+ }
+ fl_list_table_len = global_lock_count;
+ for (i = 0; i < global_lock_count; i++)
+ fl_list_table[i].free = fl_list_table[i].taken = NULL;
+ fl_list_chunk_len = listc;
+#endif /* !NSPR_LOCK */
+ return JS_TRUE;
+}
+
+void
+js_CleanupLocks()
+{
+#ifndef NSPR_LOCK
+ uint32 i;
+
+ if (global_locks) {
+ for (i = 0; i < global_lock_count; i++)
+ PR_DestroyLock(global_locks[i]);
+ free(global_locks);
+ global_locks = NULL;
+ global_lock_count = 1;
+ global_locks_log2 = 0;
+ global_locks_mask = 0;
+ }
+ if (fl_list_table) {
+ for (i = 0; i < fl_list_table_len; i++) {
+ DeleteListOfFatlocks(fl_list_table[i].free);
+ fl_list_table[i].free = NULL;
+ DeleteListOfFatlocks(fl_list_table[i].taken);
+ fl_list_table[i].taken = NULL;
+ }
+ free(fl_list_table);
+ fl_list_table = NULL;
+ fl_list_table_len = 0;
+ }
+#endif /* !NSPR_LOCK */
+}
+
+#ifdef NSPR_LOCK
+
+static JS_ALWAYS_INLINE void
+ThinLock(JSThinLock *tl, jsword me)
+{
+ JS_ACQUIRE_LOCK((JSLock *) tl->fat);
+ tl->owner = me;
+}
+
+static JS_ALWAYS_INLINE void
+ThinUnlock(JSThinLock *tl, jsword /*me*/)
+{
+ tl->owner = 0;
+ JS_RELEASE_LOCK((JSLock *) tl->fat);
+}
+
+#else
+
+/*
+ * Fast locking and unlocking is implemented by delaying the allocation of a
+ * system lock (fat lock) until contention. As long as a locking thread A
+ * runs uncontended, the lock is represented solely by storing A's identity in
+ * the object being locked.
+ *
+ * If another thread B tries to lock the object currently locked by A, B is
+ * enqueued into a fat lock structure (which might have to be allocated and
+ * pointed to by the object), and suspended using NSPR conditional variables
+ * (wait). A wait bit (Bacon bit) is set in the lock word of the object,
+ * signalling to A that when releasing the lock, B must be dequeued and
+ * notified.
+ *
+ * The basic operation of the locking primitives (js_Lock, js_Unlock,
+ * js_Enqueue, and js_Dequeue) is compare-and-swap. Hence, when locking into
+ * the word pointed at by p, compare-and-swap(p, 0, A) success implies that p
+ * is unlocked. Similarly, when unlocking p, if compare-and-swap(p, A, 0)
+ * succeeds this implies that p is uncontended (no one is waiting because the
+ * wait bit is not set).
+ *
+ * When dequeueing, the lock is released, and one of the threads suspended on
+ * the lock is notified. If other threads still are waiting, the wait bit is
+ * kept (in js_Enqueue), and if not, the fat lock is deallocated.
+ *
+ * The functions js_Enqueue, js_Dequeue, js_SuspendThread, and js_ResumeThread
+ * are serialized using a global lock. For scalability, a hashtable of global
+ * locks is used, which is indexed modulo the thin lock pointer.
+ */
+
+/*
+ * Invariants:
+ * (i) global lock is held
+ * (ii) fl->susp >= 0
+ */
+static int
+js_SuspendThread(JSThinLock *tl)
+{
+ JSFatLock *fl;
+ PRStatus stat;
+
+ if (tl->fat == NULL)
+ fl = tl->fat = GetFatlock(tl);
+ else
+ fl = tl->fat;
+ JS_ASSERT(fl->susp >= 0);
+ fl->susp++;
+ PR_Lock(fl->slock);
+ js_UnlockGlobal(tl);
+ stat = PR_WaitCondVar(fl->svar, PR_INTERVAL_NO_TIMEOUT);
+ JS_ASSERT(stat != PR_FAILURE);
+ PR_Unlock(fl->slock);
+ js_LockGlobal(tl);
+ fl->susp--;
+ if (fl->susp == 0) {
+ PutFatlock(fl, tl);
+ tl->fat = NULL;
+ }
+ return tl->fat == NULL;
+}
+
+/*
+ * (i) global lock is held
+ * (ii) fl->susp > 0
+ */
+static void
+js_ResumeThread(JSThinLock *tl)
+{
+ JSFatLock *fl = tl->fat;
+ PRStatus stat;
+
+ JS_ASSERT(fl != NULL);
+ JS_ASSERT(fl->susp > 0);
+ PR_Lock(fl->slock);
+ js_UnlockGlobal(tl);
+ stat = PR_NotifyCondVar(fl->svar);
+ JS_ASSERT(stat != PR_FAILURE);
+ PR_Unlock(fl->slock);
+}
+
+static void
+js_Enqueue(JSThinLock *tl, jsword me)
+{
+ jsword o, n;
+
+ js_LockGlobal(tl);
+ for (;;) {
+ o = ReadWord(tl->owner);
+ n = Thin_SetWait(o);
+ if (o != 0 && NativeCompareAndSwap(&tl->owner, o, n)) {
+ if (js_SuspendThread(tl))
+ me = Thin_RemoveWait(me);
+ else
+ me = Thin_SetWait(me);
+ }
+ else if (NativeCompareAndSwap(&tl->owner, 0, me)) {
+ js_UnlockGlobal(tl);
+ return;
+ }
+ }
+}
+
+static void
+js_Dequeue(JSThinLock *tl)
+{
+ jsword o;
+
+ js_LockGlobal(tl);
+ o = ReadWord(tl->owner);
+ JS_ASSERT(Thin_GetWait(o) != 0);
+ JS_ASSERT(tl->fat != NULL);
+ if (!NativeCompareAndSwap(&tl->owner, o, 0)) /* release it */
+ JS_ASSERT(0);
+ js_ResumeThread(tl);
+}
+
+static JS_ALWAYS_INLINE void
+ThinLock(JSThinLock *tl, jsword me)
+{
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ if (NativeCompareAndSwap(&tl->owner, 0, me))
+ return;
+ if (Thin_RemoveWait(ReadWord(tl->owner)) != me)
+ js_Enqueue(tl, me);
+#ifdef DEBUG
+ else
+ JS_ASSERT(0);
+#endif
+}
+
+static JS_ALWAYS_INLINE void
+ThinUnlock(JSThinLock *tl, jsword me)
+{
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+
+ /*
+ * Since we can race with the NativeCompareAndSwap in js_Enqueue, we need
+ * to use a C_A_S here as well -- Arjan van de Ven 30/1/08
+ */
+ if (NativeCompareAndSwap(&tl->owner, me, 0))
+ return;
+
+ JS_ASSERT(Thin_GetWait(tl->owner));
+ if (Thin_RemoveWait(ReadWord(tl->owner)) == me)
+ js_Dequeue(tl);
+#ifdef DEBUG
+ else
+ JS_ASSERT(0); /* unbalanced unlock */
+#endif
+}
+
+#endif /* !NSPR_LOCK */
+
+void
+js_Lock(JSContext *cx, JSThinLock *tl)
+{
+ ThinLock(tl, CX_THINLOCK_ID(cx));
+}
+
+void
+js_Unlock(JSContext *cx, JSThinLock *tl)
+{
+ ThinUnlock(tl, CX_THINLOCK_ID(cx));
+}
+
+void
+js_LockRuntime(JSRuntime *rt)
+{
+ PR_Lock(rt->rtLock);
+#ifdef DEBUG
+ rt->rtLockOwner = js_CurrentThreadId();
+#endif
+}
+
+void
+js_UnlockRuntime(JSRuntime *rt)
+{
+#ifdef DEBUG
+ rt->rtLockOwner = 0;
+#endif
+ PR_Unlock(rt->rtLock);
+}
+
+void
+js_LockTitle(JSContext *cx, JSTitle *title)
+{
+ jsword me = CX_THINLOCK_ID(cx);
+
+ JS_ASSERT(CURRENT_THREAD_IS_ME(me));
+ JS_ASSERT(title->ownercx != cx);
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+ if (title->ownercx && ClaimTitle(title, cx))
+ return;
+
+ if (Thin_RemoveWait(ReadWord(title->lock.owner)) == me) {
+ JS_ASSERT(title->u.count > 0);
+ LOGIT(scope, '+');
+ title->u.count++;
+ } else {
+ ThinLock(&title->lock, me);
+ JS_ASSERT(title->u.count == 0);
+ LOGIT(scope, '1');
+ title->u.count = 1;
+ }
+}
+
+void
+js_UnlockTitle(JSContext *cx, JSTitle *title)
+{
+ jsword me = CX_THINLOCK_ID(cx);
+
+ /* We hope compilers use me instead of reloading cx->thread in the macro. */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+ if (cx->lockedSealedTitle == title) {
+ cx->lockedSealedTitle = NULL;
+ return;
+ }
+
+ /*
+ * If title->ownercx is not null, it's likely that two contexts not using
+ * requests nested locks for title. The first context, cx here, claimed
+ * title; the second, title->ownercx here, re-claimed it because the first
+ * was not in a request, or was on the same thread. We don't want to keep
+ * track of such nesting, because it penalizes the common non-nested case.
+ * Instead of asserting here and silently coping, we simply re-claim title
+ * for cx and return.
+ *
+ * See http://bugzilla.mozilla.org/show_bug.cgi?id=229200 for a real world
+ * case where an asymmetric thread model (Mozilla's main thread is known
+ * to be the only thread that runs the GC) combined with multiple contexts
+ * per thread has led to such request-less nesting.
+ */
+ if (title->ownercx) {
+ JS_ASSERT(title->u.count == 0);
+ JS_ASSERT(title->lock.owner == 0);
+ title->ownercx = cx;
+ return;
+ }
+
+ JS_ASSERT(title->u.count > 0);
+ if (Thin_RemoveWait(ReadWord(title->lock.owner)) != me) {
+ JS_ASSERT(0); /* unbalanced unlock */
+ return;
+ }
+ LOGIT(scope, '-');
+ if (--title->u.count == 0)
+ ThinUnlock(&title->lock, me);
+}
+
+/*
+ * NB: oldtitle may be null if our caller is js_GetMutableScope and it just
+ * dropped the last reference to oldtitle.
+ */
+void
+js_TransferTitle(JSContext *cx, JSTitle *oldtitle, JSTitle *newtitle)
+{
+ JS_ASSERT(JS_IS_TITLE_LOCKED(cx, newtitle));
+
+ /*
+ * If the last reference to oldtitle went away, newtitle needs no lock
+ * state update.
+ */
+ if (!oldtitle)
+ return;
+ JS_ASSERT(JS_IS_TITLE_LOCKED(cx, oldtitle));
+
+ /*
+ * Special case in js_LockTitle and js_UnlockTitle for the GC calling
+ * code that locks, unlocks, or mutates. Nothing to do in these cases,
+ * because title and newtitle were "locked" by the GC thread, so neither
+ * was actually locked.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+
+ /*
+ * Special case in js_LockObj and js_UnlockTitle for locking the sealed
+ * scope of an object that owns that scope (the prototype or mutated obj
+ * for which OBJ_SCOPE(obj)->object == obj), and unlocking it.
+ */
+ JS_ASSERT(cx->lockedSealedTitle != newtitle);
+ if (cx->lockedSealedTitle == oldtitle) {
+ JS_ASSERT(newtitle->ownercx == cx ||
+ (!newtitle->ownercx && newtitle->u.count == 1));
+ cx->lockedSealedTitle = NULL;
+ return;
+ }
+
+ /*
+ * If oldtitle is single-threaded, there's nothing to do.
+ */
+ if (oldtitle->ownercx) {
+ JS_ASSERT(oldtitle->ownercx == cx);
+ JS_ASSERT(newtitle->ownercx == cx ||
+ (!newtitle->ownercx && newtitle->u.count == 1));
+ return;
+ }
+
+ /*
+ * We transfer oldtitle->u.count only if newtitle is not single-threaded.
+ * Flow unwinds from here through some number of JS_UNLOCK_TITLE and/or
+ * JS_UNLOCK_OBJ macro calls, which will decrement newtitle->u.count only
+ * if they find newtitle->ownercx != cx.
+ */
+ if (newtitle->ownercx != cx) {
+ JS_ASSERT(!newtitle->ownercx);
+ newtitle->u.count = oldtitle->u.count;
+ }
+
+ /*
+ * Reset oldtitle's lock state so that it is completely unlocked.
+ */
+ LOGIT(oldscope, '0');
+ oldtitle->u.count = 0;
+ ThinUnlock(&oldtitle->lock, CX_THINLOCK_ID(cx));
+}
+
+void
+js_LockObj(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope;
+ JSTitle *title;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+
+ /*
+ * We must test whether the GC is calling and return without mutating any
+ * state, especially cx->lockedSealedScope. Note asymmetry with respect to
+ * js_UnlockObj, which is a thin-layer on top of js_UnlockTitle.
+ */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return;
+
+ for (;;) {
+ scope = OBJ_SCOPE(obj);
+ title = &scope->title;
+ if (SCOPE_IS_SEALED(scope) && scope->object == obj &&
+ !cx->lockedSealedTitle) {
+ cx->lockedSealedTitle = title;
+ return;
+ }
+
+ js_LockTitle(cx, title);
+
+ /* If obj still has this scope, we're done. */
+ if (scope == OBJ_SCOPE(obj))
+ return;
+
+ /* Lost a race with a mutator; retry with obj's new scope. */
+ js_UnlockTitle(cx, title);
+ }
+}
+
+void
+js_UnlockObj(JSContext *cx, JSObject *obj)
+{
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ js_UnlockTitle(cx, &OBJ_SCOPE(obj)->title);
+}
+
+void
+js_InitTitle(JSContext *cx, JSTitle *title)
+{
+#ifdef JS_THREADSAFE
+ title->ownercx = cx;
+ memset(&title->lock, 0, sizeof title->lock);
+
+ /*
+ * Set u.link = NULL, not u.count = 0, in case the target architecture's
+ * null pointer has a non-zero integer representation.
+ */
+ title->u.link = NULL;
+
+#ifdef JS_DEBUG_TITLE_LOCKS
+ title->file[0] = title->file[1] = title->file[2] = title->file[3] = NULL;
+ title->line[0] = title->line[1] = title->line[2] = title->line[3] = 0;
+#endif
+#endif
+}
+
+void
+js_FinishTitle(JSContext *cx, JSTitle *title)
+{
+#ifdef JS_THREADSAFE
+ /* Title must be single-threaded at this point, so set ownercx. */
+ JS_ASSERT(title->u.count == 0);
+ title->ownercx = cx;
+ js_FinishLock(&title->lock);
+#endif
+}
+
+#ifdef DEBUG
+
+JSBool
+js_IsRuntimeLocked(JSRuntime *rt)
+{
+ return js_CurrentThreadId() == rt->rtLockOwner;
+}
+
+JSBool
+js_IsObjLocked(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope = OBJ_SCOPE(obj);
+
+ return MAP_IS_NATIVE(&scope->map) && js_IsTitleLocked(cx, &scope->title);
+}
+
+JSBool
+js_IsTitleLocked(JSContext *cx, JSTitle *title)
+{
+ /* Special case: the GC locking any object's title, see js_LockTitle. */
+ if (CX_THREAD_IS_RUNNING_GC(cx))
+ return JS_TRUE;
+
+ /* Special case: locked object owning a sealed scope, see js_LockObj. */
+ if (cx->lockedSealedTitle == title)
+ return JS_TRUE;
+
+ /*
+ * General case: the title is either exclusively owned (by cx), or it has
+ * a thin or fat lock to cope with shared (concurrent) ownership.
+ */
+ if (title->ownercx) {
+ JS_ASSERT(title->ownercx == cx || title->ownercx->thread == cx->thread);
+ return JS_TRUE;
+ }
+ return js_CurrentThreadId() ==
+ ((JSThread *)Thin_RemoveWait(ReadWord(title->lock.owner)))->id;
+}
+
+#ifdef JS_DEBUG_TITLE_LOCKS
+void
+js_SetScopeInfo(JSScope *scope, const char *file, int line)
+{
+ JSTitle *title = &scope->title;
+ if (!title->ownercx) {
+ jsrefcount count = title->u.count;
+ JS_ASSERT_IF(!SCOPE_IS_SEALED(scope), count > 0);
+ JS_ASSERT(count <= 4);
+ title->file[count - 1] = file;
+ title->line[count - 1] = line;
+ }
+}
+#endif /* JS_DEBUG_TITLE_LOCKS */
+#endif /* DEBUG */
+#endif /* JS_THREADSAFE */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslock.h b/tools/node_modules/expresso/deps/jscoverage/js/jslock.h
new file mode 100644
index 0000000..548e082
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslock.h
@@ -0,0 +1,311 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef jslock_h__
+#define jslock_h__
+
+#include "jstypes.h"
+#include "jsprvtd.h" /* for JSScope, etc. */
+#include "jspubtd.h" /* for JSRuntime, etc. */
+
+#ifdef JS_THREADSAFE
+# include "pratom.h"
+# include "prlock.h"
+# include "prcvar.h"
+# include "prthread.h"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+#ifdef JS_THREADSAFE
+
+#if (defined(_WIN32) && defined(_M_IX86)) || \
+ (defined(__GNUC__) && defined(__i386__)) || \
+ (defined(__GNUC__) && defined(__x86_64__)) || \
+ (defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)) || \
+ defined(AIX) || \
+ defined(USE_ARM_KUSER)
+# define JS_HAS_NATIVE_COMPARE_AND_SWAP 1
+#else
+# define JS_HAS_NATIVE_COMPARE_AND_SWAP 0
+#endif
+
+#if defined(JS_USE_ONLY_NSPR_LOCKS) || !JS_HAS_NATIVE_COMPARE_AND_SWAP
+# define NSPR_LOCK 1
+#else
+# undef NSPR_LOCK
+#endif
+
+#define Thin_GetWait(W) ((jsword)(W) & 0x1)
+#define Thin_SetWait(W) ((jsword)(W) | 0x1)
+#define Thin_RemoveWait(W) ((jsword)(W) & ~0x1)
+
+typedef struct JSFatLock JSFatLock;
+
+typedef struct JSThinLock {
+ jsword owner;
+ JSFatLock *fat;
+} JSThinLock;
+
+#define CX_THINLOCK_ID(cx) ((jsword)(cx)->thread)
+#define CURRENT_THREAD_IS_ME(me) (((JSThread *)me)->id == js_CurrentThreadId())
+
+typedef PRLock JSLock;
+
+typedef struct JSTitle JSTitle;
+
+struct JSTitle {
+ JSContext *ownercx; /* creating context, NULL if shared */
+ JSThinLock lock; /* binary semaphore protecting title */
+ union { /* union lockful and lock-free state: */
+ jsrefcount count; /* lock entry count for reentrancy */
+ JSTitle *link; /* next link in rt->titleSharingTodo */
+ } u;
+#ifdef JS_DEBUG_TITLE_LOCKS
+ const char *file[4]; /* file where lock was (re-)taken */
+ unsigned int line[4]; /* line where lock was (re-)taken */
+#endif
+};
+
+/*
+ * Title structures must be immediately preceded by JSObjectMap structures for
+ * maps that use titles for threadsafety. This is enforced by assertion in
+ * jsscope.h; see bug 408416 for future remedies to this somewhat fragile
+ * architecture.
+ */
+
+#define TITLE_TO_MAP(title) \
+ ((JSObjectMap *)((char *)(title) - sizeof(JSObjectMap)))
+
+/*
+ * Atomic increment and decrement for a reference counter, given jsrefcount *p.
+ * NB: jsrefcount is int32, aka PRInt32, so that pratom.h functions work.
+ */
+#define JS_ATOMIC_INCREMENT(p) PR_AtomicIncrement((PRInt32 *)(p))
+#define JS_ATOMIC_DECREMENT(p) PR_AtomicDecrement((PRInt32 *)(p))
+#define JS_ATOMIC_ADD(p,v) PR_AtomicAdd((PRInt32 *)(p), (PRInt32)(v))
+
+#define js_CurrentThreadId() (jsword)PR_GetCurrentThread()
+#define JS_NEW_LOCK() PR_NewLock()
+#define JS_DESTROY_LOCK(l) PR_DestroyLock(l)
+#define JS_ACQUIRE_LOCK(l) PR_Lock(l)
+#define JS_RELEASE_LOCK(l) PR_Unlock(l)
+
+#define JS_NEW_CONDVAR(l) PR_NewCondVar(l)
+#define JS_DESTROY_CONDVAR(cv) PR_DestroyCondVar(cv)
+#define JS_WAIT_CONDVAR(cv,to) PR_WaitCondVar(cv,to)
+#define JS_NO_TIMEOUT PR_INTERVAL_NO_TIMEOUT
+#define JS_NOTIFY_CONDVAR(cv) PR_NotifyCondVar(cv)
+#define JS_NOTIFY_ALL_CONDVAR(cv) PR_NotifyAllCondVar(cv)
+
+#ifdef JS_DEBUG_TITLE_LOCKS
+
+#define SET_OBJ_INFO(obj_, file_, line_) \
+ SET_SCOPE_INFO(OBJ_SCOPE(obj_), file_, line_)
+
+#define SET_SCOPE_INFO(scope_, file_, line_) \
+ js_SetScopeInfo(scope_, file_, line_)
+
+#endif
+
+#define JS_LOCK(cx, tl) js_Lock(cx, tl)
+#define JS_UNLOCK(cx, tl) js_Unlock(cx, tl)
+
+#define JS_LOCK_RUNTIME(rt) js_LockRuntime(rt)
+#define JS_UNLOCK_RUNTIME(rt) js_UnlockRuntime(rt)
+
+/*
+ * NB: The JS_LOCK_OBJ and JS_UNLOCK_OBJ macros work *only* on native objects
+ * (objects for which OBJ_IS_NATIVE returns true). All uses of these macros in
+ * the engine are predicated on OBJ_IS_NATIVE or equivalent checks. These uses
+ * are for optimizations above the JSObjectOps layer, under which object locks
+ * normally hide.
+ */
+#define JS_LOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->title.ownercx == (cx)) \
+ ? (void)0 \
+ : (js_LockObj(cx, obj), \
+ SET_OBJ_INFO(obj,__FILE__,__LINE__)))
+#define JS_UNLOCK_OBJ(cx,obj) ((OBJ_SCOPE(obj)->title.ownercx == (cx)) \
+ ? (void)0 : js_UnlockObj(cx, obj))
+
+#define JS_LOCK_TITLE(cx,title) \
+ ((title)->ownercx == (cx) ? (void)0 \
+ : (js_LockTitle(cx, (title)), \
+ SET_TITLE_INFO(title,__FILE__,__LINE__)))
+
+#define JS_UNLOCK_TITLE(cx,title) ((title)->ownercx == (cx) ? (void)0 \
+ : js_UnlockTitle(cx, title))
+
+#define JS_LOCK_SCOPE(cx,scope) JS_LOCK_TITLE(cx,&(scope)->title)
+#define JS_UNLOCK_SCOPE(cx,scope) JS_UNLOCK_TITLE(cx,&(scope)->title)
+
+#define JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope) \
+ js_TransferTitle(cx, &scope->title, &newscope->title)
+
+
+extern void js_Lock(JSContext *cx, JSThinLock *tl);
+extern void js_Unlock(JSContext *cx, JSThinLock *tl);
+extern void js_LockRuntime(JSRuntime *rt);
+extern void js_UnlockRuntime(JSRuntime *rt);
+extern void js_LockObj(JSContext *cx, JSObject *obj);
+extern void js_UnlockObj(JSContext *cx, JSObject *obj);
+extern void js_InitTitle(JSContext *cx, JSTitle *title);
+extern void js_FinishTitle(JSContext *cx, JSTitle *title);
+extern void js_LockTitle(JSContext *cx, JSTitle *title);
+extern void js_UnlockTitle(JSContext *cx, JSTitle *title);
+extern int js_SetupLocks(int,int);
+extern void js_CleanupLocks();
+extern void js_TransferTitle(JSContext *, JSTitle *, JSTitle *);
+extern JS_FRIEND_API(jsval)
+js_GetSlotThreadSafe(JSContext *, JSObject *, uint32);
+extern void js_SetSlotThreadSafe(JSContext *, JSObject *, uint32, jsval);
+extern void js_InitLock(JSThinLock *);
+extern void js_FinishLock(JSThinLock *);
+extern void js_FinishSharingTitle(JSContext *cx, JSTitle *title);
+
+#ifdef DEBUG
+
+#define JS_IS_RUNTIME_LOCKED(rt) js_IsRuntimeLocked(rt)
+#define JS_IS_OBJ_LOCKED(cx,obj) js_IsObjLocked(cx,obj)
+#define JS_IS_TITLE_LOCKED(cx,title) js_IsTitleLocked(cx,title)
+
+extern JSBool js_IsRuntimeLocked(JSRuntime *rt);
+extern JSBool js_IsObjLocked(JSContext *cx, JSObject *obj);
+extern JSBool js_IsTitleLocked(JSContext *cx, JSTitle *title);
+#ifdef JS_DEBUG_TITLE_LOCKS
+extern void js_SetScopeInfo(JSScope *scope, const char *file, int line);
+#endif
+
+#else
+
+#define JS_IS_RUNTIME_LOCKED(rt) 0
+#define JS_IS_OBJ_LOCKED(cx,obj) 1
+#define JS_IS_TITLE_LOCKED(cx,title) 1
+
+#endif /* DEBUG */
+
+#define JS_LOCK_OBJ_VOID(cx, obj, e) \
+ JS_BEGIN_MACRO \
+ JS_LOCK_OBJ(cx, obj); \
+ e; \
+ JS_UNLOCK_OBJ(cx, obj); \
+ JS_END_MACRO
+
+#define JS_LOCK_VOID(cx, e) \
+ JS_BEGIN_MACRO \
+ JSRuntime *_rt = (cx)->runtime; \
+ JS_LOCK_RUNTIME_VOID(_rt, e); \
+ JS_END_MACRO
+
+#else /* !JS_THREADSAFE */
+
+#define JS_ATOMIC_INCREMENT(p) (++*(p))
+#define JS_ATOMIC_DECREMENT(p) (--*(p))
+#define JS_ATOMIC_ADD(p,v) (*(p) += (v))
+
+#define JS_CurrentThreadId() 0
+#define JS_NEW_LOCK() NULL
+#define JS_DESTROY_LOCK(l) ((void)0)
+#define JS_ACQUIRE_LOCK(l) ((void)0)
+#define JS_RELEASE_LOCK(l) ((void)0)
+#define JS_LOCK(cx, tl) ((void)0)
+#define JS_UNLOCK(cx, tl) ((void)0)
+
+#define JS_NEW_CONDVAR(l) NULL
+#define JS_DESTROY_CONDVAR(cv) ((void)0)
+#define JS_WAIT_CONDVAR(cv,to) ((void)0)
+#define JS_NOTIFY_CONDVAR(cv) ((void)0)
+#define JS_NOTIFY_ALL_CONDVAR(cv) ((void)0)
+
+#define JS_LOCK_RUNTIME(rt) ((void)0)
+#define JS_UNLOCK_RUNTIME(rt) ((void)0)
+#define JS_LOCK_OBJ(cx,obj) ((void)0)
+#define JS_UNLOCK_OBJ(cx,obj) ((void)0)
+#define JS_LOCK_OBJ_VOID(cx,obj,e) (e)
+#define JS_LOCK_SCOPE(cx,scope) ((void)0)
+#define JS_UNLOCK_SCOPE(cx,scope) ((void)0)
+#define JS_TRANSFER_SCOPE_LOCK(c,o,n) ((void)0)
+
+#define JS_IS_RUNTIME_LOCKED(rt) 1
+#define JS_IS_OBJ_LOCKED(cx,obj) 1
+#define JS_IS_TITLE_LOCKED(cx,title) 1
+#define JS_LOCK_VOID(cx, e) JS_LOCK_RUNTIME_VOID((cx)->runtime, e)
+
+#endif /* !JS_THREADSAFE */
+
+#define JS_LOCK_RUNTIME_VOID(rt,e) \
+ JS_BEGIN_MACRO \
+ JS_LOCK_RUNTIME(rt); \
+ e; \
+ JS_UNLOCK_RUNTIME(rt); \
+ JS_END_MACRO
+
+#define JS_LOCK_GC(rt) JS_ACQUIRE_LOCK((rt)->gcLock)
+#define JS_UNLOCK_GC(rt) JS_RELEASE_LOCK((rt)->gcLock)
+#define JS_LOCK_GC_VOID(rt,e) (JS_LOCK_GC(rt), (e), JS_UNLOCK_GC(rt))
+#define JS_AWAIT_GC_DONE(rt) JS_WAIT_CONDVAR((rt)->gcDone, JS_NO_TIMEOUT)
+#define JS_NOTIFY_GC_DONE(rt) JS_NOTIFY_ALL_CONDVAR((rt)->gcDone)
+#define JS_AWAIT_REQUEST_DONE(rt) JS_WAIT_CONDVAR((rt)->requestDone, \
+ JS_NO_TIMEOUT)
+#define JS_NOTIFY_REQUEST_DONE(rt) JS_NOTIFY_CONDVAR((rt)->requestDone)
+
+#ifndef SET_OBJ_INFO
+#define SET_OBJ_INFO(obj,f,l) ((void)0)
+#endif
+#ifndef SET_TITLE_INFO
+#define SET_TITLE_INFO(title,f,l) ((void)0)
+#endif
+
+#ifdef JS_THREADSAFE
+
+extern JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv);
+
+#else
+
+static inline JSBool
+js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+{
+ return (*w == ov) ? *w = nv, JS_TRUE : JS_FALSE;
+}
+
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jslock_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm b/tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm
new file mode 100644
index 0000000..95353ba
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslocko.asm
@@ -0,0 +1,60 @@
+; -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
+
+; ***** BEGIN LICENSE BLOCK *****
+; Version: MPL 1.1/GPL 2.0/LGPL 2.1
+;
+; The contents of this file are subject to the Mozilla Public License Version
+; 1.1 (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.mozilla.org/MPL/
+;
+; Software distributed under the License is distributed on an "AS IS" basis,
+; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+; for the specific language governing rights and limitations under the
+; License.
+;
+; The Original Code is an OS/2 implementation of js_CompareAndSwap in assembly.
+;
+; The Initial Developer of the Original Code is
+; IBM Corporation.
+; Portions created by the Initial Developer are Copyright (C) 2001
+; the Initial Developer. All Rights Reserved.
+;
+; Contributor(s):
+;
+; Alternatively, the contents of this file may be used under the terms of
+; either the GNU General Public License Version 2 or later (the "GPL"), or
+; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+; in which case the provisions of the GPL or the LGPL are applicable instead
+; of those above. If you wish to allow use of your version of this file only
+; under the terms of either the GPL or the LGPL, and not to allow others to
+; use your version of this file under the terms of the MPL, indicate your
+; decision by deleting the provisions above and replace them with the notice
+; and other provisions required by the GPL or the LGPL. If you do not delete
+; the provisions above, a recipient may use your version of this file under
+; the terms of any one of the MPL, the GPL or the LGPL.
+;
+; ***** END LICENSE BLOCK *****
+
+ .486P
+ .MODEL FLAT, OPTLINK
+ .STACK
+
+ .CODE
+
+;;;---------------------------------------------------------------------
+;;; int _Optlink js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
+;;;---------------------------------------------------------------------
+js_CompareAndSwap PROC OPTLINK EXPORT
+ push ebx
+ mov ebx, eax
+ mov eax, edx
+ mov edx, ebx
+ lock cmpxchg [ebx], ecx
+ sete al
+ and eax, 1h
+ pop ebx
+ ret
+js_CompareAndSwap endp
+
+ END
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp
new file mode 100644
index 0000000..84f4f51
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslog2.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include "jsbit.h"
+#include "jsutil.h"
+
+/*
+** Compute the log of the least power of 2 greater than or equal to n
+*/
+JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 n)
+{
+ JSIntn log2;
+
+ JS_CEILING_LOG2(log2, n);
+ return log2;
+}
+
+/*
+** Compute the log of the greatest power of 2 less than or equal to n.
+** This really just finds the highest set bit in the word.
+*/
+JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 n)
+{
+ JSIntn log2;
+
+ JS_FLOOR_LOG2(log2, n);
+ return log2;
+}
+
+/*
+ * js_FloorLog2wImpl has to be defined only for 64-bit non-GCC case.
+ */
+#if !defined(JS_HAS_BUILTIN_BITSCAN64) && JS_BYTES_PER_WORD == 8
+
+JSUword
+js_FloorLog2wImpl(JSUword n)
+{
+ JSUword log2, m;
+
+ JS_ASSERT(n != 0);
+
+ log2 = 0;
+ m = n >> 32;
+ if (m != 0) { n = m; log2 = 32; }
+ m = n >> 16;
+ if (m != 0) { n = m; log2 |= 16; }
+ m = n >> 8;
+ if (m != 0) { n = m; log2 |= 8; }
+ m = n >> 4;
+ if (m != 0) { n = m; log2 |= 4; }
+ m = n >> 2;
+ if (m != 0) { n = m; log2 |= 2; }
+ log2 |= (n >> 1);
+
+ return log2;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp
new file mode 100644
index 0000000..71dd06d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslong.cpp
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jslong.h"
+
+#ifndef JS_HAVE_LONG_LONG
+/*
+** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1.
+*/
+static void norm_udivmod32(JSUint32 *qp, JSUint32 *rp, JSUint64 a, JSUint32 b)
+{
+ JSUint32 d1, d0, q1, q0;
+ JSUint32 r1, r0, m;
+
+ d1 = jshi16(b);
+ d0 = jslo16(b);
+ r1 = a.hi % d1;
+ q1 = a.hi / d1;
+ m = q1 * d0;
+ r1 = (r1 << 16) | jshi16(a.lo);
+ if (r1 < m) {
+ q1--, r1 += b;
+ if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */
+ && r1 < m) {
+ q1--, r1 += b;
+ }
+ }
+ r1 -= m;
+ r0 = r1 % d1;
+ q0 = r1 / d1;
+ m = q0 * d0;
+ r0 = (r0 << 16) | jslo16(a.lo);
+ if (r0 < m) {
+ q0--, r0 += b;
+ if (r0 >= b
+ && r0 < m) {
+ q0--, r0 += b;
+ }
+ }
+ *qp = (q1 << 16) | q0;
+ *rp = r0 - m;
+}
+
+static JSUint32 CountLeadingZeros(JSUint32 a)
+{
+ JSUint32 t;
+ JSUint32 r = 32;
+
+ if ((t = a >> 16) != 0)
+ r -= 16, a = t;
+ if ((t = a >> 8) != 0)
+ r -= 8, a = t;
+ if ((t = a >> 4) != 0)
+ r -= 4, a = t;
+ if ((t = a >> 2) != 0)
+ r -= 2, a = t;
+ if ((t = a >> 1) != 0)
+ r -= 1, a = t;
+ if (a & 1)
+ r--;
+ return r;
+}
+
+JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b)
+{
+ JSUint32 n0, n1, n2;
+ JSUint32 q0, q1;
+ JSUint32 rsh, lsh;
+
+ n0 = a.lo;
+ n1 = a.hi;
+
+ if (b.hi == 0) {
+ if (b.lo > n1) {
+ /* (0 q0) = (n1 n0) / (0 D0) */
+
+ lsh = CountLeadingZeros(b.lo);
+
+ if (lsh) {
+ /*
+ * Normalize, i.e. make the most significant bit of the
+ * denominator be set.
+ */
+ b.lo = b.lo << lsh;
+ n1 = (n1 << lsh) | (n0 >> (32 - lsh));
+ n0 = n0 << lsh;
+ }
+
+ a.lo = n0, a.hi = n1;
+ norm_udivmod32(&q0, &n0, a, b.lo);
+ q1 = 0;
+
+ /* remainder is in n0 >> lsh */
+ } else {
+ /* (q1 q0) = (n1 n0) / (0 d0) */
+
+ if (b.lo == 0) /* user wants to divide by zero! */
+ b.lo = 1 / b.lo; /* so go ahead and crash */
+
+ lsh = CountLeadingZeros(b.lo);
+
+ if (lsh == 0) {
+ /*
+ * From (n1 >= b.lo)
+ * && (the most significant bit of b.lo is set),
+ * conclude that
+ * (the most significant bit of n1 is set)
+ * && (the leading quotient digit q1 = 1).
+ *
+ * This special case is necessary, not an optimization
+ * (Shifts counts of 32 are undefined).
+ */
+ n1 -= b.lo;
+ q1 = 1;
+ } else {
+ /*
+ * Normalize.
+ */
+ rsh = 32 - lsh;
+
+ b.lo = b.lo << lsh;
+ n2 = n1 >> rsh;
+ n1 = (n1 << lsh) | (n0 >> rsh);
+ n0 = n0 << lsh;
+
+ a.lo = n1, a.hi = n2;
+ norm_udivmod32(&q1, &n1, a, b.lo);
+ }
+
+ /* n1 != b.lo... */
+
+ a.lo = n0, a.hi = n1;
+ norm_udivmod32(&q0, &n0, a, b.lo);
+
+ /* remainder in n0 >> lsh */
+ }
+
+ if (rp) {
+ rp->lo = n0 >> lsh;
+ rp->hi = 0;
+ }
+ } else {
+ if (b.hi > n1) {
+ /* (0 0) = (n1 n0) / (D1 d0) */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* remainder in (n1 n0) */
+ if (rp) {
+ rp->lo = n0;
+ rp->hi = n1;
+ }
+ } else {
+ /* (0 q0) = (n1 n0) / (d1 d0) */
+
+ lsh = CountLeadingZeros(b.hi);
+ if (lsh == 0) {
+ /*
+ * From (n1 >= b.hi)
+ * && (the most significant bit of b.hi is set),
+ * conclude that
+ * (the most significant bit of n1 is set)
+ * && (the quotient digit q0 = 0 or 1).
+ *
+ * This special case is necessary, not an optimization.
+ */
+
+ /*
+ * The condition on the next line takes advantage of that
+ * n1 >= b.hi (true due to control flow).
+ */
+ if (n1 > b.hi || n0 >= b.lo) {
+ q0 = 1;
+ a.lo = n0, a.hi = n1;
+ JSLL_SUB(a, a, b);
+ } else {
+ q0 = 0;
+ }
+ q1 = 0;
+
+ if (rp) {
+ rp->lo = n0;
+ rp->hi = n1;
+ }
+ } else {
+ JSInt64 m;
+
+ /*
+ * Normalize.
+ */
+ rsh = 32 - lsh;
+
+ b.hi = (b.hi << lsh) | (b.lo >> rsh);
+ b.lo = b.lo << lsh;
+ n2 = n1 >> rsh;
+ n1 = (n1 << lsh) | (n0 >> rsh);
+ n0 = n0 << lsh;
+
+ a.lo = n1, a.hi = n2;
+ norm_udivmod32(&q0, &n1, a, b.hi);
+ JSLL_MUL32(m, q0, b.lo);
+
+ if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) {
+ q0--;
+ JSLL_SUB(m, m, b);
+ }
+
+ q1 = 0;
+
+ /* Remainder is ((n1 n0) - (m1 m0)) >> lsh */
+ if (rp) {
+ a.lo = n0, a.hi = n1;
+ JSLL_SUB(a, a, m);
+ rp->lo = (a.hi << rsh) | (a.lo >> lsh);
+ rp->hi = a.hi >> lsh;
+ }
+ }
+ }
+ }
+
+ if (qp) {
+ qp->lo = q0;
+ qp->hi = q1;
+ }
+}
+#endif /* !JS_HAVE_LONG_LONG */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jslong.h b/tools/node_modules/expresso/deps/jscoverage/js/jslong.h
new file mode 100644
index 0000000..e5bd4d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jslong.h
@@ -0,0 +1,412 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+** File: jslong.h
+** Description: Portable access to 64 bit numerics
+**
+** Long-long (64-bit signed integer type) support. Some C compilers
+** don't support 64 bit integers yet, so we use these macros to
+** support both machines that do and don't.
+**/
+#ifndef jslong_h___
+#define jslong_h___
+
+#include "jstypes.h"
+
+JS_BEGIN_EXTERN_C
+
+#ifdef JS_HAVE_LONG_LONG
+
+#if JS_BYTES_PER_LONG == 8
+#define JSLL_INIT(hi, lo) ((hi ## L << 32) + lo ## L)
+#elif (defined(WIN32) || defined(WIN16)) && !defined(__GNUC__)
+#define JSLL_INIT(hi, lo) ((hi ## i64 << 32) + lo ## i64)
+#else
+#define JSLL_INIT(hi, lo) ((hi ## LL << 32) + lo ## LL)
+#endif
+
+/***********************************************************************
+** MACROS: JSLL_*
+** DESCRIPTION:
+** The following macros define portable access to the 64 bit
+** math facilities.
+**
+***********************************************************************/
+
+/***********************************************************************
+** MACROS: JSLL_<relational operators>
+**
+** JSLL_IS_ZERO Test for zero
+** JSLL_EQ Test for equality
+** JSLL_NE Test for inequality
+** JSLL_GE_ZERO Test for zero or positive
+** JSLL_CMP Compare two values
+***********************************************************************/
+#define JSLL_IS_ZERO(a) ((a) == 0)
+#define JSLL_EQ(a, b) ((a) == (b))
+#define JSLL_NE(a, b) ((a) != (b))
+#define JSLL_GE_ZERO(a) ((a) >= 0)
+#define JSLL_CMP(a, op, b) ((JSInt64)(a) op (JSInt64)(b))
+#define JSLL_UCMP(a, op, b) ((JSUint64)(a) op (JSUint64)(b))
+
+/***********************************************************************
+** MACROS: JSLL_<logical operators>
+**
+** JSLL_AND Logical and
+** JSLL_OR Logical or
+** JSLL_XOR Logical exclusion
+** JSLL_OR2 A disgusting deviation
+** JSLL_NOT Negation (one's compliment)
+***********************************************************************/
+#define JSLL_AND(r, a, b) ((r) = (a) & (b))
+#define JSLL_OR(r, a, b) ((r) = (a) | (b))
+#define JSLL_XOR(r, a, b) ((r) = (a) ^ (b))
+#define JSLL_OR2(r, a) ((r) = (r) | (a))
+#define JSLL_NOT(r, a) ((r) = ~(a))
+
+/***********************************************************************
+** MACROS: JSLL_<mathematical operators>
+**
+** JSLL_NEG Negation (two's compliment)
+** JSLL_ADD Summation (two's compliment)
+** JSLL_SUB Difference (two's compliment)
+***********************************************************************/
+#define JSLL_NEG(r, a) ((r) = -(a))
+#define JSLL_ADD(r, a, b) ((r) = (a) + (b))
+#define JSLL_SUB(r, a, b) ((r) = (a) - (b))
+
+/***********************************************************************
+** MACROS: JSLL_<mathematical operators>
+**
+** JSLL_MUL Product (two's compliment)
+** JSLL_DIV Quotient (two's compliment)
+** JSLL_MOD Modulus (two's compliment)
+***********************************************************************/
+#define JSLL_MUL(r, a, b) ((r) = (a) * (b))
+#define JSLL_DIV(r, a, b) ((r) = (a) / (b))
+#define JSLL_MOD(r, a, b) ((r) = (a) % (b))
+
+/***********************************************************************
+** MACROS: JSLL_<shifting operators>
+**
+** JSLL_SHL Shift left [0..64] bits
+** JSLL_SHR Shift right [0..64] bits with sign extension
+** JSLL_USHR Unsigned shift right [0..64] bits
+** JSLL_ISHL Signed shift left [0..64] bits
+***********************************************************************/
+#define JSLL_SHL(r, a, b) ((r) = (JSInt64)(a) << (b))
+#define JSLL_SHR(r, a, b) ((r) = (JSInt64)(a) >> (b))
+#define JSLL_USHR(r, a, b) ((r) = (JSUint64)(a) >> (b))
+#define JSLL_ISHL(r, a, b) ((r) = (JSInt64)(a) << (b))
+
+/***********************************************************************
+** MACROS: JSLL_<conversion operators>
+**
+** JSLL_L2I Convert to signed 32 bit
+** JSLL_L2UI Convert to unsigned 32 bit
+** JSLL_L2F Convert to floating point
+** JSLL_L2D Convert to floating point
+** JSLL_I2L Convert signed to 64 bit
+** JSLL_UI2L Convert unsigned to 64 bit
+** JSLL_F2L Convert float to 64 bit
+** JSLL_D2L Convert float to 64 bit
+***********************************************************************/
+#define JSLL_L2I(i, l) ((i) = (JSInt32)(l))
+#define JSLL_L2UI(ui, l) ((ui) = (JSUint32)(l))
+#define JSLL_L2F(f, l) ((f) = (JSFloat64)(l))
+#define JSLL_L2D(d, l) ((d) = (JSFloat64)(l))
+
+#define JSLL_I2L(l, i) ((l) = (JSInt64)(i))
+#define JSLL_UI2L(l, ui) ((l) = (JSInt64)(ui))
+#define JSLL_F2L(l, f) ((l) = (JSInt64)(f))
+#define JSLL_D2L(l, d) ((l) = (JSInt64)(d))
+
+/***********************************************************************
+** MACROS: JSLL_UDIVMOD
+** DESCRIPTION:
+** Produce both a quotient and a remainder given an unsigned
+** INPUTS: JSUint64 a: The dividend of the operation
+** JSUint64 b: The quotient of the operation
+** OUTPUTS: JSUint64 *qp: pointer to quotient
+** JSUint64 *rp: pointer to remainder
+***********************************************************************/
+#define JSLL_UDIVMOD(qp, rp, a, b) \
+ (*(qp) = ((JSUint64)(a) / (b)), \
+ *(rp) = ((JSUint64)(a) % (b)))
+
+#else /* !JS_HAVE_LONG_LONG */
+
+#ifdef IS_LITTLE_ENDIAN
+#define JSLL_INIT(hi, lo) {JS_INT32(lo), JS_INT32(hi)}
+#else
+#define JSLL_INIT(hi, lo) {JS_INT32(hi), JS_INT32(lo)}
+#endif
+
+#define JSLL_IS_ZERO(a) (((a).hi == 0) && ((a).lo == 0))
+#define JSLL_EQ(a, b) (((a).hi == (b).hi) && ((a).lo == (b).lo))
+#define JSLL_NE(a, b) (((a).hi != (b).hi) || ((a).lo != (b).lo))
+#define JSLL_GE_ZERO(a) (((a).hi >> 31) == 0)
+
+#ifdef DEBUG
+#define JSLL_CMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_CMP(a, op, b))
+#define JSLL_UCMP(a, op, b) (JS_ASSERT((#op)[1] != '='), JSLL_REAL_UCMP(a, op, b))
+#else
+#define JSLL_CMP(a, op, b) JSLL_REAL_CMP(a, op, b)
+#define JSLL_UCMP(a, op, b) JSLL_REAL_UCMP(a, op, b)
+#endif
+
+#define JSLL_REAL_CMP(a,op,b) (((JSInt32)(a).hi op (JSInt32)(b).hi) || \
+ (((a).hi == (b).hi) && ((a).lo op (b).lo)))
+#define JSLL_REAL_UCMP(a,op,b) (((a).hi op (b).hi) || \
+ (((a).hi == (b).hi) && ((a).lo op (b).lo)))
+
+#define JSLL_AND(r, a, b) ((r).lo = (a).lo & (b).lo, \
+ (r).hi = (a).hi & (b).hi)
+#define JSLL_OR(r, a, b) ((r).lo = (a).lo | (b).lo, \
+ (r).hi = (a).hi | (b).hi)
+#define JSLL_XOR(r, a, b) ((r).lo = (a).lo ^ (b).lo, \
+ (r).hi = (a).hi ^ (b).hi)
+#define JSLL_OR2(r, a) ((r).lo = (r).lo | (a).lo, \
+ (r).hi = (r).hi | (a).hi)
+#define JSLL_NOT(r, a) ((r).lo = ~(a).lo, \
+ (r).hi = ~(a).hi)
+
+#define JSLL_NEG(r, a) ((r).lo = -(JSInt32)(a).lo, \
+ (r).hi = -(JSInt32)(a).hi - ((r).lo != 0))
+#define JSLL_ADD(r, a, b) { \
+ JSInt64 _a, _b; \
+ _a = a; _b = b; \
+ (r).lo = _a.lo + _b.lo; \
+ (r).hi = _a.hi + _b.hi + ((r).lo < _b.lo); \
+}
+
+#define JSLL_SUB(r, a, b) { \
+ JSInt64 _a, _b; \
+ _a = a; _b = b; \
+ (r).lo = _a.lo - _b.lo; \
+ (r).hi = _a.hi - _b.hi - (_a.lo < _b.lo); \
+}
+
+#define JSLL_MUL(r, a, b) { \
+ JSInt64 _a, _b; \
+ _a = a; _b = b; \
+ JSLL_MUL32(r, _a.lo, _b.lo); \
+ (r).hi += _a.hi * _b.lo + _a.lo * _b.hi; \
+}
+
+#define jslo16(a) ((a) & JS_BITMASK(16))
+#define jshi16(a) ((a) >> 16)
+
+#define JSLL_MUL32(r, a, b) { \
+ JSUint32 _a1, _a0, _b1, _b0, _y0, _y1, _y2, _y3; \
+ _a1 = jshi16(a), _a0 = jslo16(a); \
+ _b1 = jshi16(b), _b0 = jslo16(b); \
+ _y0 = _a0 * _b0; \
+ _y1 = _a0 * _b1; \
+ _y2 = _a1 * _b0; \
+ _y3 = _a1 * _b1; \
+ _y1 += jshi16(_y0); /* can't carry */ \
+ _y1 += _y2; /* might carry */ \
+ if (_y1 < _y2) \
+ _y3 += (JSUint32)(JS_BIT(16)); /* propagate */ \
+ (r).lo = (jslo16(_y1) << 16) + jslo16(_y0); \
+ (r).hi = _y3 + jshi16(_y1); \
+}
+
+#define JSLL_UDIVMOD(qp, rp, a, b) jsll_udivmod(qp, rp, a, b)
+
+extern JS_PUBLIC_API(void) jsll_udivmod(JSUint64 *qp, JSUint64 *rp, JSUint64 a, JSUint64 b);
+
+#define JSLL_DIV(r, a, b) { \
+ JSInt64 _a, _b; \
+ JSUint32 _negative = (JSInt32)(a).hi < 0; \
+ if (_negative) { \
+ JSLL_NEG(_a, a); \
+ } else { \
+ _a = a; \
+ } \
+ if ((JSInt32)(b).hi < 0) { \
+ _negative ^= 1; \
+ JSLL_NEG(_b, b); \
+ } else { \
+ _b = b; \
+ } \
+ JSLL_UDIVMOD(&(r), 0, _a, _b); \
+ if (_negative) \
+ JSLL_NEG(r, r); \
+}
+
+#define JSLL_MOD(r, a, b) { \
+ JSInt64 _a, _b; \
+ JSUint32 _negative = (JSInt32)(a).hi < 0; \
+ if (_negative) { \
+ JSLL_NEG(_a, a); \
+ } else { \
+ _a = a; \
+ } \
+ if ((JSInt32)(b).hi < 0) { \
+ JSLL_NEG(_b, b); \
+ } else { \
+ _b = b; \
+ } \
+ JSLL_UDIVMOD(0, &(r), _a, _b); \
+ if (_negative) \
+ JSLL_NEG(r, r); \
+}
+
+#define JSLL_SHL(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = _a.lo << ((b) & 31); \
+ (r).hi = (_a.hi << ((b) & 31)) | (_a.lo >> (32 - (b))); \
+ } else { \
+ (r).lo = 0; \
+ (r).hi = _a.lo << ((b) & 31); \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+/* a is an JSInt32, b is JSInt32, r is JSInt64 */
+#define JSLL_ISHL(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a.lo = (a); \
+ _a.hi = 0; \
+ if ((b) < 32) { \
+ (r).lo = (a) << ((b) & 31); \
+ (r).hi = ((a) >> (32 - (b))); \
+ } else { \
+ (r).lo = 0; \
+ (r).hi = (a) << ((b) & 31); \
+ } \
+ } else { \
+ (r).lo = (a); \
+ (r).hi = 0; \
+ } \
+}
+
+#define JSLL_SHR(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
+ (r).hi = (JSInt32)_a.hi >> ((b) & 31); \
+ } else { \
+ (r).lo = (JSInt32)_a.hi >> ((b) & 31); \
+ (r).hi = (JSInt32)_a.hi >> 31; \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+#define JSLL_USHR(r, a, b) { \
+ if (b) { \
+ JSInt64 _a; \
+ _a = a; \
+ if ((b) < 32) { \
+ (r).lo = (_a.hi << (32 - (b))) | (_a.lo >> ((b) & 31)); \
+ (r).hi = _a.hi >> ((b) & 31); \
+ } else { \
+ (r).lo = _a.hi >> ((b) & 31); \
+ (r).hi = 0; \
+ } \
+ } else { \
+ (r) = (a); \
+ } \
+}
+
+#define JSLL_L2I(i, l) ((i) = (l).lo)
+#define JSLL_L2UI(ui, l) ((ui) = (l).lo)
+#define JSLL_L2F(f, l) { double _d; JSLL_L2D(_d, l); (f) = (JSFloat64)_d; }
+
+#define JSLL_L2D(d, l) { \
+ int _negative; \
+ JSInt64 _absval; \
+ \
+ _negative = (l).hi >> 31; \
+ if (_negative) { \
+ JSLL_NEG(_absval, l); \
+ } else { \
+ _absval = l; \
+ } \
+ (d) = (double)_absval.hi * 4.294967296e9 + _absval.lo; \
+ if (_negative) \
+ (d) = -(d); \
+}
+
+#define JSLL_I2L(l, i) { JSInt32 _i = (i) >> 31; (l).lo = (i); (l).hi = _i; }
+#define JSLL_UI2L(l, ui) ((l).lo = (ui), (l).hi = 0)
+#define JSLL_F2L(l, f) { double _d = (double)f; JSLL_D2L(l, _d); }
+
+#define JSLL_D2L(l, d) { \
+ int _negative; \
+ double _absval, _d_hi; \
+ JSInt64 _lo_d; \
+ \
+ _negative = ((d) < 0); \
+ _absval = _negative ? -(d) : (d); \
+ \
+ (l).hi = _absval / 4.294967296e9; \
+ (l).lo = 0; \
+ JSLL_L2D(_d_hi, l); \
+ _absval -= _d_hi; \
+ _lo_d.hi = 0; \
+ if (_absval < 0) { \
+ _lo_d.lo = -_absval; \
+ JSLL_SUB(l, l, _lo_d); \
+ } else { \
+ _lo_d.lo = _absval; \
+ JSLL_ADD(l, l, _lo_d); \
+ } \
+ \
+ if (_negative) \
+ JSLL_NEG(l, l); \
+}
+
+#endif /* !JS_HAVE_LONG_LONG */
+
+JS_END_EXTERN_C
+
+#endif /* jslong_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp
new file mode 100644
index 0000000..75fa900
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.cpp
@@ -0,0 +1,721 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS math package.
+ */
+#include "jsstddef.h"
+#include "jslibmath.h"
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jslong.h"
+#include "prmjtime.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jslock.h"
+#include "jsmath.h"
+#include "jsnum.h"
+#include "jsobj.h"
+
+extern jsdouble js_NaN;
+
+#ifndef M_E
+#define M_E 2.7182818284590452354
+#endif
+#ifndef M_LOG2E
+#define M_LOG2E 1.4426950408889634074
+#endif
+#ifndef M_LOG10E
+#define M_LOG10E 0.43429448190325182765
+#endif
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+#ifndef M_LN10
+#define M_LN10 2.30258509299404568402
+#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_SQRT2
+#define M_SQRT2 1.41421356237309504880
+#endif
+#ifndef M_SQRT1_2
+#define M_SQRT1_2 0.70710678118654752440
+#endif
+
+static JSConstDoubleSpec math_constants[] = {
+ {M_E, "E", 0, {0,0,0}},
+ {M_LOG2E, "LOG2E", 0, {0,0,0}},
+ {M_LOG10E, "LOG10E", 0, {0,0,0}},
+ {M_LN2, "LN2", 0, {0,0,0}},
+ {M_LN10, "LN10", 0, {0,0,0}},
+ {M_PI, "PI", 0, {0,0,0}},
+ {M_SQRT2, "SQRT2", 0, {0,0,0}},
+ {M_SQRT1_2, "SQRT1_2", 0, {0,0,0}},
+ {0,0,0,{0,0,0}}
+};
+
+JSClass js_MathClass = {
+ js_Math_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Math),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+math_abs(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = fabs(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_acos(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x < -1 || 1 < x) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+#endif
+ z = acos(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_asin(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x < -1 || 1 < x) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+#endif
+ z = asin(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_atan(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = atan(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_atan2(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, y, z;
+
+ if (argc <= 1) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ y = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+#if defined(_MSC_VER)
+ /*
+ * MSVC's atan2 does not yield the result demanded by ECMA when both x
+ * and y are infinite.
+ * - The result is a multiple of pi/4.
+ * - The sign of x determines the sign of the result.
+ * - The sign of y determines the multiplicator, 1 or 3.
+ */
+ if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
+ z = js_copysign(M_PI / 4, x);
+ if (y < 0)
+ z *= 3;
+ return js_NewDoubleInRootedValue(cx, z, vp);
+ }
+#endif
+
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x == 0) {
+ if (JSDOUBLE_IS_NEGZERO(y)) {
+ z = js_copysign(M_PI, x);
+ return js_NewDoubleInRootedValue(cx, z, vp);
+ }
+ if (y == 0) {
+ z = x;
+ return js_NewDoubleInRootedValue(cx, z, vp);
+ }
+ }
+#endif
+ z = atan2(x, y);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_ceil(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = ceil(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_cos(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = cos(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_exp(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#ifdef _WIN32
+ if (!JSDOUBLE_IS_NaN(x)) {
+ if (x == *cx->runtime->jsPositiveInfinity) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+ return JS_TRUE;
+ }
+ if (x == *cx->runtime->jsNegativeInfinity) {
+ *vp = JSVAL_ZERO;
+ return JS_TRUE;
+ }
+ }
+#endif
+ z = exp(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_floor(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = floor(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_log(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (x < 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+#endif
+ z = log(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_max(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z = *cx->runtime->jsNegativeInfinity;
+ jsval *argv;
+ uintN i;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
+ return JS_TRUE;
+ }
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ x = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (JSDOUBLE_IS_NaN(x)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ if (x == 0 && x == z) {
+ if (js_copysign(1.0, z) == -1)
+ z = x;
+ } else {
+ z = (x > z) ? x : z;
+ }
+ }
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_min(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z = *cx->runtime->jsPositiveInfinity;
+ jsval *argv;
+ uintN i;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsPositiveInfinity);
+ return JS_TRUE;
+ }
+ argv = vp + 2;
+ for (i = 0; i < argc; i++) {
+ x = js_ValueToNumber(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i]))
+ return JS_FALSE;
+ if (JSDOUBLE_IS_NaN(x)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ if (x == 0 && x == z) {
+ if (js_copysign(1.0, x) == -1)
+ z = x;
+ } else {
+ z = (x < z) ? x : z;
+ }
+ }
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_pow(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, y, z;
+
+ if (argc <= 1) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ y = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ /*
+ * Because C99 and ECMA specify different behavior for pow(),
+ * we need to wrap the libm call to make it ECMA compliant.
+ */
+ if (!JSDOUBLE_IS_FINITE(y) && (x == 1.0 || x == -1.0)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ /* pow(x, +-0) is always 1, even for x = NaN. */
+ if (y == 0) {
+ *vp = JSVAL_ONE;
+ return JS_TRUE;
+ }
+ z = pow(x, y);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+/*
+ * Math.random() support, lifted from java.util.Random.java.
+ */
+static void
+random_setSeed(JSRuntime *rt, int64 seed)
+{
+ int64 tmp;
+
+ JSLL_I2L(tmp, 1000);
+ JSLL_DIV(seed, seed, tmp);
+ JSLL_XOR(tmp, seed, rt->rngMultiplier);
+ JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
+}
+
+void
+js_random_init(JSRuntime *rt)
+{
+ int64 tmp, tmp2;
+
+ /* Do at most once. */
+ if (rt->rngInitialized)
+ return;
+ rt->rngInitialized = JS_TRUE;
+
+ /* rt->rngMultiplier = 0x5DEECE66DL */
+ JSLL_ISHL(tmp, 0x5, 32);
+ JSLL_UI2L(tmp2, 0xDEECE66DL);
+ JSLL_OR(rt->rngMultiplier, tmp, tmp2);
+
+ /* rt->rngAddend = 0xBL */
+ JSLL_I2L(rt->rngAddend, 0xBL);
+
+ /* rt->rngMask = (1L << 48) - 1 */
+ JSLL_I2L(tmp, 1);
+ JSLL_SHL(tmp2, tmp, 48);
+ JSLL_SUB(rt->rngMask, tmp2, tmp);
+
+ /* rt->rngDscale = (jsdouble)(1L << 53) */
+ JSLL_SHL(tmp2, tmp, 53);
+ JSLL_L2D(rt->rngDscale, tmp2);
+
+ /* Finally, set the seed from current time. */
+ random_setSeed(rt, PRMJ_Now());
+}
+
+static uint32
+random_next(JSRuntime *rt, int bits)
+{
+ int64 nextseed, tmp;
+ uint32 retval;
+
+ JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
+ JSLL_ADD(nextseed, nextseed, rt->rngAddend);
+ JSLL_AND(nextseed, nextseed, rt->rngMask);
+ rt->rngSeed = nextseed;
+ JSLL_USHR(tmp, nextseed, 48 - bits);
+ JSLL_L2I(retval, tmp);
+ return retval;
+}
+
+jsdouble
+js_random_nextDouble(JSRuntime *rt)
+{
+ int64 tmp, tmp2;
+ jsdouble d;
+
+ JSLL_ISHL(tmp, random_next(rt, 26), 27);
+ JSLL_UI2L(tmp2, random_next(rt, 27));
+ JSLL_ADD(tmp, tmp, tmp2);
+ JSLL_L2D(d, tmp);
+ return d / rt->rngDscale;
+}
+
+static JSBool
+math_random(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSRuntime *rt;
+ jsdouble z;
+
+ rt = cx->runtime;
+ JS_LOCK_RUNTIME(rt);
+ js_random_init(rt);
+ z = js_random_nextDouble(rt);
+ JS_UNLOCK_RUNTIME(rt);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+#if defined _WIN32 && !defined WINCE && _MSC_VER < 1400
+/* Try to work around apparent _copysign bustage in VC6 and VC7. */
+double
+js_copysign(double x, double y)
+{
+ jsdpun xu, yu;
+
+ xu.d = x;
+ yu.d = y;
+ xu.s.hi &= ~JSDOUBLE_HI32_SIGNBIT;
+ xu.s.hi |= yu.s.hi & JSDOUBLE_HI32_SIGNBIT;
+ return xu.d;
+}
+#endif
+
+static JSBool
+math_round(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = js_copysign(floor(x + 0.5), x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_sin(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = sin(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_sqrt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = sqrt(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+static JSBool
+math_tan(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x, z;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ z = tan(x);
+ return js_NewNumberInRootedValue(cx, z, vp);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+math_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = ATOM_KEY(CLASS_ATOM(cx, Math));
+ return JS_TRUE;
+}
+#endif
+
+#ifdef JS_TRACER
+
+#define MATH_BUILTIN_1(name) \
+ static jsdouble FASTCALL math_##name##_tn(jsdouble d) { return name(d); } \
+ JS_DEFINE_TRCINFO_1(math_##name, \
+ (1, (static, DOUBLE, math_##name##_tn, DOUBLE, 1, 1)))
+
+MATH_BUILTIN_1(sin)
+MATH_BUILTIN_1(cos)
+MATH_BUILTIN_1(sqrt)
+MATH_BUILTIN_1(floor)
+MATH_BUILTIN_1(ceil)
+
+static jsdouble FASTCALL
+math_abs_tn(jsdouble d)
+{
+ return fabs(d);
+}
+
+static jsdouble FASTCALL
+math_log_tn(jsdouble d)
+{
+#if defined(SOLARIS) && defined(__GNUC__)
+ if (d < 0)
+ return js_NaN;
+#endif
+ return log(d);
+}
+
+static jsdouble FASTCALL
+math_max_tn(jsdouble d, jsdouble p)
+{
+ if (JSDOUBLE_IS_NaN(d) || JSDOUBLE_IS_NaN(p))
+ return js_NaN;
+
+ if (p == 0 && p == d) {
+ if (js_copysign(1.0, d) == -1)
+ return p;
+ return d;
+ }
+ return (p > d) ? p : d;
+}
+
+static jsdouble FASTCALL
+math_pow_tn(jsdouble d, jsdouble p)
+{
+ if (!JSDOUBLE_IS_FINITE(p) && (d == 1.0 || d == -1.0))
+ return js_NaN;
+ if (p == 0)
+ return 1.0;
+ return pow(d, p);
+}
+
+static jsdouble FASTCALL
+math_random_tn(JSRuntime* rt)
+{
+ JS_LOCK_RUNTIME(rt);
+ js_random_init(rt);
+ jsdouble z = js_random_nextDouble(rt);
+ JS_UNLOCK_RUNTIME(rt);
+ return z;
+}
+
+static jsdouble FASTCALL
+math_round_tn(jsdouble x)
+{
+ return js_copysign(floor(x + 0.5), x);
+}
+
+JS_DEFINE_TRCINFO_1(math_abs,
+ (1, (static, DOUBLE, math_abs_tn, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_log,
+ (1, (static, DOUBLE, math_log_tn, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_max,
+ (2, (static, DOUBLE, math_max_tn, DOUBLE, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_pow,
+ (2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1)))
+JS_DEFINE_TRCINFO_1(math_random,
+ (1, (static, DOUBLE, math_random_tn, RUNTIME, 0, 0)))
+JS_DEFINE_TRCINFO_1(math_round,
+ (1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1)))
+
+#endif /* JS_TRACER */
+
+static JSFunctionSpec math_static_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, math_toSource, 0, 0),
+#endif
+ JS_TN("abs", math_abs, 1, 0, math_abs_trcinfo),
+ JS_FN("acos", math_acos, 1, 0),
+ JS_FN("asin", math_asin, 1, 0),
+ JS_FN("atan", math_atan, 1, 0),
+ JS_FN("atan2", math_atan2, 2, 0),
+ JS_TN("ceil", math_ceil, 1, 0, math_ceil_trcinfo),
+ JS_TN("cos", math_cos, 1, 0, math_cos_trcinfo),
+ JS_FN("exp", math_exp, 1, 0),
+ JS_TN("floor", math_floor, 1, 0, math_floor_trcinfo),
+ JS_TN("log", math_log, 1, 0, math_log_trcinfo),
+ JS_TN("max", math_max, 2, 0, math_max_trcinfo),
+ JS_FN("min", math_min, 2, 0),
+ JS_TN("pow", math_pow, 2, 0, math_pow_trcinfo),
+ JS_TN("random", math_random, 0, 0, math_random_trcinfo),
+ JS_TN("round", math_round, 1, 0, math_round_trcinfo),
+ JS_TN("sin", math_sin, 1, 0, math_sin_trcinfo),
+ JS_TN("sqrt", math_sqrt, 1, 0, math_sqrt_trcinfo),
+ JS_FN("tan", math_tan, 1, 0),
+ JS_FS_END
+};
+
+JSObject *
+js_InitMathClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *Math;
+
+ Math = JS_NewObject(cx, &js_MathClass, NULL, obj);
+ if (!Math)
+ return NULL;
+ if (!JS_DefineProperty(cx, obj, js_Math_str, OBJECT_TO_JSVAL(Math),
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_READONLY | JSPROP_PERMANENT))
+ return NULL;
+
+ if (!JS_DefineFunctions(cx, Math, math_static_methods))
+ return NULL;
+ if (!JS_DefineConstDoubles(cx, Math, math_constants))
+ return NULL;
+ return Math;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsmath.h b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.h
new file mode 100644
index 0000000..96e1c7f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsmath.h
@@ -0,0 +1,63 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* -*- Mode: C; tab-width: 8 -*-
+ * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved.
+ */
+
+#ifndef jsmath_h___
+#define jsmath_h___
+/*
+ * JS math functions.
+ */
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_MathClass;
+
+extern JSObject *
+js_InitMathClass(JSContext *cx, JSObject *obj);
+
+extern void
+js_random_init(JSRuntime *rt);
+
+extern jsdouble
+js_random_nextDouble(JSRuntime *rt);
+
+JS_END_EXTERN_C
+
+#endif /* jsmath_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp
new file mode 100644
index 0000000..f6c1b5f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.cpp
@@ -0,0 +1,1338 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS number type and wrapper class.
+ */
+#include "jsstddef.h"
+#if defined(XP_WIN) || defined(XP_OS2)
+#include <float.h>
+#endif
+#include <locale.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdtoa.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsprf.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+static JSBool
+num_isNaN(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x;
+
+ if (argc == 0) {
+ *vp = JSVAL_TRUE;
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ *vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
+ return JS_TRUE;
+}
+
+static JSBool
+num_isFinite(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsdouble x;
+
+ if (argc == 0) {
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+ x = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ *vp = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_FINITE(x));
+ return JS_TRUE;
+}
+
+static JSBool
+num_parseFloat(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble d;
+ const jschar *bp, *end, *ep;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtod(cx, bp, end, &ep, &d))
+ return JS_FALSE;
+ if (ep == bp) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ return js_NewNumberInRootedValue(cx, d, vp);
+}
+
+#ifdef JS_TRACER
+static jsdouble FASTCALL
+ParseFloat(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtod(cx, bp, end, &ep, &d) || ep == bp)
+ return js_NaN;
+ return d;
+}
+#endif
+
+/* See ECMA 15.1.2.2. */
+static JSBool
+num_parseInt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsint radix;
+ JSString *str;
+ jsdouble d;
+ const jschar *bp, *end, *ep;
+
+ if (argc == 0) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ if (argc > 1) {
+ radix = js_ValueToECMAInt32(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ } else {
+ radix = 0;
+ }
+ if (radix != 0 && (radix < 2 || radix > 36)) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+
+ if (JSVAL_IS_INT(vp[2]) && (radix == 0 || radix == 10)) {
+ *vp = vp[2];
+ return JS_TRUE;
+ }
+
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtointeger(cx, bp, end, &ep, radix, &d))
+ return JS_FALSE;
+ if (ep == bp) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ return js_NewNumberInRootedValue(cx, d, vp);
+}
+
+#ifdef JS_TRACER
+static jsdouble FASTCALL
+ParseInt(JSContext* cx, JSString* str)
+{
+ const jschar* bp;
+ const jschar* end;
+ const jschar* ep;
+ jsdouble d;
+
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if (!js_strtointeger(cx, bp, end, &ep, 0, &d) || ep == bp)
+ return js_NaN;
+ return d;
+}
+
+static jsdouble FASTCALL
+ParseIntDouble(jsdouble d)
+{
+ if (!JSDOUBLE_IS_FINITE(d))
+ return js_NaN;
+ return floor(d);
+}
+#endif
+
+const char js_Infinity_str[] = "Infinity";
+const char js_NaN_str[] = "NaN";
+const char js_isNaN_str[] = "isNaN";
+const char js_isFinite_str[] = "isFinite";
+const char js_parseFloat_str[] = "parseFloat";
+const char js_parseInt_str[] = "parseInt";
+
+#ifdef JS_TRACER
+
+JS_DEFINE_TRCINFO_2(num_parseInt,
+ (2, (static, DOUBLE, ParseInt, CONTEXT, STRING, 1, 1)),
+ (1, (static, DOUBLE, ParseIntDouble, DOUBLE, 1, 1)))
+
+JS_DEFINE_TRCINFO_1(num_parseFloat,
+ (2, (static, DOUBLE, ParseFloat, CONTEXT, STRING, 1, 1)))
+
+#endif /* JS_TRACER */
+
+static JSFunctionSpec number_functions[] = {
+ JS_FN(js_isNaN_str, num_isNaN, 1,0),
+ JS_FN(js_isFinite_str, num_isFinite, 1,0),
+ JS_TN(js_parseFloat_str, num_parseFloat, 1,0, num_parseFloat_trcinfo),
+ JS_TN(js_parseInt_str, num_parseInt, 2,0, num_parseInt_trcinfo),
+ JS_FS_END
+};
+
+JSClass js_NumberClass = {
+ js_Number_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Number),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+static JSBool
+Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval v;
+ jsdouble d;
+
+ if (argc != 0) {
+ d = js_ValueToNumber(cx, &argv[0]);
+ v = argv[0];
+ if (JSVAL_IS_NULL(v))
+ return JS_FALSE;
+ if (v != JSVAL_TRUE) {
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
+ } else {
+ if (!js_NewNumberInRootedValue(cx, d, &argv[0]))
+ return JS_FALSE;
+ v = argv[0];
+ }
+ } else {
+ v = JSVAL_ZERO;
+ }
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ *rval = v;
+ return JS_TRUE;
+ }
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, v);
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+num_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+ char numBuf[DTOSTR_STANDARD_BUFFER_SIZE], *numStr;
+ char buf[64];
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
+ numStr = JS_dtostr(numBuf, sizeof numBuf, DTOSTR_STANDARD, 0, d);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ JS_snprintf(buf, sizeof buf, "(new %s(%s))", js_NumberClass.name, numStr);
+ str = JS_NewStringCopyZ(cx, buf);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+/* The buf must be big enough for MIN_INT to fit including '-' and '\0'. */
+char *
+js_IntToCString(jsint i, jsint base, char *buf, size_t bufSize)
+{
+ char *cp;
+ jsuint u;
+
+ u = (i < 0) ? -i : i;
+
+ cp = buf + bufSize; /* one past last buffer cell */
+ *--cp = '\0'; /* null terminate the string to be */
+
+ /*
+ * Build the string from behind. We use multiply and subtraction
+ * instead of modulus because that's much faster.
+ */
+ switch (base) {
+ case 10:
+ do {
+ jsuint newu = u / 10;
+ *--cp = (char)(u - newu * 10) + '0';
+ u = newu;
+ } while (u != 0);
+ break;
+ case 16:
+ do {
+ jsuint newu = u / 16;
+ *--cp = "0123456789abcdef"[u - newu * 16];
+ u = newu;
+ } while (u != 0);
+ break;
+ default:
+ JS_ASSERT(base >= 2 && base <= 36);
+ do {
+ jsuint newu = u / base;
+ *--cp = "0123456789abcdefghijklmnopqrstuvwxyz"[u - newu * base];
+ u = newu;
+ } while (u != 0);
+ break;
+ }
+ if (i < 0)
+ *--cp = '-';
+
+ JS_ASSERT(cp >= buf);
+ return cp;
+}
+
+static JSBool
+num_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+ jsint base;
+ JSString *str;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
+ base = 10;
+ if (argc != 0 && !JSVAL_IS_VOID(vp[2])) {
+ base = js_ValueToECMAInt32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ if (base < 2 || base > 36) {
+ char numBuf[12];
+ char *numStr = js_IntToCString(base, 10, numBuf, sizeof numBuf);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_RADIX,
+ numStr);
+ return JS_FALSE;
+ }
+ }
+ if (base == 10) {
+ str = js_NumberToString(cx, d);
+ } else {
+ char *dStr = JS_dtobasestr(base, d);
+ if (!dStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ str = JS_NewStringCopyZ(cx, dStr);
+ free(dStr);
+ }
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+num_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ char thousandsLength, decimalLength;
+ const char *numGrouping, *tmpGroup;
+ JSRuntime *rt;
+ JSString *numStr, *str;
+ const char *num, *end, *tmpSrc;
+ char *buf, *tmpDest;
+ const char *nint;
+ int digits, size, remainder, nrepeat;
+
+ /*
+ * Create the string, move back to bytes to make string twiddling
+ * a bit easier and so we can insert platform charset seperators.
+ */
+ if (!num_toString(cx, 0, vp))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_STRING(*vp));
+ numStr = JSVAL_TO_STRING(*vp);
+ num = js_GetStringBytes(cx, numStr);
+ if (!num)
+ return JS_FALSE;
+
+ /*
+ * Find the first non-integer value, whether it be a letter as in
+ * 'Infinity', a decimal point, or an 'e' from exponential notation.
+ */
+ nint = num;
+ if (*nint == '-')
+ nint++;
+ while (*nint >= '0' && *nint <= '9')
+ nint++;
+ digits = nint - num;
+ end = num + digits;
+ if (!digits)
+ return JS_TRUE;
+
+ rt = cx->runtime;
+ thousandsLength = strlen(rt->thousandsSeparator);
+ decimalLength = strlen(rt->decimalSeparator);
+
+ /* Figure out how long resulting string will be. */
+ size = digits + (*nint ? strlen(nint + 1) + 1 : 0);
+ if (*nint == '.')
+ size += decimalLength;
+
+ numGrouping = tmpGroup = rt->numGrouping;
+ remainder = digits;
+ if (*num == '-')
+ remainder--;
+
+ while (*tmpGroup != CHAR_MAX && *tmpGroup != '\0') {
+ if (*tmpGroup >= remainder)
+ break;
+ size += thousandsLength;
+ remainder -= *tmpGroup;
+ tmpGroup++;
+ }
+ if (*tmpGroup == '\0' && *numGrouping != '\0') {
+ nrepeat = (remainder - 1) / tmpGroup[-1];
+ size += thousandsLength * nrepeat;
+ remainder -= nrepeat * tmpGroup[-1];
+ } else {
+ nrepeat = 0;
+ }
+ tmpGroup--;
+
+ buf = (char *)JS_malloc(cx, size + 1);
+ if (!buf)
+ return JS_FALSE;
+
+ tmpDest = buf;
+ tmpSrc = num;
+
+ while (*tmpSrc == '-' || remainder--)
+ *tmpDest++ = *tmpSrc++;
+ while (tmpSrc < end) {
+ strcpy(tmpDest, rt->thousandsSeparator);
+ tmpDest += thousandsLength;
+ memcpy(tmpDest, tmpSrc, *tmpGroup);
+ tmpDest += *tmpGroup;
+ tmpSrc += *tmpGroup;
+ if (--nrepeat < 0)
+ tmpGroup--;
+ }
+
+ if (*nint == '.') {
+ strcpy(tmpDest, rt->decimalSeparator);
+ tmpDest += decimalLength;
+ strcpy(tmpDest, nint + 1);
+ } else {
+ strcpy(tmpDest, nint);
+ }
+
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUnicode)
+ return cx->localeCallbacks->localeToUnicode(cx, buf, vp);
+
+ str = JS_NewString(cx, buf, size);
+ if (!str) {
+ JS_free(cx, buf);
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+num_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ JSObject *obj;
+
+ v = vp[1];
+ if (JSVAL_IS_NUMBER(v)) {
+ *vp = v;
+ return JS_TRUE;
+ }
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_NumberClass, vp + 2))
+ return JS_FALSE;
+ *vp = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ return JS_TRUE;
+}
+
+
+#define MAX_PRECISION 100
+
+static JSBool
+num_to(JSContext *cx, JSDToStrMode zeroArgMode, JSDToStrMode oneArgMode,
+ jsint precisionMin, jsint precisionMax, jsint precisionOffset,
+ uintN argc, jsval *vp)
+{
+ jsval v;
+ jsdouble d, precision;
+ JSString *str;
+
+ /* Use MAX_PRECISION+1 because precisionOffset can be 1. */
+ char buf[DTOSTR_VARIABLE_BUFFER_SIZE(MAX_PRECISION+1)];
+ char *numStr;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_NumberClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ d = JSVAL_IS_INT(v) ? (jsdouble)JSVAL_TO_INT(v) : *JSVAL_TO_DOUBLE(v);
+
+ if (argc == 0) {
+ precision = 0.0;
+ oneArgMode = zeroArgMode;
+ } else {
+ precision = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ precision = js_DoubleToInteger(precision);
+ if (precision < precisionMin || precision > precisionMax) {
+ numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, precision);
+ if (!numStr)
+ JS_ReportOutOfMemory(cx);
+ else
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_PRECISION_RANGE, numStr);
+ return JS_FALSE;
+ }
+ }
+
+ numStr = JS_dtostr(buf, sizeof buf, oneArgMode, (jsint)precision + precisionOffset, d);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ str = JS_NewStringCopyZ(cx, numStr);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/*
+ * In the following three implementations, we allow a larger range of precision
+ * than ECMA requires; this is permitted by ECMA-262.
+ */
+static JSBool
+num_toFixed(JSContext *cx, uintN argc, jsval *vp)
+{
+ return num_to(cx, DTOSTR_FIXED, DTOSTR_FIXED, -20, MAX_PRECISION, 0,
+ argc, vp);
+}
+
+static JSBool
+num_toExponential(JSContext *cx, uintN argc, jsval *vp)
+{
+ return num_to(cx, DTOSTR_STANDARD_EXPONENTIAL, DTOSTR_EXPONENTIAL, 0,
+ MAX_PRECISION, 1, argc, vp);
+}
+
+static JSBool
+num_toPrecision(JSContext *cx, uintN argc, jsval *vp)
+{
+ if (argc == 0 || JSVAL_IS_VOID(vp[2]))
+ return num_toString(cx, 0, vp);
+ return num_to(cx, DTOSTR_STANDARD, DTOSTR_PRECISION, 1, MAX_PRECISION, 0,
+ argc, vp);
+}
+
+#ifdef JS_TRACER
+
+JS_DEFINE_TRCINFO_2(num_toString,
+ (3, (static, STRING, NumberToStringWithBase, CONTEXT, THIS_DOUBLE, INT32, 1, 1)),
+ (2, (extern, STRING, js_NumberToString, CONTEXT, THIS_DOUBLE, 1, 1)))
+
+#endif /* JS_TRACER */
+
+static JSFunctionSpec number_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, num_toSource, 0,JSFUN_THISP_NUMBER),
+#endif
+ JS_TN(js_toString_str, num_toString, 1,JSFUN_THISP_NUMBER,
+ num_toString_trcinfo),
+ JS_FN(js_toLocaleString_str, num_toLocaleString, 0,JSFUN_THISP_NUMBER),
+ JS_FN(js_valueOf_str, num_valueOf, 0,JSFUN_THISP_NUMBER),
+ JS_FN(js_toJSON_str, num_valueOf, 0,JSFUN_THISP_NUMBER),
+ JS_FN("toFixed", num_toFixed, 1,JSFUN_THISP_NUMBER),
+ JS_FN("toExponential", num_toExponential, 1,JSFUN_THISP_NUMBER),
+ JS_FN("toPrecision", num_toPrecision, 1,JSFUN_THISP_NUMBER),
+ JS_FS_END
+};
+
+/* NB: Keep this in synch with number_constants[]. */
+enum nc_slot {
+ NC_NaN,
+ NC_POSITIVE_INFINITY,
+ NC_NEGATIVE_INFINITY,
+ NC_MAX_VALUE,
+ NC_MIN_VALUE,
+ NC_LIMIT
+};
+
+/*
+ * Some to most C compilers forbid spelling these at compile time, or barf
+ * if you try, so all but MAX_VALUE are set up by js_InitRuntimeNumberState
+ * using union jsdpun.
+ */
+static JSConstDoubleSpec number_constants[] = {
+ {0, js_NaN_str, 0,{0,0,0}},
+ {0, "POSITIVE_INFINITY", 0,{0,0,0}},
+ {0, "NEGATIVE_INFINITY", 0,{0,0,0}},
+ {1.7976931348623157E+308, "MAX_VALUE", 0,{0,0,0}},
+ {0, "MIN_VALUE", 0,{0,0,0}},
+ {0,0,0,{0,0,0}}
+};
+
+jsdouble js_NaN;
+
+#if (defined XP_WIN || defined XP_OS2) && \
+ !defined WINCE && \
+ !defined __MWERKS__ && \
+ (defined _M_IX86 || \
+ (defined __GNUC__ && !defined __MINGW32__))
+
+/*
+ * Set the exception mask to mask all exceptions and set the FPU precision
+ * to 53 bit mantissa.
+ * On Alpha platform this is handled via Compiler option.
+ */
+#define FIX_FPU() _control87(MCW_EM | PC_53, MCW_EM | MCW_PC)
+
+#else
+
+#define FIX_FPU() ((void)0)
+
+#endif
+
+JSBool
+js_InitRuntimeNumberState(JSContext *cx)
+{
+ JSRuntime *rt;
+ jsdpun u;
+ struct lconv *locale;
+
+ rt = cx->runtime;
+ JS_ASSERT(!rt->jsNaN);
+
+ FIX_FPU();
+
+ u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
+ u.s.lo = 0xffffffff;
+ number_constants[NC_NaN].dval = js_NaN = u.d;
+ rt->jsNaN = js_NewWeaklyRootedDouble(cx, js_NaN);
+ if (!rt->jsNaN)
+ return JS_FALSE;
+
+ u.s.hi = JSDOUBLE_HI32_EXPMASK;
+ u.s.lo = 0x00000000;
+ number_constants[NC_POSITIVE_INFINITY].dval = u.d;
+ rt->jsPositiveInfinity = js_NewWeaklyRootedDouble(cx, u.d);
+ if (!rt->jsPositiveInfinity)
+ return JS_FALSE;
+
+ u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
+ u.s.lo = 0x00000000;
+ number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
+ rt->jsNegativeInfinity = js_NewWeaklyRootedDouble(cx, u.d);
+ if (!rt->jsNegativeInfinity)
+ return JS_FALSE;
+
+ u.s.hi = 0;
+ u.s.lo = 1;
+ number_constants[NC_MIN_VALUE].dval = u.d;
+
+ locale = localeconv();
+ rt->thousandsSeparator =
+ JS_strdup(cx, locale->thousands_sep ? locale->thousands_sep : "'");
+ rt->decimalSeparator =
+ JS_strdup(cx, locale->decimal_point ? locale->decimal_point : ".");
+ rt->numGrouping =
+ JS_strdup(cx, locale->grouping ? locale->grouping : "\3\0");
+
+ return rt->thousandsSeparator && rt->decimalSeparator && rt->numGrouping;
+}
+
+void
+js_TraceRuntimeNumberState(JSTracer *trc)
+{
+ JSRuntime *rt;
+
+ rt = trc->context->runtime;
+ if (rt->jsNaN)
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsNaN, "NaN");
+ if (rt->jsPositiveInfinity)
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsPositiveInfinity, "+Infinity");
+ if (rt->jsNegativeInfinity)
+ JS_CALL_DOUBLE_TRACER(trc, rt->jsNegativeInfinity, "-Infinity");
+}
+
+void
+js_FinishRuntimeNumberState(JSContext *cx)
+{
+ JSRuntime *rt = cx->runtime;
+
+ js_UnlockGCThingRT(rt, rt->jsNaN);
+ js_UnlockGCThingRT(rt, rt->jsNegativeInfinity);
+ js_UnlockGCThingRT(rt, rt->jsPositiveInfinity);
+
+ rt->jsNaN = NULL;
+ rt->jsNegativeInfinity = NULL;
+ rt->jsPositiveInfinity = NULL;
+
+ JS_free(cx, (void *)rt->thousandsSeparator);
+ JS_free(cx, (void *)rt->decimalSeparator);
+ JS_free(cx, (void *)rt->numGrouping);
+ rt->thousandsSeparator = rt->decimalSeparator = rt->numGrouping = NULL;
+}
+
+JSObject *
+js_InitNumberClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *ctor;
+ JSRuntime *rt;
+
+ /* XXX must do at least once per new thread, so do it per JSContext... */
+ FIX_FPU();
+
+ if (!JS_DefineFunctions(cx, obj, number_functions))
+ return NULL;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_NumberClass, Number, 1,
+ NULL, number_methods, NULL, NULL);
+ if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE, JSVAL_ZERO);
+ if (!JS_DefineConstDoubles(cx, ctor, number_constants))
+ return NULL;
+
+ /* ECMA 15.1.1.1 */
+ rt = cx->runtime;
+ if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN),
+ NULL, NULL, JSPROP_PERMANENT)) {
+ return NULL;
+ }
+
+ /* ECMA 15.1.1.2 */
+ if (!JS_DefineProperty(cx, obj, js_Infinity_str,
+ DOUBLE_TO_JSVAL(rt->jsPositiveInfinity),
+ NULL, NULL, JSPROP_PERMANENT)) {
+ return NULL;
+ }
+ return proto;
+}
+
+JSBool
+js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp)
+{
+ jsint i;
+
+ if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+ return js_NewDoubleInRootedValue(cx, d, vp);
+}
+
+char *
+js_NumberToCString(JSContext *cx, jsdouble d, jsint base, char *buf, size_t bufSize)
+{
+ jsint i;
+ char *numStr;
+
+ JS_ASSERT(bufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
+ if (JSDOUBLE_IS_INT(d, i)) {
+ numStr = js_IntToCString(i, base, buf, bufSize);
+ } else {
+ if (base == 10)
+ numStr = JS_dtostr(buf, bufSize, DTOSTR_STANDARD, 0, d);
+ else
+ numStr = JS_dtobasestr(base, d);
+ if (!numStr) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ }
+ return numStr;
+}
+
+static JSString * JS_FASTCALL
+NumberToStringWithBase(JSContext *cx, jsdouble d, jsint base)
+{
+ char buf[DTOSTR_STANDARD_BUFFER_SIZE];
+ char *numStr;
+
+ if (base < 2 || base > 36)
+ return NULL;
+ numStr = js_NumberToCString(cx, d, base, buf, sizeof buf);
+ if (!numStr)
+ return NULL;
+ return JS_NewStringCopyZ(cx, numStr);
+}
+
+JSString * JS_FASTCALL
+js_NumberToString(JSContext *cx, jsdouble d)
+{
+ return NumberToStringWithBase(cx, d, 10);
+}
+
+jsdouble
+js_ValueToNumber(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ JSString *str;
+ const jschar *bp, *end, *ep;
+ jsdouble d, *dp;
+ JSObject *obj;
+ JSTempValueRooter tvr;
+
+ v = *vp;
+ for (;;) {
+ if (JSVAL_IS_INT(v))
+ return (jsdouble) JSVAL_TO_INT(v);
+ if (JSVAL_IS_DOUBLE(v))
+ return *JSVAL_TO_DOUBLE(v);
+ if (JSVAL_IS_STRING(v)) {
+ str = JSVAL_TO_STRING(v);
+
+ /*
+ * Note that ECMA doesn't treat a string beginning with a '0' as
+ * an octal number here. This works because all such numbers will
+ * be interpreted as decimal by js_strtod and will never get
+ * passed to js_strtointeger (which would interpret them as
+ * octal).
+ */
+ JSSTRING_CHARS_AND_END(str, bp, end);
+ if ((!js_strtod(cx, bp, end, &ep, &d) ||
+ js_SkipWhiteSpace(ep, end) != end) &&
+ (!js_strtointeger(cx, bp, end, &ep, 0, &d) ||
+ js_SkipWhiteSpace(ep, end) != end)) {
+ break;
+ }
+
+ /*
+ * JSVAL_TRUE indicates that double jsval was never constructed
+ * for the result.
+ */
+ *vp = JSVAL_TRUE;
+ return d;
+ }
+ if (JSVAL_IS_BOOLEAN(v)) {
+ if (JSVAL_TO_BOOLEAN(v)) {
+ *vp = JSVAL_ONE;
+ return 1.0;
+ } else {
+ *vp = JSVAL_ZERO;
+ return 0.0;
+ }
+ }
+ if (JSVAL_IS_NULL(v)) {
+ *vp = JSVAL_ZERO;
+ return 0.0;
+ }
+ if (JSVAL_IS_VOID(v))
+ break;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ obj = JSVAL_TO_OBJECT(v);
+
+ /*
+ * vp roots obj so we cannot use it as an extra root for
+ * OBJ_DEFAULT_VALUE result when calling the hook.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, v, &tvr);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_NUMBER, &tvr.u.value))
+ obj = NULL;
+ else
+ v = *vp = tvr.u.value;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!obj) {
+ *vp = JSVAL_NULL;
+ return 0.0;
+ }
+ if (!JSVAL_IS_PRIMITIVE(v))
+ break;
+ }
+
+ dp = cx->runtime->jsNaN;
+ *vp = DOUBLE_TO_JSVAL(dp);
+ return *dp;
+}
+
+int32
+js_ValueToECMAInt32(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_INT(v))
+ return JSVAL_TO_INT(v);
+ if (JSVAL_IS_DOUBLE(v)) {
+ d = *JSVAL_TO_DOUBLE(v);
+ *vp = JSVAL_TRUE;
+ } else {
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+ *vp = JSVAL_TRUE;
+ }
+ return js_DoubleToECMAInt32(d);
+}
+
+int32
+js_DoubleToECMAInt32(jsdouble d)
+{
+ int32 i;
+ jsdouble two32, two31;
+
+ if (!JSDOUBLE_IS_FINITE(d))
+ return 0;
+
+ i = (int32) d;
+ if ((jsdouble) i == d)
+ return i;
+
+ two32 = 4294967296.0;
+ two31 = 2147483648.0;
+ d = fmod(d, two32);
+ d = (d >= 0) ? floor(d) : ceil(d) + two32;
+ return (int32) (d >= two31 ? d - two32 : d);
+}
+
+uint32
+js_ValueToECMAUint32(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ jsint i;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_INT(v)) {
+ i = JSVAL_TO_INT(v);
+ if (i < 0)
+ *vp = JSVAL_TRUE;
+ return (uint32) i;
+ }
+ if (JSVAL_IS_DOUBLE(v)) {
+ d = *JSVAL_TO_DOUBLE(v);
+ *vp = JSVAL_TRUE;
+ } else {
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+ *vp = JSVAL_TRUE;
+ }
+ return js_DoubleToECMAUint32(d);
+}
+
+uint32
+js_DoubleToECMAUint32(jsdouble d)
+{
+ int32 i;
+ JSBool neg;
+ jsdouble two32;
+
+ if (!JSDOUBLE_IS_FINITE(d))
+ return 0;
+
+ /*
+ * We check whether d fits int32, not uint32, as all but the ">>>" bit
+ * manipulation bytecode stores the result as int, not uint. When the
+ * result does not fit int jsval, it will be stored as a negative double.
+ */
+ i = (int32) d;
+ if ((jsdouble) i == d)
+ return (int32)i;
+
+ neg = (d < 0);
+ d = floor(neg ? -d : d);
+ d = neg ? -d : d;
+
+ two32 = 4294967296.0;
+ d = fmod(d, two32);
+
+ return (uint32) (d >= 0 ? d : d + two32);
+}
+
+int32
+js_ValueToInt32(JSContext *cx, jsval *vp)
+{
+ jsval v;
+ jsdouble d;
+
+ v = *vp;
+ if (JSVAL_IS_INT(v))
+ return JSVAL_TO_INT(v);
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+ if (JSVAL_IS_INT(*vp))
+ return JSVAL_TO_INT(*vp);
+
+ *vp = JSVAL_TRUE;
+ if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
+ js_ReportValueError(cx, JSMSG_CANT_CONVERT,
+ JSDVG_SEARCH_STACK, v, NULL);
+ *vp = JSVAL_NULL;
+ return 0;
+ }
+ return (int32) floor(d + 0.5); /* Round to nearest */
+}
+
+uint16
+js_ValueToUint16(JSContext *cx, jsval *vp)
+{
+ jsdouble d;
+ uint16 u;
+ jsuint m;
+ JSBool neg;
+
+ d = js_ValueToNumber(cx, vp);
+ if (JSVAL_IS_NULL(*vp))
+ return 0;
+
+ if (JSVAL_IS_INT(*vp)) {
+ u = (uint16) JSVAL_TO_INT(*vp);
+ } else if (d == 0 || !JSDOUBLE_IS_FINITE(d)) {
+ u = (uint16) 0;
+ } else {
+ u = (uint16) d;
+ if ((jsdouble) u != d) {
+ neg = (d < 0);
+ d = floor(neg ? -d : d);
+ d = neg ? -d : d;
+ m = JS_BIT(16);
+ d = fmod(d, (double) m);
+ if (d < 0)
+ d += m;
+ u = (uint16) d;
+ }
+ }
+ *vp = INT_TO_JSVAL(u);
+ return u;
+}
+
+jsdouble
+js_DoubleToInteger(jsdouble d)
+{
+ JSBool neg;
+
+ if (d == 0)
+ return d;
+ if (!JSDOUBLE_IS_FINITE(d)) {
+ if (JSDOUBLE_IS_NaN(d))
+ return 0;
+ return d;
+ }
+ neg = (d < 0);
+ d = floor(neg ? -d : d);
+ return neg ? -d : d;
+}
+
+JSBool
+js_strtod(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsdouble *dp)
+{
+ const jschar *s1;
+ size_t length, i;
+ char cbuf[32];
+ char *cstr, *istr, *estr;
+ JSBool negative;
+ jsdouble d;
+
+ s1 = js_SkipWhiteSpace(s, send);
+ length = send - s1;
+
+ /* Use cbuf to avoid malloc */
+ if (length >= sizeof cbuf) {
+ cstr = (char *) JS_malloc(cx, length + 1);
+ if (!cstr)
+ return JS_FALSE;
+ } else {
+ cstr = cbuf;
+ }
+
+ for (i = 0; i != length; i++) {
+ if (s1[i] >> 8)
+ break;
+ cstr[i] = (char)s1[i];
+ }
+ cstr[i] = 0;
+
+ istr = cstr;
+ if ((negative = (*istr == '-')) != 0 || *istr == '+')
+ istr++;
+ if (!strncmp(istr, js_Infinity_str, sizeof js_Infinity_str - 1)) {
+ d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity);
+ estr = istr + 8;
+ } else {
+ int err;
+ d = JS_strtod(cstr, &estr, &err);
+ if (d == HUGE_VAL)
+ d = *cx->runtime->jsPositiveInfinity;
+ else if (d == -HUGE_VAL)
+ d = *cx->runtime->jsNegativeInfinity;
+#ifdef HPUX
+ if (d == 0.0 && negative) {
+ /*
+ * "-0", "-1e-2000" come out as positive zero
+ * here on HPUX. Force a negative zero instead.
+ */
+ JSDOUBLE_HI32(d) = JSDOUBLE_HI32_SIGNBIT;
+ JSDOUBLE_LO32(d) = 0;
+ }
+#endif
+ }
+
+ i = estr - cstr;
+ if (cstr != cbuf)
+ JS_free(cx, cstr);
+ *ep = i ? s1 + i : s;
+ *dp = d;
+ return JS_TRUE;
+}
+
+struct BinaryDigitReader
+{
+ uintN base; /* Base of number; must be a power of 2 */
+ uintN digit; /* Current digit value in radix given by base */
+ uintN digitMask; /* Mask to extract the next bit from digit */
+ const jschar *digits; /* Pointer to the remaining digits */
+ const jschar *end; /* Pointer to first non-digit */
+};
+
+/* Return the next binary digit from the number or -1 if done */
+static intN GetNextBinaryDigit(struct BinaryDigitReader *bdr)
+{
+ intN bit;
+
+ if (bdr->digitMask == 0) {
+ uintN c;
+
+ if (bdr->digits == bdr->end)
+ return -1;
+
+ c = *bdr->digits++;
+ if ('0' <= c && c <= '9')
+ bdr->digit = c - '0';
+ else if ('a' <= c && c <= 'z')
+ bdr->digit = c - 'a' + 10;
+ else bdr->digit = c - 'A' + 10;
+ bdr->digitMask = bdr->base >> 1;
+ }
+ bit = (bdr->digit & bdr->digitMask) != 0;
+ bdr->digitMask >>= 1;
+ return bit;
+}
+
+JSBool
+js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsint base, jsdouble *dp)
+{
+ const jschar *s1, *start;
+ JSBool negative;
+ jsdouble value;
+
+ s1 = js_SkipWhiteSpace(s, send);
+ if (s1 == send)
+ goto no_digits;
+ if ((negative = (*s1 == '-')) != 0 || *s1 == '+') {
+ s1++;
+ if (s1 == send)
+ goto no_digits;
+ }
+
+ if (base == 0) {
+ /* No base supplied, or some base that evaluated to 0. */
+ if (*s1 == '0') {
+ /* It's either hex or octal; only increment char if str isn't '0' */
+ if (s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
+ base = 16;
+ s1 += 2;
+ if (s1 == send)
+ goto no_digits;
+ } else {
+ base = 8;
+ }
+ } else {
+ base = 10; /* Default to decimal. */
+ }
+ } else if (base == 16) {
+ /* If base is 16, ignore hex prefix. */
+ if (*s1 == '0' && s1 + 1 != send && (s1[1] == 'X' || s1[1] == 'x')) {
+ s1 += 2;
+ if (s1 == send)
+ goto no_digits;
+ }
+ }
+
+ /*
+ * Done with the preliminaries; find some prefix of the string that's
+ * a number in the given base.
+ */
+ JS_ASSERT(s1 < send);
+ start = s1;
+ value = 0.0;
+ do {
+ uintN digit;
+ jschar c = *s1;
+ if ('0' <= c && c <= '9')
+ digit = c - '0';
+ else if ('a' <= c && c <= 'z')
+ digit = c - 'a' + 10;
+ else if ('A' <= c && c <= 'Z')
+ digit = c - 'A' + 10;
+ else
+ break;
+ if (digit >= (uintN)base)
+ break;
+ value = value * base + digit;
+ } while (++s1 != send);
+
+ if (value >= 9007199254740992.0) {
+ if (base == 10) {
+ /*
+ * If we're accumulating a decimal number and the number is >=
+ * 2^53, then the result from the repeated multiply-add above may
+ * be inaccurate. Call JS_strtod to get the correct answer.
+ */
+ size_t i;
+ size_t length = s1 - start;
+ char *cstr = (char *) JS_malloc(cx, length + 1);
+ char *estr;
+ int err=0;
+
+ if (!cstr)
+ return JS_FALSE;
+ for (i = 0; i != length; i++)
+ cstr[i] = (char)start[i];
+ cstr[length] = 0;
+
+ value = JS_strtod(cstr, &estr, &err);
+ if (err == JS_DTOA_ENOMEM) {
+ JS_ReportOutOfMemory(cx);
+ JS_free(cx, cstr);
+ return JS_FALSE;
+ }
+ if (err == JS_DTOA_ERANGE && value == HUGE_VAL)
+ value = *cx->runtime->jsPositiveInfinity;
+ JS_free(cx, cstr);
+ } else if ((base & (base - 1)) == 0) {
+ /*
+ * The number may also be inaccurate for power-of-two bases. This
+ * happens if the addition in value * base + digit causes a round-
+ * down to an even least significant mantissa bit when the first
+ * dropped bit is a one. If any of the following digits in the
+ * number (which haven't been added in yet) are nonzero, then the
+ * correct action would have been to round up instead of down. An
+ * example occurs when reading the number 0x1000000000000081, which
+ * rounds to 0x1000000000000000 instead of 0x1000000000000100.
+ */
+ struct BinaryDigitReader bdr;
+ intN bit, bit2;
+ intN j;
+
+ bdr.base = base;
+ bdr.digitMask = 0;
+ bdr.digits = start;
+ bdr.end = s1;
+ value = 0.0;
+
+ /* Skip leading zeros. */
+ do {
+ bit = GetNextBinaryDigit(&bdr);
+ } while (bit == 0);
+
+ if (bit == 1) {
+ /* Gather the 53 significant bits (including the leading 1) */
+ value = 1.0;
+ for (j = 52; j; j--) {
+ bit = GetNextBinaryDigit(&bdr);
+ if (bit < 0)
+ goto done;
+ value = value*2 + bit;
+ }
+ /* bit2 is the 54th bit (the first dropped from the mantissa) */
+ bit2 = GetNextBinaryDigit(&bdr);
+ if (bit2 >= 0) {
+ jsdouble factor = 2.0;
+ intN sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */
+ intN bit3;
+
+ while ((bit3 = GetNextBinaryDigit(&bdr)) >= 0) {
+ sticky |= bit3;
+ factor *= 2;
+ }
+ value += bit2 & (bit | sticky);
+ value *= factor;
+ }
+ done:;
+ }
+ }
+ }
+ /* We don't worry about inaccurate numbers for any other base. */
+
+ if (s1 == start) {
+ no_digits:
+ *dp = 0.0;
+ *ep = s;
+ } else {
+ *dp = negative ? -value : value;
+ *ep = s1;
+ }
+ return JS_TRUE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsnum.h b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.h
new file mode 100644
index 0000000..285e29c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsnum.h
@@ -0,0 +1,287 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsnum_h___
+#define jsnum_h___
+
+/*
+ * JS number (IEEE double) interface.
+ *
+ * JS numbers are optimistically stored in the top 31 bits of 32-bit integers,
+ * but floating point literals, results that overflow 31 bits, and division and
+ * modulus operands and results require a 64-bit IEEE double. These are GC'ed
+ * and pointed to by 32-bit jsvals on the stack and in object properties.
+ */
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * The ARM architecture supports two floating point models: VFP and FPA. When
+ * targetting FPA, doubles are mixed-endian on little endian ARMs (meaning that
+ * the high and low words are in big endian order).
+ */
+#if defined(__arm) || defined(__arm32__) || defined(__arm26__) || defined(__arm__)
+#if !defined(__VFP_FP__)
+#define FPU_IS_ARM_FPA
+#endif
+#endif
+
+typedef union jsdpun {
+ struct {
+#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
+ uint32 lo, hi;
+#else
+ uint32 hi, lo;
+#endif
+ } s;
+ uint64 u64;
+ jsdouble d;
+} jsdpun;
+
+#if (__GNUC__ == 2 && __GNUC_MINOR__ > 95) || __GNUC__ > 2
+/*
+ * This version of the macros is safe for the alias optimizations that gcc
+ * does, but uses gcc-specific extensions.
+ */
+
+#define JSDOUBLE_HI32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.hi; }))
+#define JSDOUBLE_LO32(x) (__extension__ ({ jsdpun u; u.d = (x); u.s.lo; }))
+#define JSDOUBLE_SET_HI32(x, y) \
+ (__extension__ ({ jsdpun u; u.d = (x); u.s.hi = (y); (x) = u.d; }))
+#define JSDOUBLE_SET_LO32(x, y) \
+ (__extension__ ({ jsdpun u; u.d = (x); u.s.lo = (y); (x) = u.d; }))
+
+#else /* not or old GNUC */
+
+/*
+ * We don't know of any non-gcc compilers that perform alias optimization,
+ * so this code should work.
+ */
+
+#if defined(IS_LITTLE_ENDIAN) && !defined(FPU_IS_ARM_FPA)
+#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
+#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
+#else
+#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
+#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
+#endif
+
+#define JSDOUBLE_SET_HI32(x, y) (JSDOUBLE_HI32(x)=(y))
+#define JSDOUBLE_SET_LO32(x, y) (JSDOUBLE_LO32(x)=(y))
+
+#endif /* not or old GNUC */
+
+#define JSDOUBLE_HI32_SIGNBIT 0x80000000
+#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
+#define JSDOUBLE_HI32_MANTMASK 0x000fffff
+
+#define JSDOUBLE_IS_NaN(x) \
+ ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
+ (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
+
+#define JSDOUBLE_IS_INFINITE(x) \
+ ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
+ !JSDOUBLE_LO32(x))
+
+#define JSDOUBLE_IS_FINITE(x) \
+ ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)
+
+#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \
+ JSDOUBLE_LO32(d) == 0)
+
+/*
+ * JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid
+ * raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is
+ * safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point
+ * comparisons under MSVC.
+ */
+#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \
+ && !JSDOUBLE_IS_NEGZERO(d) \
+ && ((d) == (i = (jsint)(d))))
+
+#if defined(XP_WIN)
+#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) \
+ ((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \
+ ? (IFNAN) \
+ : (LVAL) OP (RVAL))
+#else
+#define JSDOUBLE_COMPARE(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL))
+#endif
+
+extern jsdouble js_NaN;
+
+/* Initialize number constants and runtime state for the first context. */
+extern JSBool
+js_InitRuntimeNumberState(JSContext *cx);
+
+extern void
+js_TraceRuntimeNumberState(JSTracer *trc);
+
+extern void
+js_FinishRuntimeNumberState(JSContext *cx);
+
+/* Initialize the Number class, returning its prototype object. */
+extern JSClass js_NumberClass;
+
+extern JSObject *
+js_InitNumberClass(JSContext *cx, JSObject *obj);
+
+/*
+ * String constants for global function names, used in jsapi.c and jsnum.c.
+ */
+extern const char js_Infinity_str[];
+extern const char js_NaN_str[];
+extern const char js_isNaN_str[];
+extern const char js_isFinite_str[];
+extern const char js_parseFloat_str[];
+extern const char js_parseInt_str[];
+
+/*
+ * vp must be a root.
+ */
+extern JSBool
+js_NewNumberInRootedValue(JSContext *cx, jsdouble d, jsval *vp);
+
+/* Convert a number to a GC'ed string. */
+extern JSString * JS_FASTCALL
+js_NumberToString(JSContext *cx, jsdouble d);
+
+/*
+ * Convert int to C string. The buf must be big enough for MIN_INT to fit
+ * including '-' and '\0'.
+ */
+char *
+js_IntToCString(jsint i, jsint base, char *buf, size_t bufSize);
+
+/*
+ * Convert a number to C string. The buf must be at least
+ * DTOSTR_STANDARD_BUFFER_SIZE.
+ */
+char *
+js_NumberToCString(JSContext *cx, jsdouble d, jsint base, char *buf, size_t bufSize);
+
+/*
+ * Convert a value to a number. On exit JSVAL_IS_NULL(*vp) iff there was an
+ * error. If on exit JSVAL_IS_NUMBER(*vp), then *vp holds the jsval that
+ * matches the result. Otherwise *vp is JSVAL_TRUE indicating that the jsval
+ * for result has to be created explicitly using, for example, the
+ * js_NewNumberInRootedValue function.
+ */
+extern jsdouble
+js_ValueToNumber(JSContext *cx, jsval* vp);
+
+/*
+ * Convert a value to an int32 or uint32, according to the ECMA rules for
+ * ToInt32 and ToUint32. On exit JSVAL_IS_NULL(*vp) iff there was an error. If
+ * on exit JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result.
+ * Otherwise *vp is JSVAL_TRUE indicating that the jsval for result has to be
+ * created explicitly using, for example, the js_NewNumberInRootedValue
+ * function.
+ */
+extern int32
+js_ValueToECMAInt32(JSContext *cx, jsval *vp);
+
+extern uint32
+js_ValueToECMAUint32(JSContext *cx, jsval *vp);
+
+/*
+ * Specialized ToInt32 and ToUint32 converters for doubles.
+ */
+extern int32
+js_DoubleToECMAInt32(jsdouble d);
+
+extern uint32
+js_DoubleToECMAUint32(jsdouble d);
+
+/*
+ * Convert a value to a number, then to an int32 if it fits by rounding to
+ * nearest; but failing with an error report if the double is out of range
+ * or unordered. On exit JSVAL_IS_NULL(*vp) iff there was an error. If on exit
+ * JSVAL_IS_INT(*vp), then *vp holds the jsval matching the result. Otherwise
+ * *vp is JSVAL_TRUE indicating that the jsval for result has to be created
+ * explicitly using, for example, the js_NewNumberInRootedValue function.
+ */
+extern int32
+js_ValueToInt32(JSContext *cx, jsval *vp);
+
+/*
+ * Convert a value to a number, then to a uint16 according to the ECMA rules
+ * for ToUint16. On exit JSVAL_IS_NULL(*vp) iff there was an error, otherwise
+ * vp is jsval matching the result.
+ */
+extern uint16
+js_ValueToUint16(JSContext *cx, jsval *vp);
+
+/*
+ * Convert a jsdouble to an integral number, stored in a jsdouble.
+ * If d is NaN, return 0. If d is an infinity, return it without conversion.
+ */
+extern jsdouble
+js_DoubleToInteger(jsdouble d);
+
+/*
+ * Similar to strtod except that it replaces overflows with infinities of the
+ * correct sign, and underflows with zeros of the correct sign. Guaranteed to
+ * return the closest double number to the given input in dp.
+ *
+ * Also allows inputs of the form [+|-]Infinity, which produce an infinity of
+ * the appropriate sign. The case of the "Infinity" string must match exactly.
+ * If the string does not contain a number, set *ep to s and return 0.0 in dp.
+ * Return false if out of memory.
+ */
+extern JSBool
+js_strtod(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsdouble *dp);
+
+/*
+ * Similar to strtol except that it handles integers of arbitrary size.
+ * Guaranteed to return the closest double number to the given input when radix
+ * is 10 or a power of 2. Callers may see round-off errors for very large
+ * numbers of a different radix than 10 or a power of 2.
+ *
+ * If the string does not contain a number, set *ep to s and return 0.0 in dp.
+ * Return false if out of memory.
+ */
+extern JSBool
+js_strtointeger(JSContext *cx, const jschar *s, const jschar *send,
+ const jschar **ep, jsint radix, jsdouble *dp);
+
+JS_END_EXTERN_C
+
+#endif /* jsnum_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp
new file mode 100644
index 0000000..4e7f80a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.cpp
@@ -0,0 +1,5563 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS object implementation.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsbit.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsdhash.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */
+#include "jsstaticcheck.h"
+
+#if JS_HAS_GENERATORS
+#include "jsiter.h"
+#endif
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#if JS_HAS_XDR
+#include "jsxdrapi.h"
+#endif
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+#include "jsdtracef.h"
+#endif
+
+#include "jsautooplen.h"
+
+#ifdef JS_THREADSAFE
+#define NATIVE_DROP_PROPERTY js_DropProperty
+
+extern void
+js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop);
+#else
+#define NATIVE_DROP_PROPERTY NULL
+#endif
+
+JS_FRIEND_DATA(JSObjectOps) js_ObjectOps = {
+ js_NewObjectMap, js_DestroyObjectMap,
+ js_LookupProperty, js_DefineProperty,
+ js_GetProperty, js_SetProperty,
+ js_GetAttributes, js_SetAttributes,
+ js_DeleteProperty, js_DefaultValue,
+ js_Enumerate, js_CheckAccess,
+ NULL, NATIVE_DROP_PROPERTY,
+ js_Call, js_Construct,
+ NULL, js_HasInstance,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ js_TraceObject, js_Clear,
+ js_GetRequiredSlot, js_SetRequiredSlot
+};
+
+JSClass js_ObjectClass = {
+ js_Object_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_Object),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#if JS_HAS_OBJ_PROTO_PROP
+
+static JSBool
+obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+static JSBool
+obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+static JSBool
+obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+static JSPropertySpec object_props[] = {
+ /* These two must come first; see object_props[slot].name usage below. */
+ {js_proto_str, JSSLOT_PROTO, JSPROP_PERMANENT|JSPROP_SHARED,
+ obj_getSlot, obj_setSlot},
+ {js_parent_str,JSSLOT_PARENT,JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
+ obj_getSlot, obj_setSlot},
+ {js_count_str, 0, JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED,
+ obj_getCount, NULL},
+ {0,0,0,0,0}
+};
+
+/* NB: JSSLOT_PROTO and JSSLOT_PARENT are already indexes into object_props. */
+#define JSSLOT_COUNT 2
+
+static JSBool
+ReportStrictSlot(JSContext *cx, uint32 slot)
+{
+ if (slot == JSSLOT_PROTO)
+ return JS_TRUE;
+ return JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_DEPRECATED_USAGE,
+ object_props[slot].name);
+}
+
+static JSBool
+obj_getSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uint32 slot;
+ jsid propid;
+ JSAccessMode mode;
+ uintN attrs;
+ JSObject *pobj;
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+
+ slot = (uint32) JSVAL_TO_INT(id);
+ if (id == INT_TO_JSVAL(JSSLOT_PROTO)) {
+ propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
+ mode = JSACC_PROTO;
+ } else {
+ propid = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
+ mode = JSACC_PARENT;
+ }
+
+ /* Let OBJ_CHECK_ACCESS get the slot's value, based on the access mode. */
+ if (!OBJ_CHECK_ACCESS(cx, obj, propid, mode, vp, &attrs))
+ return JS_FALSE;
+
+ pobj = JSVAL_TO_OBJECT(*vp);
+ if (pobj) {
+ clasp = OBJ_GET_CLASS(cx, pobj);
+ if (clasp == &js_CallClass || clasp == &js_BlockClass) {
+ /* Censor activations and lexical scopes per ECMA-262. */
+ *vp = JSVAL_NULL;
+ } else if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ xclasp = (JSExtendedClass *) clasp;
+ if (xclasp->outerObject) {
+ pobj = xclasp->outerObject(cx, pobj);
+ if (!pobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(pobj);
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+obj_setSlot(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSObject *pobj;
+ uint32 slot;
+ jsid propid;
+ uintN attrs;
+
+ if (!JSVAL_IS_OBJECT(*vp))
+ return JS_TRUE;
+ pobj = JSVAL_TO_OBJECT(*vp);
+
+ if (pobj) {
+ /*
+ * Innerize pobj here to avoid sticking unwanted properties on the
+ * outer object. This ensures that any with statements only grant
+ * access to the inner object.
+ */
+ OBJ_TO_INNER_OBJECT(cx, pobj);
+ if (!pobj)
+ return JS_FALSE;
+ }
+ slot = (uint32) JSVAL_TO_INT(id);
+ if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, slot))
+ return JS_FALSE;
+
+ /* __parent__ is readonly and permanent, only __proto__ may be set. */
+ propid = ATOM_TO_JSID(cx->runtime->atomState.protoAtom);
+ if (!OBJ_CHECK_ACCESS(cx, obj, propid,
+ (JSAccessMode)(JSACC_PROTO|JSACC_WRITE), vp,
+ &attrs)) {
+ return JS_FALSE;
+ }
+
+ return js_SetProtoOrParent(cx, obj, slot, pobj);
+}
+
+static JSBool
+obj_getCount(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsval iter_state;
+ jsid num_properties;
+ JSBool ok;
+
+ if (JS_HAS_STRICT_OPTION(cx) && !ReportStrictSlot(cx, JSSLOT_COUNT))
+ return JS_FALSE;
+
+ /* Get the number of properties to enumerate. */
+ iter_state = JSVAL_NULL;
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &iter_state, &num_properties);
+ if (!ok)
+ goto out;
+
+ if (!JSVAL_IS_INT(num_properties)) {
+ JS_ASSERT(0);
+ *vp = JSVAL_ZERO;
+ goto out;
+ }
+ *vp = num_properties;
+
+out:
+ if (iter_state != JSVAL_NULL)
+ ok = OBJ_ENUMERATE(cx, obj, JSENUMERATE_DESTROY, &iter_state, 0);
+ return ok;
+}
+
+#else /* !JS_HAS_OBJ_PROTO_PROP */
+
+#define object_props NULL
+
+#endif /* !JS_HAS_OBJ_PROTO_PROP */
+
+JSBool
+js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj)
+{
+ JSSetSlotRequest ssr;
+ JSRuntime *rt;
+
+ /* Optimize the null case to avoid the unnecessary overhead of js_GC. */
+ if (!pobj) {
+ JS_LOCK_OBJ(cx, obj);
+ if (slot == JSSLOT_PROTO && !js_GetMutableScope(cx, obj)) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_NULL);
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+ }
+
+ ssr.obj = obj;
+ ssr.pobj = pobj;
+ ssr.slot = (uint16) slot;
+ ssr.errnum = (uint16) JSMSG_NOT_AN_ERROR;
+
+ rt = cx->runtime;
+ JS_LOCK_GC(rt);
+ ssr.next = rt->setSlotRequests;
+ rt->setSlotRequests = &ssr;
+ for (;;) {
+ js_GC(cx, GC_SET_SLOT_REQUEST);
+ JS_UNLOCK_GC(rt);
+ if (!rt->setSlotRequests)
+ break;
+ JS_LOCK_GC(rt);
+ }
+
+ if (ssr.errnum != JSMSG_NOT_AN_ERROR) {
+ if (ssr.errnum == JSMSG_OUT_OF_MEMORY) {
+ JS_ReportOutOfMemory(cx);
+ } else {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, ssr.errnum,
+#if JS_HAS_OBJ_PROTO_PROP
+ object_props[slot].name
+#else
+ (slot == JSSLOT_PROTO) ? js_proto_str
+ : js_parent_str
+#endif
+ );
+ }
+ return JS_FALSE;
+ }
+
+ // Maintain the "any Array prototype has indexed properties hazard" flag.
+ if (slot == JSSLOT_PROTO &&
+ OBJ_IS_ARRAY(cx, pobj) &&
+ pobj->fslots[JSSLOT_ARRAY_LENGTH] != 0) {
+ rt->anyArrayProtoHasElement = JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static JSHashNumber
+js_hash_object(const void *key)
+{
+ return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS;
+}
+
+static JSHashEntry *
+MarkSharpObjects(JSContext *cx, JSObject *obj, JSIdArray **idap)
+{
+ JSSharpObjectMap *map;
+ JSHashTable *table;
+ JSHashNumber hash;
+ JSHashEntry **hep, *he;
+ jsatomid sharpid;
+ JSIdArray *ida;
+ JSBool ok;
+ jsint i, length;
+ jsid id;
+#if JS_HAS_GETTER_SETTER
+ JSObject *obj2;
+ JSProperty *prop;
+ uintN attrs;
+#endif
+ jsval val;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ map = &cx->sharpObjectMap;
+ table = map->table;
+ hash = js_hash_object(obj);
+ hep = JS_HashTableRawLookup(table, hash, obj);
+ he = *hep;
+ if (!he) {
+ sharpid = 0;
+ he = JS_HashTableRawAdd(table, hep, hash, obj,
+ JS_UINT32_TO_PTR(sharpid));
+ if (!he) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+
+ /*
+ * Increment map->depth to protect js_EnterSharpObject from reentering
+ * itself badly. Without this fix, if we reenter the basis case where
+ * map->depth == 0, when unwinding the inner call we will destroy the
+ * newly-created hash table and crash.
+ */
+ ++map->depth;
+ ida = JS_Enumerate(cx, obj);
+ --map->depth;
+ if (!ida)
+ return NULL;
+
+ ok = JS_TRUE;
+ for (i = 0, length = ida->length; i < length; i++) {
+ id = ida->vector[i];
+#if JS_HAS_GETTER_SETTER
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
+ if (!ok)
+ break;
+ if (!prop)
+ continue;
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
+ if (ok) {
+ if (OBJ_IS_NATIVE(obj2) &&
+ (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ val = JSVAL_NULL;
+ if (attrs & JSPROP_GETTER)
+ val = (jsval) ((JSScopeProperty*)prop)->getter;
+ if (attrs & JSPROP_SETTER) {
+ if (val != JSVAL_NULL) {
+ /* Mark the getter, then set val to setter. */
+ ok = (MarkSharpObjects(cx, JSVAL_TO_OBJECT(val),
+ NULL)
+ != NULL);
+ }
+ val = (jsval) ((JSScopeProperty*)prop)->setter;
+ }
+ } else {
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
+ }
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+#else
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val);
+#endif
+ if (!ok)
+ break;
+ if (!JSVAL_IS_PRIMITIVE(val) &&
+ !MarkSharpObjects(cx, JSVAL_TO_OBJECT(val), NULL)) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ if (!ok || !idap)
+ JS_DestroyIdArray(cx, ida);
+ if (!ok)
+ return NULL;
+ } else {
+ sharpid = JS_PTR_TO_UINT32(he->value);
+ if (sharpid == 0) {
+ sharpid = ++map->sharpgen << SHARP_ID_SHIFT;
+ he->value = JS_UINT32_TO_PTR(sharpid);
+ }
+ ida = NULL;
+ }
+ if (idap)
+ *idap = ida;
+ return he;
+}
+
+JSHashEntry *
+js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,
+ jschar **sp)
+{
+ JSSharpObjectMap *map;
+ JSHashTable *table;
+ JSIdArray *ida;
+ JSHashNumber hash;
+ JSHashEntry *he, **hep;
+ jsatomid sharpid;
+ char buf[20];
+ size_t len;
+
+ if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_ENTER_SHARP))
+ return NULL;
+
+ /* Set to null in case we return an early error. */
+ *sp = NULL;
+ map = &cx->sharpObjectMap;
+ table = map->table;
+ if (!table) {
+ table = JS_NewHashTable(8, js_hash_object, JS_CompareValues,
+ JS_CompareValues, NULL, NULL);
+ if (!table) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ map->table = table;
+ JS_KEEP_ATOMS(cx->runtime);
+ }
+
+ /* From this point the control must flow either through out: or bad:. */
+ ida = NULL;
+ if (map->depth == 0) {
+ he = MarkSharpObjects(cx, obj, &ida);
+ if (!he)
+ goto bad;
+ JS_ASSERT((JS_PTR_TO_UINT32(he->value) & SHARP_BIT) == 0);
+ if (!idap) {
+ JS_DestroyIdArray(cx, ida);
+ ida = NULL;
+ }
+ } else {
+ hash = js_hash_object(obj);
+ hep = JS_HashTableRawLookup(table, hash, obj);
+ he = *hep;
+
+ /*
+ * It's possible that the value of a property has changed from the
+ * first time the object's properties are traversed (when the property
+ * ids are entered into the hash table) to the second (when they are
+ * converted to strings), i.e., the OBJ_GET_PROPERTY() call is not
+ * idempotent.
+ */
+ if (!he) {
+ he = JS_HashTableRawAdd(table, hep, hash, obj, NULL);
+ if (!he) {
+ JS_ReportOutOfMemory(cx);
+ goto bad;
+ }
+ sharpid = 0;
+ goto out;
+ }
+ }
+
+ sharpid = JS_PTR_TO_UINT32(he->value);
+ if (sharpid != 0) {
+ len = JS_snprintf(buf, sizeof buf, "#%u%c",
+ sharpid >> SHARP_ID_SHIFT,
+ (sharpid & SHARP_BIT) ? '#' : '=');
+ *sp = js_InflateString(cx, buf, &len);
+ if (!*sp) {
+ if (ida)
+ JS_DestroyIdArray(cx, ida);
+ goto bad;
+ }
+ }
+
+out:
+ JS_ASSERT(he);
+ if ((sharpid & SHARP_BIT) == 0) {
+ if (idap && !ida) {
+ ida = JS_Enumerate(cx, obj);
+ if (!ida) {
+ if (*sp) {
+ JS_free(cx, *sp);
+ *sp = NULL;
+ }
+ goto bad;
+ }
+ }
+ map->depth++;
+ }
+
+ if (idap)
+ *idap = ida;
+ return he;
+
+bad:
+ /* Clean up the sharpObjectMap table on outermost error. */
+ if (map->depth == 0) {
+ JS_UNKEEP_ATOMS(cx->runtime);
+ map->sharpgen = 0;
+ JS_HashTableDestroy(map->table);
+ map->table = NULL;
+ }
+ return NULL;
+}
+
+void
+js_LeaveSharpObject(JSContext *cx, JSIdArray **idap)
+{
+ JSSharpObjectMap *map;
+ JSIdArray *ida;
+
+ map = &cx->sharpObjectMap;
+ JS_ASSERT(map->depth > 0);
+ if (--map->depth == 0) {
+ JS_UNKEEP_ATOMS(cx->runtime);
+ map->sharpgen = 0;
+ JS_HashTableDestroy(map->table);
+ map->table = NULL;
+ }
+ if (idap) {
+ ida = *idap;
+ if (ida) {
+ JS_DestroyIdArray(cx, ida);
+ *idap = NULL;
+ }
+ }
+}
+
+static intN
+gc_sharp_table_entry_marker(JSHashEntry *he, intN i, void *arg)
+{
+ JS_CALL_OBJECT_TRACER((JSTracer *)arg, (JSObject *)he->key,
+ "sharp table entry");
+ return JS_DHASH_NEXT;
+}
+
+void
+js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map)
+{
+ JS_ASSERT(map->depth > 0);
+ JS_ASSERT(map->table);
+
+ /*
+ * During recursive calls to MarkSharpObjects a non-native object or
+ * object with a custom getProperty method can potentially return an
+ * unrooted value or even cut from the object graph an argument of one of
+ * MarkSharpObjects recursive invocations. So we must protect map->table
+ * entries against GC.
+ *
+ * We can not simply use JSTempValueRooter to mark the obj argument of
+ * MarkSharpObjects during recursion as we have to protect *all* entries
+ * in JSSharpObjectMap including those that contains otherwise unreachable
+ * objects just allocated through custom getProperty. Otherwise newer
+ * allocations can re-use the address of an object stored in the hashtable
+ * confusing js_EnterSharpObject. So to address the problem we simply
+ * mark all objects from map->table.
+ *
+ * An alternative "proper" solution is to use JSTempValueRooter in
+ * MarkSharpObjects with code to remove during finalization entries
+ * with otherwise unreachable objects. But this is way too complex
+ * to justify spending efforts.
+ */
+ JS_HashTableEnumerateEntries(map->table, gc_sharp_table_entry_marker, trc);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+obj_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSBool ok, outermost;
+ JSObject *obj;
+ JSHashEntry *he;
+ JSIdArray *ida;
+ jschar *chars, *ochars, *vsharp;
+ const jschar *idstrchars, *vchars;
+ size_t nchars, idstrlength, gsoplength, vlength, vsharplength, curlen;
+ const char *comma;
+ jsint i, j, length, valcnt;
+ jsid id;
+#if JS_HAS_GETTER_SETTER
+ JSObject *obj2;
+ JSProperty *prop;
+ uintN attrs;
+#endif
+ jsval *val;
+ jsval localroot[4] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
+ JSTempValueRooter tvr;
+ JSString *gsopold[2];
+ JSString *gsop[2];
+ JSString *idstr, *valstr, *str;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT(cx, 4, localroot, &tvr);
+
+ /* If outermost, we need parentheses to be an expression, not a block. */
+ outermost = (cx->sharpObjectMap.depth == 0);
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !(he = js_EnterSharpObject(cx, obj, &ida, &chars))) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ if (IS_SHARP(he)) {
+ /*
+ * We didn't enter -- obj is already "sharp", meaning we've visited it
+ * already in our depth first search, and therefore chars contains a
+ * string of the form "#n#".
+ */
+ JS_ASSERT(!ida);
+#if JS_HAS_SHARP_VARS
+ nchars = js_strlen(chars);
+#else
+ chars[0] = '{';
+ chars[1] = '}';
+ chars[2] = 0;
+ nchars = 2;
+#endif
+ goto make_string;
+ }
+ JS_ASSERT(ida);
+ ok = JS_TRUE;
+
+ if (!chars) {
+ /* If outermost, allocate 4 + 1 for "({})" and the terminator. */
+ chars = (jschar *) malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
+ nchars = 0;
+ if (!chars)
+ goto error;
+ if (outermost)
+ chars[nchars++] = '(';
+ } else {
+ /* js_EnterSharpObject returned a string of the form "#n=" in chars. */
+ MAKE_SHARP(he);
+ nchars = js_strlen(chars);
+ chars = (jschar *)
+ realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
+ if (!chars) {
+ free(ochars);
+ goto error;
+ }
+ if (outermost) {
+ /*
+ * No need for parentheses around the whole shebang, because #n=
+ * unambiguously begins an object initializer, and never a block
+ * statement.
+ */
+ outermost = JS_FALSE;
+ }
+ }
+
+ chars[nchars++] = '{';
+
+ comma = NULL;
+
+ /*
+ * We have four local roots for cooked and raw value GC safety. Hoist the
+ * "localroot + 2" out of the loop using the val local, which refers to
+ * the raw (unconverted, "uncooked") values.
+ */
+ val = localroot + 2;
+
+ for (i = 0, length = ida->length; i < length; i++) {
+ JSBool idIsLexicalIdentifier, needOldStyleGetterSetter;
+
+ /* Get strings for id and value and GC-root them via vp. */
+ id = ida->vector[i];
+
+#if JS_HAS_GETTER_SETTER
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop);
+ if (!ok)
+ goto error;
+#endif
+
+ /*
+ * Convert id to a jsval and then to a string. Decide early whether we
+ * prefer get/set or old getter/setter syntax.
+ */
+ idstr = js_ValueToString(cx, ID_TO_VALUE(id));
+ if (!idstr) {
+ ok = JS_FALSE;
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ goto error;
+ }
+ *vp = STRING_TO_JSVAL(idstr); /* local root */
+ idIsLexicalIdentifier = js_IsIdentifier(idstr);
+ needOldStyleGetterSetter =
+ !idIsLexicalIdentifier ||
+ js_CheckKeyword(JSSTRING_CHARS(idstr),
+ JSSTRING_LENGTH(idstr)) != TOK_EOF;
+
+#if JS_HAS_GETTER_SETTER
+
+ valcnt = 0;
+ if (prop) {
+ ok = OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &attrs);
+ if (!ok) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ goto error;
+ }
+ if (OBJ_IS_NATIVE(obj2) &&
+ (attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ if (attrs & JSPROP_GETTER) {
+ val[valcnt] = (jsval) ((JSScopeProperty *)prop)->getter;
+ gsopold[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.getterAtom);
+ gsop[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.getAtom);
+
+ valcnt++;
+ }
+ if (attrs & JSPROP_SETTER) {
+ val[valcnt] = (jsval) ((JSScopeProperty *)prop)->setter;
+ gsopold[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.setterAtom);
+ gsop[valcnt] =
+ ATOM_TO_STRING(cx->runtime->atomState.setAtom);
+
+ valcnt++;
+ }
+ } else {
+ valcnt = 1;
+ gsop[0] = NULL;
+ gsopold[0] = NULL;
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ }
+
+#else /* !JS_HAS_GETTER_SETTER */
+
+ /*
+ * We simplify the source code at the price of minor dead code bloat in
+ * the ECMA version (for testing only, see jsversion.h). The null
+ * default values in gsop[j] suffice to disable non-ECMA getter and
+ * setter code.
+ */
+ valcnt = 1;
+ gsop[0] = NULL;
+ gsopold[0] = NULL;
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &val[0]);
+
+#endif /* !JS_HAS_GETTER_SETTER */
+
+ if (!ok)
+ goto error;
+
+ /*
+ * If id is a string that's not an identifier, then it needs to be
+ * quoted. Also, negative integer ids must be quoted.
+ */
+ if (JSID_IS_ATOM(id)
+ ? !idIsLexicalIdentifier
+ : (!JSID_IS_INT(id) || JSID_TO_INT(id) < 0)) {
+ idstr = js_QuoteString(cx, idstr, (jschar)'\'');
+ if (!idstr) {
+ ok = JS_FALSE;
+ goto error;
+ }
+ *vp = STRING_TO_JSVAL(idstr); /* local root */
+ }
+ JSSTRING_CHARS_AND_LENGTH(idstr, idstrchars, idstrlength);
+
+ for (j = 0; j < valcnt; j++) {
+ /* Convert val[j] to its canonical source form. */
+ valstr = js_ValueToSource(cx, val[j]);
+ if (!valstr) {
+ ok = JS_FALSE;
+ goto error;
+ }
+ localroot[j] = STRING_TO_JSVAL(valstr); /* local root */
+ JSSTRING_CHARS_AND_LENGTH(valstr, vchars, vlength);
+
+ if (vchars[0] == '#')
+ needOldStyleGetterSetter = JS_TRUE;
+
+ if (needOldStyleGetterSetter)
+ gsop[j] = gsopold[j];
+
+ /* If val[j] is a non-sharp object, consider sharpening it. */
+ vsharp = NULL;
+ vsharplength = 0;
+#if JS_HAS_SHARP_VARS
+ if (!JSVAL_IS_PRIMITIVE(val[j]) && vchars[0] != '#') {
+ he = js_EnterSharpObject(cx, JSVAL_TO_OBJECT(val[j]), NULL,
+ &vsharp);
+ if (!he) {
+ ok = JS_FALSE;
+ goto error;
+ }
+ if (IS_SHARP(he)) {
+ vchars = vsharp;
+ vlength = js_strlen(vchars);
+ needOldStyleGetterSetter = JS_TRUE;
+ gsop[j] = gsopold[j];
+ } else {
+ if (vsharp) {
+ vsharplength = js_strlen(vsharp);
+ MAKE_SHARP(he);
+ needOldStyleGetterSetter = JS_TRUE;
+ gsop[j] = gsopold[j];
+ }
+ js_LeaveSharpObject(cx, NULL);
+ }
+ }
+#endif
+
+#ifndef OLD_GETTER_SETTER
+ /*
+ * Remove '(function ' from the beginning of valstr and ')' from the
+ * end so that we can put "get" in front of the function definition.
+ */
+ if (gsop[j] && VALUE_IS_FUNCTION(cx, val[j]) &&
+ !needOldStyleGetterSetter) {
+ JSFunction *fun = JS_ValueToFunction(cx, val[j]);
+ const jschar *start = vchars;
+ const jschar *end = vchars + vlength;
+
+ uint8 parenChomp = 0;
+ if (vchars[0] == '(') {
+ vchars++;
+ parenChomp = 1;
+ }
+
+ /*
+ * Try to jump "getter" or "setter" keywords, if we suspect
+ * they might appear here. This code can be confused by people
+ * defining Function.prototype.toString, so let's be cautious.
+ */
+ if (JSFUN_GETTER_TEST(fun->flags) ||
+ JSFUN_SETTER_TEST(fun->flags)) { /* skip "getter/setter" */
+ const jschar *tmp = js_strchr_limit(vchars, ' ', end);
+ if (tmp)
+ vchars = tmp + 1;
+ }
+
+ /* Try to jump "function" keyword. */
+ if (vchars)
+ vchars = js_strchr_limit(vchars, ' ', end);
+
+ if (vchars) {
+ if (*vchars == ' ')
+ vchars++;
+ vlength = end - vchars - parenChomp;
+ } else {
+ gsop[j] = NULL;
+ vchars = start;
+ }
+ }
+#else
+ needOldStyleGetterSetter = JS_TRUE;
+ gsop[j] = gsopold[j];
+#endif
+
+#define SAFE_ADD(n) \
+ JS_BEGIN_MACRO \
+ size_t n_ = (n); \
+ curlen += n_; \
+ if (curlen < n_) \
+ goto overflow; \
+ JS_END_MACRO
+
+ curlen = nchars;
+ if (comma)
+ SAFE_ADD(2);
+ SAFE_ADD(idstrlength + 1);
+ if (gsop[j])
+ SAFE_ADD(JSSTRING_LENGTH(gsop[j]) + 1);
+ SAFE_ADD(vsharplength);
+ SAFE_ADD(vlength);
+ /* Account for the trailing null. */
+ SAFE_ADD((outermost ? 2 : 1) + 1);
+#undef SAFE_ADD
+
+ if (curlen > (size_t)-1 / sizeof(jschar))
+ goto overflow;
+
+ /* Allocate 1 + 1 at end for closing brace and terminating 0. */
+ chars = (jschar *)
+ realloc((ochars = chars), curlen * sizeof(jschar));
+ if (!chars) {
+ /* Save code space on error: let JS_free ignore null vsharp. */
+ JS_free(cx, vsharp);
+ free(ochars);
+ goto error;
+ }
+
+ if (comma) {
+ chars[nchars++] = comma[0];
+ chars[nchars++] = comma[1];
+ }
+ comma = ", ";
+
+ if (needOldStyleGetterSetter) {
+ js_strncpy(&chars[nchars], idstrchars, idstrlength);
+ nchars += idstrlength;
+ if (gsop[j]) {
+ chars[nchars++] = ' ';
+ gsoplength = JSSTRING_LENGTH(gsop[j]);
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]),
+ gsoplength);
+ nchars += gsoplength;
+ }
+ chars[nchars++] = ':';
+ } else { /* New style "decompilation" */
+ if (gsop[j]) {
+ gsoplength = JSSTRING_LENGTH(gsop[j]);
+ js_strncpy(&chars[nchars], JSSTRING_CHARS(gsop[j]),
+ gsoplength);
+ nchars += gsoplength;
+ chars[nchars++] = ' ';
+ }
+ js_strncpy(&chars[nchars], idstrchars, idstrlength);
+ nchars += idstrlength;
+ /* Extraneous space after id here will be extracted later */
+ chars[nchars++] = gsop[j] ? ' ' : ':';
+ }
+
+ if (vsharplength) {
+ js_strncpy(&chars[nchars], vsharp, vsharplength);
+ nchars += vsharplength;
+ }
+ js_strncpy(&chars[nchars], vchars, vlength);
+ nchars += vlength;
+
+ if (vsharp)
+ JS_free(cx, vsharp);
+ }
+ }
+
+ chars[nchars++] = '}';
+ if (outermost)
+ chars[nchars++] = ')';
+ chars[nchars] = 0;
+
+ error:
+ js_LeaveSharpObject(cx, &ida);
+
+ if (!ok) {
+ if (chars)
+ free(chars);
+ goto out;
+ }
+
+ if (!chars) {
+ JS_ReportOutOfMemory(cx);
+ ok = JS_FALSE;
+ goto out;
+ }
+ make_string:
+ str = js_NewString(cx, chars, nchars);
+ if (!str) {
+ free(chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ ok = JS_TRUE;
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+
+ overflow:
+ JS_free(cx, vsharp);
+ free(chars);
+ chars = NULL;
+ goto error;
+}
+#endif /* JS_HAS_TOSOURCE */
+
+static JSBool
+obj_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jschar *chars;
+ size_t nchars;
+ const char *clazz, *prefix;
+ JSString *str;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ obj = js_GetWrappedObject(cx, obj);
+ clazz = OBJ_GET_CLASS(cx, obj)->name;
+ nchars = 9 + strlen(clazz); /* 9 for "[object ]" */
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+
+ prefix = "[object ";
+ nchars = 0;
+ while ((chars[nchars] = (jschar)*prefix) != 0)
+ nchars++, prefix++;
+ while ((chars[nchars] = (jschar)*clazz) != 0)
+ nchars++, clazz++;
+ chars[nchars++] = ']';
+ chars[nchars] = 0;
+
+ str = js_NewString(cx, chars, nchars);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+obj_toLocaleString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval thisv;
+ JSString *str;
+
+ thisv = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(thisv))
+ return JS_FALSE;
+
+ str = js_ValueToString(cx, thisv);
+ if (!str)
+ return JS_FALSE;
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+obj_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = JS_THIS(cx, vp);
+ return !JSVAL_IS_NULL(*vp);
+}
+
+/*
+ * Check whether principals subsumes scopeobj's principals, and return true
+ * if so (or if scopeobj has no principals, for backward compatibility with
+ * the JS API, which does not require principals), and false otherwise.
+ */
+JSBool
+js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
+ JSPrincipals *principals, JSAtom *caller)
+{
+ JSSecurityCallbacks *callbacks;
+ JSPrincipals *scopePrincipals;
+ const char *callerstr;
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ scopePrincipals = callbacks->findObjectPrincipals(cx, scopeobj);
+ if (!principals || !scopePrincipals ||
+ !principals->subsume(principals, scopePrincipals)) {
+ callerstr = js_AtomToPrintableString(cx, caller);
+ if (!callerstr)
+ return JS_FALSE;
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_INDIRECT_CALL, callerstr);
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+JSObject *
+js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller)
+{
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSObject *inner;
+
+ if (!scopeobj)
+ goto bad;
+
+ OBJ_TO_INNER_OBJECT(cx, scopeobj);
+ if (!scopeobj)
+ return NULL;
+
+ inner = scopeobj;
+
+ /* XXX This is an awful gross hack. */
+ while (scopeobj) {
+ clasp = OBJ_GET_CLASS(cx, scopeobj);
+ if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ xclasp = (JSExtendedClass*)clasp;
+ if (xclasp->innerObject &&
+ xclasp->innerObject(cx, scopeobj) != scopeobj) {
+ goto bad;
+ }
+ }
+
+ scopeobj = OBJ_GET_PARENT(cx, scopeobj);
+ }
+
+ return inner;
+
+bad:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_INDIRECT_CALL, caller);
+ return NULL;
+}
+
+const char *
+js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
+ JSPrincipals *principals, uintN *linenop)
+{
+ uint32 flags;
+#ifdef DEBUG
+ JSSecurityCallbacks *callbacks = JS_GetSecurityCallbacks(cx);
+#endif
+
+ JS_ASSERT(principals || !(callbacks && callbacks->findObjectPrincipals));
+ flags = JS_GetScriptFilenameFlags(caller->script);
+ if ((flags & JSFILENAME_PROTECTED) &&
+ principals &&
+ strcmp(principals->codebase, "[System Principal]")) {
+ *linenop = 0;
+ return principals->codebase;
+ }
+
+ if (caller->regs && *caller->regs->pc == JSOP_EVAL) {
+ JS_ASSERT(caller->regs->pc[JSOP_EVAL_LENGTH] == JSOP_LINENO);
+ *linenop = GET_UINT16(caller->regs->pc + JSOP_EVAL_LENGTH);
+ } else {
+ *linenop = js_FramePCToLineNumber(cx, caller);
+ }
+ return caller->script->filename;
+}
+
+static JSBool
+obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSStackFrame *fp, *caller;
+ JSBool indirectCall;
+ JSObject *scopeobj;
+ JSString *str;
+ const char *file;
+ uintN line;
+ JSPrincipals *principals;
+ uint32 tcflags;
+ JSScript *script;
+ JSBool ok;
+#if JS_HAS_EVAL_THIS_SCOPE
+ JSObject *callerScopeChain = NULL, *callerVarObj = NULL;
+ JSObject *setCallerScopeChain = NULL;
+ JSBool setCallerVarObj = JS_FALSE;
+#endif
+
+ fp = cx->fp;
+ caller = JS_GetScriptedCaller(cx, fp);
+ indirectCall = (caller && caller->regs && *caller->regs->pc != JSOP_EVAL);
+
+ /*
+ * Ban all indirect uses of eval (global.foo = eval; global.foo(...)) and
+ * calls that attempt to use a non-global object as the "with" object in
+ * the former indirect case.
+ */
+ scopeobj = OBJ_GET_PARENT(cx, obj);
+ if (scopeobj) {
+ scopeobj = js_GetWrappedObject(cx, obj);
+ scopeobj = OBJ_GET_PARENT(cx, scopeobj);
+ }
+ if (indirectCall || scopeobj) {
+ uintN flags = scopeobj
+ ? JSREPORT_ERROR
+ : JSREPORT_STRICT | JSREPORT_WARNING;
+ if (!JS_ReportErrorFlagsAndNumber(cx, flags, js_GetErrorMessage, NULL,
+ JSMSG_BAD_INDIRECT_CALL,
+ js_eval_str)) {
+ return JS_FALSE;
+ }
+ }
+
+ if (!JSVAL_IS_STRING(argv[0])) {
+ *rval = argv[0];
+ return JS_TRUE;
+ }
+
+ /*
+ * If the caller is a lightweight function and doesn't have a variables
+ * object, then we need to provide one for the compiler to stick any
+ * declared (var) variables into.
+ */
+ if (caller && !caller->varobj && !js_GetCallObject(cx, caller, NULL))
+ return JS_FALSE;
+
+ /* eval no longer takes an optional trailing argument. */
+ if (argc >= 2 &&
+ !JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_EVAL_ARITY)) {
+ return JS_FALSE;
+ }
+
+ /* From here on, control must exit through label out with ok set. */
+ MUST_FLOW_THROUGH("out");
+ if (!scopeobj) {
+#if JS_HAS_EVAL_THIS_SCOPE
+ /* If obj.eval(str), emulate 'with (obj) eval(str)' in the caller. */
+ if (indirectCall) {
+ callerScopeChain = js_GetScopeChain(cx, caller);
+ if (!callerScopeChain) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ if (obj != callerScopeChain) {
+ ok = js_CheckPrincipalsAccess(cx, obj,
+ caller->script->principals,
+ cx->runtime->atomState.evalAtom);
+ if (!ok)
+ goto out;
+
+ scopeobj = js_NewWithObject(cx, obj, callerScopeChain, -1);
+ if (!scopeobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ /* Set fp->scopeChain too, for the compiler. */
+ caller->scopeChain = fp->scopeChain = scopeobj;
+
+ /* Remember scopeobj so we can null its private when done. */
+ setCallerScopeChain = scopeobj;
+ }
+
+ callerVarObj = caller->varobj;
+ if (obj != callerVarObj) {
+ /* Set fp->varobj too, for the compiler. */
+ caller->varobj = fp->varobj = obj;
+ setCallerVarObj = JS_TRUE;
+ }
+ }
+#endif
+
+ /*
+ * Compile using caller's current scope object.
+ *
+ * NB: This means that native callers (who reach this point through
+ * the C API) must use the two parameter form.
+ */
+ if (caller) {
+ scopeobj = js_GetScopeChain(cx, caller);
+ if (!scopeobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ }
+
+ /* Ensure we compile this eval with the right object in the scope chain. */
+ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str);
+ if (!scopeobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ str = JSVAL_TO_STRING(argv[0]);
+ if (caller) {
+ principals = JS_EvalFramePrincipals(cx, fp, caller);
+ file = js_ComputeFilename(cx, caller, principals, &line);
+ } else {
+ file = NULL;
+ line = 0;
+ principals = NULL;
+ }
+
+ tcflags = TCF_COMPILE_N_GO;
+ if (caller)
+ tcflags |= TCF_PUT_STATIC_DEPTH(caller->script->staticDepth + 1);
+ script = js_CompileScript(cx, scopeobj, caller, principals, tcflags,
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
+ NULL, file, line);
+ if (!script) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ if (argc < 2) {
+ /* Execute using caller's new scope object (might be a Call object). */
+ if (caller)
+ scopeobj = caller->scopeChain;
+ }
+
+ /*
+ * Belt-and-braces: check that the lesser of eval's principals and the
+ * caller's principals has access to scopeobj.
+ */
+ ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
+ cx->runtime->atomState.evalAtom);
+ if (ok)
+ ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
+
+ script->u.nextToGC = JS_SCRIPTS_TO_GC(cx);
+ JS_SCRIPTS_TO_GC(cx) = script;
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = NULL;
+#endif
+
+out:
+#if JS_HAS_EVAL_THIS_SCOPE
+ /* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */
+ if (setCallerScopeChain) {
+ caller->scopeChain = callerScopeChain;
+ JS_ASSERT(OBJ_GET_CLASS(cx, setCallerScopeChain) == &js_WithClass);
+ JS_SetPrivate(cx, setCallerScopeChain, NULL);
+ }
+ if (setCallerVarObj)
+ caller->varobj = callerVarObj;
+#endif
+ return ok;
+}
+
+#if JS_HAS_OBJ_WATCHPOINT
+
+static JSBool
+obj_watch_handler(JSContext *cx, JSObject *obj, jsval id, jsval old, jsval *nvp,
+ void *closure)
+{
+ JSObject *callable;
+ JSSecurityCallbacks *callbacks;
+ JSStackFrame *caller;
+ JSPrincipals *subject, *watcher;
+ JSResolvingKey key;
+ JSResolvingEntry *entry;
+ uint32 generation;
+ jsval argv[3];
+ JSBool ok;
+
+ callable = (JSObject *) closure;
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (callbacks && callbacks->findObjectPrincipals) {
+ /* Skip over any obj_watch_* frames between us and the real subject. */
+ caller = JS_GetScriptedCaller(cx, cx->fp);
+ if (caller) {
+ /*
+ * Only call the watch handler if the watcher is allowed to watch
+ * the currently executing script.
+ */
+ watcher = callbacks->findObjectPrincipals(cx, callable);
+ subject = JS_StackFramePrincipals(cx, caller);
+
+ if (watcher && subject && !watcher->subsume(watcher, subject)) {
+ /* Silently don't call the watch handler. */
+ return JS_TRUE;
+ }
+ }
+ }
+
+ /* Avoid recursion on (obj, id) already being watched on cx. */
+ key.obj = obj;
+ key.id = id;
+ if (!js_StartResolving(cx, &key, JSRESFLAG_WATCH, &entry))
+ return JS_FALSE;
+ if (!entry)
+ return JS_TRUE;
+ generation = cx->resolvingTable->generation;
+
+ argv[0] = id;
+ argv[1] = old;
+ argv[2] = *nvp;
+ ok = js_InternalCall(cx, obj, OBJECT_TO_JSVAL(callable), 3, argv, nvp);
+ js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation);
+ return ok;
+}
+
+static JSBool
+obj_watch(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *callable;
+ jsval userid, value;
+ jsid propid;
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc <= 1) {
+ js_ReportMissingArg(cx, vp, 1);
+ return JS_FALSE;
+ }
+
+ callable = js_ValueToCallableObject(cx, &vp[3], 0);
+ if (!callable)
+ return JS_FALSE;
+
+ /* Compute the unique int/atom symbol id needed by js_LookupProperty. */
+ userid = vp[2];
+ if (!JS_ValueToId(cx, userid, &propid))
+ return JS_FALSE;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_CHECK_ACCESS(cx, obj, propid, JSACC_WATCH, &value, &attrs))
+ return JS_FALSE;
+ if (attrs & JSPROP_READONLY)
+ return JS_TRUE;
+ *vp = JSVAL_VOID;
+
+ if (OBJ_IS_DENSE_ARRAY(cx, obj) && !js_MakeArraySlow(cx, obj))
+ return JS_FALSE;
+ return JS_SetWatchPoint(cx, obj, userid, obj_watch_handler, callable);
+}
+
+static JSBool
+obj_unwatch(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ return JS_ClearWatchPoint(cx, obj, argc != 0 ? vp[2] : JSVAL_VOID,
+ NULL, NULL);
+}
+
+#endif /* JS_HAS_OBJ_WATCHPOINT */
+
+/*
+ * Prototype and property query methods, to complement the 'in' and
+ * 'instanceof' operators.
+ */
+
+/* Proposed ECMA 15.2.4.5. */
+static JSBool
+obj_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj &&
+ js_HasOwnPropertyHelper(cx, obj->map->ops->lookupProperty, argc, vp);
+}
+
+JSBool
+js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
+ jsval *vp)
+{
+ jsid id;
+ JSObject *obj;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_HasOwnProperty(cx, lookup, obj, id, vp);
+}
+
+JSBool
+js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
+ jsval *vp)
+{
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ if (!lookup(cx, obj, id, &obj2, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ *vp = JSVAL_FALSE;
+ } else if (obj2 == obj) {
+ *vp = JSVAL_TRUE;
+ } else {
+ JSClass *clasp;
+ JSExtendedClass *xclasp;
+ JSObject *outer;
+
+ clasp = OBJ_GET_CLASS(cx, obj2);
+ if (!(clasp->flags & JSCLASS_IS_EXTENDED) ||
+ !(xclasp = (JSExtendedClass *) clasp)->outerObject) {
+ outer = NULL;
+ } else {
+ outer = xclasp->outerObject(cx, obj2);
+ if (!outer)
+ return JS_FALSE;
+ }
+ if (outer == obj) {
+ *vp = JSVAL_TRUE;
+ } else if (OBJ_IS_NATIVE(obj2) && OBJ_GET_CLASS(cx, obj) == clasp) {
+ /*
+ * The combination of JSPROP_SHARED and JSPROP_PERMANENT in a
+ * delegated property makes that property appear to be direct in
+ * all delegating instances of the same native class. This hack
+ * avoids bloating every function instance with its own 'length'
+ * (AKA 'arity') property. But it must not extend across class
+ * boundaries, to avoid making hasOwnProperty lie (bug 320854).
+ *
+ * It's not really a hack, of course: a permanent property can't
+ * be deleted, and JSPROP_SHARED means "don't allocate a slot in
+ * any instance, prototype or delegating". Without a slot, and
+ * without the ability to remove and recreate (with differences)
+ * the property, there is no way to tell whether it is directly
+ * owned, or indirectly delegated.
+ */
+ sprop = (JSScopeProperty *)prop;
+ *vp = BOOLEAN_TO_JSVAL(SPROP_IS_SHARED_PERMANENT(sprop));
+ } else {
+ *vp = JSVAL_FALSE;
+ }
+ }
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static int32 FASTCALL
+Object_p_hasOwnProperty(JSContext* cx, JSObject* obj, JSString *str)
+{
+ jsid id;
+ jsval v;
+
+ if (!js_ValueToStringId(cx, STRING_TO_JSVAL(str), &id))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ if (!js_HasOwnProperty(cx, obj->map->ops->lookupProperty, obj, id, &v))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ return JSVAL_TO_BOOLEAN(v);
+}
+#endif
+
+/* Proposed ECMA 15.2.4.6. */
+static JSBool
+obj_isPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSBool b;
+
+ if (!js_IsDelegate(cx, JS_THIS_OBJECT(cx, vp),
+ argc != 0 ? vp[2] : JSVAL_VOID, &b)) {
+ return JS_FALSE;
+ }
+ *vp = BOOLEAN_TO_JSVAL(b);
+ return JS_TRUE;
+}
+
+/* Proposed ECMA 15.2.4.7. */
+static JSBool
+obj_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsid id;
+ JSObject *obj;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_PropertyIsEnumerable(cx, obj, id, vp);
+}
+
+#ifdef JS_TRACER
+static int32 FASTCALL
+Object_p_propertyIsEnumerable(JSContext* cx, JSObject* obj, JSString *str)
+{
+ jsid id = ATOM_TO_JSID(STRING_TO_JSVAL(str));
+ jsval v;
+ if (!js_PropertyIsEnumerable(cx, obj, id, &v))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_BOOLEAN(v));
+ return JSVAL_TO_BOOLEAN(v);
+}
+#endif
+
+JSBool
+js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *pobj;
+ uintN attrs;
+ JSProperty *prop;
+ JSBool ok;
+
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+
+ if (!prop) {
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ /*
+ * XXX ECMA spec error compatible: return false unless hasOwnProperty.
+ * The ECMA spec really should be fixed so propertyIsEnumerable and the
+ * for..in loop agree on whether prototype properties are enumerable,
+ * obviously by fixing this method (not by breaking the for..in loop!).
+ *
+ * We check here for shared permanent prototype properties, which should
+ * be treated as if they are local to obj. They are an implementation
+ * technique used to satisfy ECMA requirements; users should not be able
+ * to distinguish a shared permanent proto-property from a local one.
+ */
+ if (pobj != obj &&
+ !(OBJ_IS_NATIVE(pobj) &&
+ SPROP_IS_SHARED_PERMANENT((JSScopeProperty *)prop))) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ ok = OBJ_GET_ATTRIBUTES(cx, pobj, id, prop, &attrs);
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ if (ok)
+ *vp = BOOLEAN_TO_JSVAL((attrs & JSPROP_ENUMERATE) != 0);
+ return ok;
+}
+
+#if JS_HAS_GETTER_SETTER
+static JSBool
+obj_defineGetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval fval, junk;
+ jsid id;
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc <= 1 || JS_TypeOfValue(cx, vp[3]) != JSTYPE_FUNCTION) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ js_getter_str);
+ return JS_FALSE;
+ }
+ fval = vp[3];
+
+ if (!JS_ValueToId(cx, vp[2], &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL))
+ return JS_FALSE;
+ /*
+ * Getters and setters are just like watchpoints from an access
+ * control point of view.
+ */
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
+ (JSPropertyOp) JSVAL_TO_OBJECT(fval),
+ JS_PropertyStub,
+ JSPROP_ENUMERATE | JSPROP_GETTER | JSPROP_SHARED,
+ NULL);
+}
+
+static JSBool
+obj_defineSetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval fval, junk;
+ jsid id;
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc <= 1 || JS_TypeOfValue(cx, vp[3]) != JSTYPE_FUNCTION) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ js_setter_str);
+ return JS_FALSE;
+ }
+ fval = vp[3];
+
+ if (!JS_ValueToId(cx, vp[2], &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !js_CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL))
+ return JS_FALSE;
+ /*
+ * Getters and setters are just like watchpoints from an access
+ * control point of view.
+ */
+ if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &junk, &attrs))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ return OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,
+ JS_PropertyStub,
+ (JSPropertyOp) JSVAL_TO_OBJECT(fval),
+ JSPROP_ENUMERATE | JSPROP_SETTER | JSPROP_SHARED,
+ NULL);
+}
+
+static JSBool
+obj_lookupGetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsid id;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ if (prop) {
+ if (OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (sprop->attrs & JSPROP_GETTER)
+ *vp = OBJECT_TO_JSVAL(sprop->getter);
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+obj_lookupSetter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsid id;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ if (!JS_ValueToId(cx, argc != 0 ? vp[2] : JSVAL_VOID, &id))
+ return JS_FALSE;
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj || !OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ *vp = JSVAL_VOID;
+ if (prop) {
+ if (OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (sprop->attrs & JSPROP_SETTER)
+ *vp = OBJECT_TO_JSVAL(sprop->setter);
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ return JS_TRUE;
+}
+#endif /* JS_HAS_GETTER_SETTER */
+
+JSBool
+obj_getPrototypeOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ uintN attrs;
+
+ if (argc == 0) {
+ js_ReportMissingArg(cx, vp, 0);
+ return JS_FALSE;
+ }
+
+ obj = js_ValueToNonNullObject(cx, vp[2]);
+ if (!obj)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(obj);
+
+ return OBJ_CHECK_ACCESS(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState.protoAtom),
+ JSACC_PROTO, vp, &attrs);
+}
+
+#if JS_HAS_OBJ_WATCHPOINT
+const char js_watch_str[] = "watch";
+const char js_unwatch_str[] = "unwatch";
+#endif
+const char js_hasOwnProperty_str[] = "hasOwnProperty";
+const char js_isPrototypeOf_str[] = "isPrototypeOf";
+const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
+#if JS_HAS_GETTER_SETTER
+const char js_defineGetter_str[] = "__defineGetter__";
+const char js_defineSetter_str[] = "__defineSetter__";
+const char js_lookupGetter_str[] = "__lookupGetter__";
+const char js_lookupSetter_str[] = "__lookupSetter__";
+#endif
+
+JS_DEFINE_TRCINFO_1(obj_hasOwnProperty,
+ (3, (static, BOOL_FAIL, Object_p_hasOwnProperty, CONTEXT, THIS, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(obj_propertyIsEnumerable,
+ (3, (static, BOOL_FAIL, Object_p_propertyIsEnumerable, CONTEXT, THIS, STRING, 0, 0)))
+
+static JSFunctionSpec object_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, obj_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, obj_toString, 0,0),
+ JS_FN(js_toLocaleString_str, obj_toLocaleString, 0,0),
+ JS_FN(js_valueOf_str, obj_valueOf, 0,0),
+#if JS_HAS_OBJ_WATCHPOINT
+ JS_FN(js_watch_str, obj_watch, 2,0),
+ JS_FN(js_unwatch_str, obj_unwatch, 1,0),
+#endif
+ JS_TN(js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,
+ obj_hasOwnProperty_trcinfo),
+ JS_FN(js_isPrototypeOf_str, obj_isPrototypeOf, 1,0),
+ JS_TN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,
+ obj_propertyIsEnumerable_trcinfo),
+#if JS_HAS_GETTER_SETTER
+ JS_FN(js_defineGetter_str, obj_defineGetter, 2,0),
+ JS_FN(js_defineSetter_str, obj_defineSetter, 2,0),
+ JS_FN(js_lookupGetter_str, obj_lookupGetter, 1,0),
+ JS_FN(js_lookupSetter_str, obj_lookupSetter, 1,0),
+#endif
+ JS_FS_END
+};
+
+static JSFunctionSpec object_static_methods[] = {
+ JS_FN("getPrototypeOf", obj_getPrototypeOf, 1,0),
+ JS_FS_END
+};
+
+JSBool
+js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (argc == 0) {
+ /* Trigger logic below to construct a blank object. */
+ obj = NULL;
+ } else {
+ /* If argv[0] is null or undefined, obj comes back null. */
+ if (!js_ValueToObject(cx, argv[0], &obj))
+ return JS_FALSE;
+ }
+ if (!obj) {
+ JS_ASSERT(!argc || JSVAL_IS_NULL(argv[0]) || JSVAL_IS_VOID(argv[0]));
+ if (cx->fp->flags & JSFRAME_CONSTRUCTING)
+ return JS_TRUE;
+ obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ }
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/*
+ * ObjectOps and Class for with-statement stack objects.
+ */
+static JSBool
+with_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_LookupProperty(cx, obj, id, objp, propp);
+ return OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp);
+}
+
+static JSBool
+with_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_GetProperty(cx, obj, id, vp);
+ return OBJ_GET_PROPERTY(cx, proto, id, vp);
+}
+
+static JSBool
+with_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_SetProperty(cx, obj, id, vp);
+ return OBJ_SET_PROPERTY(cx, proto, id, vp);
+}
+
+static JSBool
+with_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_GetAttributes(cx, obj, id, prop, attrsp);
+ return OBJ_GET_ATTRIBUTES(cx, proto, id, prop, attrsp);
+}
+
+static JSBool
+with_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_SetAttributes(cx, obj, id, prop, attrsp);
+ return OBJ_SET_ATTRIBUTES(cx, proto, id, prop, attrsp);
+}
+
+static JSBool
+with_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_DeleteProperty(cx, obj, id, rval);
+ return OBJ_DELETE_PROPERTY(cx, proto, id, rval);
+}
+
+static JSBool
+with_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_DefaultValue(cx, obj, hint, vp);
+ return OBJ_DEFAULT_VALUE(cx, proto, hint, vp);
+}
+
+static JSBool
+with_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_Enumerate(cx, obj, enum_op, statep, idp);
+ return OBJ_ENUMERATE(cx, proto, enum_op, statep, idp);
+}
+
+static JSBool
+with_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return js_CheckAccess(cx, obj, id, mode, vp, attrsp);
+ return OBJ_CHECK_ACCESS(cx, proto, id, mode, vp, attrsp);
+}
+
+static JSObject *
+with_ThisObject(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto = OBJ_GET_PROTO(cx, obj);
+ if (!proto)
+ return obj;
+ return OBJ_THIS_OBJECT(cx, proto);
+}
+
+JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps = {
+ js_NewObjectMap, js_DestroyObjectMap,
+ with_LookupProperty, js_DefineProperty,
+ with_GetProperty, with_SetProperty,
+ with_GetAttributes, with_SetAttributes,
+ with_DeleteProperty, with_DefaultValue,
+ with_Enumerate, with_CheckAccess,
+ with_ThisObject, NATIVE_DROP_PROPERTY,
+ NULL, NULL,
+ NULL, NULL,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ js_TraceObject, js_Clear,
+ NULL, NULL
+};
+
+static JSObjectOps *
+with_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_WithObjectOps;
+}
+
+JSClass js_WithClass = {
+ "With",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_IS_ANONYMOUS,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ with_getObjectOps,
+ 0,0,0,0,0,0,0
+};
+
+JSObject *
+js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_WithClass, proto, parent, 0);
+ if (!obj)
+ return NULL;
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(cx->fp));
+ OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
+ return obj;
+}
+
+JSObject *
+js_NewBlockObject(JSContext *cx)
+{
+ JSObject *obj;
+ JSBool ok;
+
+ /*
+ * Null obj's proto slot so that Object.prototype.* does not pollute block
+ * scopes. Make sure obj has its own scope too, since clearing proto does
+ * not affect OBJ_SCOPE(obj).
+ */
+ obj = js_NewObject(cx, &js_BlockClass, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+ JS_LOCK_OBJ(cx, obj);
+ ok = js_GetMutableScope(cx, obj) != NULL;
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!ok)
+ return NULL;
+ OBJ_CLEAR_PROTO(cx, obj);
+ return obj;
+}
+
+JSObject *
+js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
+ JSStackFrame *fp)
+{
+ JSObject *clone;
+
+ JS_ASSERT(STOBJ_GET_CLASS(proto) == &js_BlockClass);
+ JS_ASSERT(!OBJ_IS_CLONED_BLOCK(proto));
+ clone = js_NewObject(cx, &js_BlockClass, proto, parent, 0);
+ if (!clone)
+ return NULL;
+ STOBJ_SET_SLOT(clone, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(fp));
+ STOBJ_SET_SLOT(clone, JSSLOT_BLOCK_DEPTH,
+ OBJ_GET_SLOT(cx, proto, JSSLOT_BLOCK_DEPTH));
+ JS_ASSERT(OBJ_IS_CLONED_BLOCK(clone));
+ return clone;
+}
+
+JSBool
+js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
+{
+ JSStackFrame *fp;
+ JSObject *obj;
+ uintN depth, count;
+
+ /* Blocks have one fixed slot available for the first local.*/
+ JS_STATIC_ASSERT(JS_INITIAL_NSLOTS == JSSLOT_BLOCK_DEPTH + 2);
+
+ fp = cx->fp;
+ obj = fp->scopeChain;
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_BlockClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, obj) == cx->fp);
+ JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
+
+ /*
+ * Block objects should never be exposed to scripts. Thus the clone should
+ * not own the property map and rather always share it with the prototype
+ * object. This allows to skip updating OBJ_SCOPE(obj)->map.freeslot after
+ * we copy the stack slots into reserved slots.
+ */
+ JS_ASSERT(OBJ_SCOPE(obj)->object != obj);
+
+ /* Block objects should not have reserved slots before they are put. */
+ JS_ASSERT(STOBJ_NSLOTS(obj) == JS_INITIAL_NSLOTS);
+
+ /* The block and its locals must be on the current stack for GC safety. */
+ depth = OBJ_BLOCK_DEPTH(cx, obj);
+ count = OBJ_BLOCK_COUNT(cx, obj);
+ JS_ASSERT(depth <= (size_t) (fp->regs->sp - StackBase(fp)));
+ JS_ASSERT(count <= (size_t) (fp->regs->sp - StackBase(fp) - depth));
+
+ /* See comments in CheckDestructuring from jsparse.c. */
+ JS_ASSERT(count >= 1);
+
+ depth += fp->script->nfixed;
+ obj->fslots[JSSLOT_BLOCK_DEPTH + 1] = fp->slots[depth];
+ if (normalUnwind && count > 1) {
+ --count;
+ JS_LOCK_OBJ(cx, obj);
+ if (!js_ReallocSlots(cx, obj, JS_INITIAL_NSLOTS + count, JS_TRUE))
+ normalUnwind = JS_FALSE;
+ else
+ memcpy(obj->dslots, fp->slots + depth + 1, count * sizeof(jsval));
+ JS_UNLOCK_OBJ(cx, obj);
+ }
+
+ /* We must clear the private slot even with errors. */
+ JS_SetPrivate(cx, obj, NULL);
+ fp->scopeChain = OBJ_GET_PARENT(cx, obj);
+ return normalUnwind;
+}
+
+static JSBool
+block_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uintN index;
+ JSStackFrame *fp;
+
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_BlockClass, NULL));
+ JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ index = (uint16) JSVAL_TO_INT(id);
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+ if (fp) {
+ index += fp->script->nfixed + OBJ_BLOCK_DEPTH(cx, obj);
+ JS_ASSERT(index < fp->script->nslots);
+ *vp = fp->slots[index];
+ return JS_TRUE;
+ }
+
+ /* Reserve slots start with the first slot after the private. */
+ index += JSSLOT_BLOCK_DEPTH - JSSLOT_PRIVATE;
+ return JS_GetReservedSlot(cx, obj, index, vp);
+}
+
+static JSBool
+block_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uintN index;
+ JSStackFrame *fp;
+
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_BlockClass, NULL));
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ index = (uint16) JSVAL_TO_INT(id);
+ fp = (JSStackFrame *) JS_GetPrivate(cx, obj);
+ if (fp) {
+ index += fp->script->nfixed + OBJ_BLOCK_DEPTH(cx, obj);
+ JS_ASSERT(index < fp->script->nslots);
+ fp->slots[index] = *vp;
+ return JS_TRUE;
+ }
+
+ /* Reserve slots start with the first slot after the private. */
+ index += JSSLOT_BLOCK_DEPTH - JSSLOT_PRIVATE;
+ return JS_SetReservedSlot(cx, obj, index, *vp);
+}
+
+#if JS_HAS_XDR
+
+#define NO_PARENT_INDEX ((uint32)-1)
+
+uint32
+FindObjectIndex(JSObjectArray *array, JSObject *obj)
+{
+ size_t i;
+
+ if (array) {
+ i = array->length;
+ do {
+
+ if (array->vector[--i] == obj)
+ return i;
+ } while (i != 0);
+ }
+
+ return NO_PARENT_INDEX;
+}
+
+static JSBool
+block_xdrObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSContext *cx;
+ uint32 parentId;
+ JSObject *obj, *parent;
+ uint16 depth, count, i;
+ uint32 tmp;
+ JSTempValueRooter tvr;
+ JSScopeProperty *sprop;
+ jsid propid;
+ JSAtom *atom;
+ int16 shortid;
+ JSBool ok;
+
+ cx = xdr->cx;
+#ifdef __GNUC__
+ obj = NULL; /* quell GCC overwarning */
+#endif
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ obj = *objp;
+ parent = OBJ_GET_PARENT(cx, obj);
+ parentId = (xdr->script->objectsOffset == 0)
+ ? NO_PARENT_INDEX
+ : FindObjectIndex(JS_SCRIPT_OBJECTS(xdr->script), parent);
+ depth = (uint16)OBJ_BLOCK_DEPTH(cx, obj);
+ count = (uint16)OBJ_BLOCK_COUNT(cx, obj);
+ tmp = (uint32)(depth << 16) | count;
+ }
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ else count = 0;
+#endif
+
+ /* First, XDR the parent atomid. */
+ if (!JS_XDRUint32(xdr, &parentId))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ obj = js_NewBlockObject(cx);
+ if (!obj)
+ return JS_FALSE;
+ *objp = obj;
+
+ /*
+ * If there's a parent id, then get the parent out of our script's
+ * object array. We know that we XDR block object in outer-to-inner
+ * order, which means that getting the parent now will work.
+ */
+ if (parentId == NO_PARENT_INDEX)
+ parent = NULL;
+ else
+ JS_GET_SCRIPT_OBJECT(xdr->script, parentId, parent);
+ STOBJ_SET_PARENT(obj, parent);
+ }
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, OBJECT_TO_JSVAL(obj), &tvr);
+
+ if (!JS_XDRUint32(xdr, &tmp)) {
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return JS_FALSE;
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ depth = (uint16)(tmp >> 16);
+ count = (uint16)tmp;
+ STOBJ_SET_SLOT(obj, JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth));
+ }
+
+ /*
+ * XDR the block object's properties. We know that there are 'count'
+ * properties to XDR, stored as id/shortid pairs. We do not XDR any
+ * non-native properties, only those that the compiler created.
+ */
+ sprop = NULL;
+ ok = JS_TRUE;
+ for (i = 0; i < count; i++) {
+ if (xdr->mode == JSXDR_ENCODE) {
+ /* Find a property to XDR. */
+ do {
+ /* If sprop is NULL, this is the first property. */
+ sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProp;
+ } while (!(sprop->flags & SPROP_HAS_SHORTID));
+
+ JS_ASSERT(sprop->getter == js_BlockClass.getProperty);
+ propid = sprop->id;
+ JS_ASSERT(JSID_IS_ATOM(propid));
+ atom = JSID_TO_ATOM(propid);
+ shortid = sprop->shortid;
+ JS_ASSERT(shortid >= 0);
+ }
+
+ /* XDR the real id, then the shortid. */
+ if (!js_XDRStringAtom(xdr, &atom) ||
+ !JS_XDRUint16(xdr, (uint16 *)&shortid)) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ if (!js_DefineNativeProperty(cx, obj, ATOM_TO_JSID(atom),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT,
+ SPROP_HAS_SHORTID, shortid, NULL)) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ }
+
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+#else
+# define block_xdrObject NULL
+#endif
+
+static uint32
+block_reserveSlots(JSContext *cx, JSObject *obj)
+{
+ return OBJ_IS_CLONED_BLOCK(obj) ? OBJ_BLOCK_COUNT(cx, obj) : 0;
+}
+
+JSClass js_BlockClass = {
+ "Block",
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_IS_ANONYMOUS | JSCLASS_HAS_CACHED_PROTO(JSProto_Block),
+ JS_PropertyStub, JS_PropertyStub, block_getProperty, block_setProperty,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL, block_xdrObject, NULL, NULL, block_reserveSlots
+};
+
+JSObject*
+js_InitBlockClass(JSContext *cx, JSObject* obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_BlockClass, NULL, 0, NULL,
+ NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+JSObject *
+js_InitEval(JSContext *cx, JSObject *obj)
+{
+ /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
+ if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom,
+ obj_eval, 1, 0)) {
+ return NULL;
+ }
+
+ return obj;
+}
+
+JSObject *
+js_InitObjectClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
+ object_props, object_methods, NULL,
+ object_static_methods);
+}
+
+void
+js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp)
+{
+ map->nrefs = nrefs;
+ map->ops = ops;
+ map->freeslot = JSSLOT_FREE(clasp);
+}
+
+JSObjectMap *
+js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj)
+{
+ return (JSObjectMap *) js_NewScope(cx, nrefs, ops, clasp, obj);
+}
+
+void
+js_DestroyObjectMap(JSContext *cx, JSObjectMap *map)
+{
+ js_DestroyScope(cx, (JSScope *)map);
+}
+
+JSObjectMap *
+js_HoldObjectMap(JSContext *cx, JSObjectMap *map)
+{
+ JS_ASSERT(map->nrefs >= 0);
+ JS_ATOMIC_INCREMENT(&map->nrefs);
+ return map;
+}
+
+JSObjectMap *
+js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj)
+{
+ JS_ASSERT(map->nrefs > 0);
+ JS_ATOMIC_DECREMENT(&map->nrefs);
+ if (map->nrefs == 0) {
+ map->ops->destroyObjectMap(cx, map);
+ return NULL;
+ }
+ if (MAP_IS_NATIVE(map) && ((JSScope *)map)->object == obj)
+ ((JSScope *)map)->object = NULL;
+ return map;
+}
+
+static void
+FreeSlots(JSContext *cx, JSObject *obj)
+{
+ if (obj->dslots) {
+ JS_ASSERT((uint32)obj->dslots[-1] > JS_INITIAL_NSLOTS);
+ JS_free(cx, obj->dslots - 1);
+ obj->dslots = NULL;
+ }
+}
+
+#define SLOTS_TO_DYNAMIC_WORDS(nslots) \
+ (JS_ASSERT((nslots) > JS_INITIAL_NSLOTS), (nslots) + 1 - JS_INITIAL_NSLOTS)
+
+#define DYNAMIC_WORDS_TO_SLOTS(words) \
+ (JS_ASSERT((words) > 1), (words) - 1 + JS_INITIAL_NSLOTS)
+
+JSBool
+js_ReallocSlots(JSContext *cx, JSObject *obj, uint32 nslots,
+ JSBool exactAllocation)
+{
+ jsval *old, *slots;
+ uint32 oslots, nwords, owords, log, i;
+
+ /*
+ * Minimal number of dynamic slots to allocate.
+ */
+#define MIN_DYNAMIC_WORDS 4
+
+ /*
+ * The limit to switch to linear allocation strategy from the power of 2
+ * growth no to waste too much memory.
+ */
+#define LINEAR_GROWTH_STEP JS_BIT(16)
+
+ old = obj->dslots;
+ if (nslots <= JS_INITIAL_NSLOTS) {
+ if (old &&
+ (exactAllocation ||
+ SLOTS_TO_DYNAMIC_WORDS((uint32)old[-1]) != MIN_DYNAMIC_WORDS ||
+ nslots <= (JS_INITIAL_NSLOTS +
+ JSSLOT_FREE(STOBJ_GET_CLASS(obj))) / 2)) {
+ /*
+ * We do not want to free dynamic slots when allocation is a hint,
+ * we reached minimal allocation and almost all fixed slots are
+ * used. It avoids allocating dynamic slots again when properties
+ * are added to the object.
+ *
+ * If there were no private or reserved slots, the condition to
+ * free the slots would be
+ *
+ * nslots <= JS_INITIAL_NSLOTS / 2
+ *
+ * but to account for never removed slots before JSSLOT_FREE(class)
+ * we need to subtract it from the slot counts which gives
+ *
+ * nslots - JSSLOT_FREE <= (JS_INITIAL_NSLOTS - JSSLOT_FREE) / 2
+ *
+ * or
+ *
+ * nslots <= (JS_INITIAL_NSLOTS + JSSLOT_FREE) / 2
+ */
+ FreeSlots(cx, obj);
+ }
+ return JS_TRUE;
+ }
+
+ oslots = (old) ? (uint32)*--old : JS_INITIAL_NSLOTS;
+ nwords = SLOTS_TO_DYNAMIC_WORDS(nslots);
+
+ if (nslots > oslots) {
+ if (!exactAllocation) {
+ /*
+ * Round up nslots so the number of bytes in dslots array is power
+ * of 2 to ensure exponential grouth.
+ */
+ if (nwords <= MIN_DYNAMIC_WORDS) {
+ nwords = MIN_DYNAMIC_WORDS;
+ } else if (nwords < LINEAR_GROWTH_STEP) {
+ JS_CEILING_LOG2(log, nwords);
+ nwords = JS_BIT(log);
+ } else {
+ nwords = JS_ROUNDUP(nwords, LINEAR_GROWTH_STEP);
+ }
+ }
+ slots = (jsval *)JS_realloc(cx, old, nwords * sizeof(jsval));
+ if (!slots)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(nslots < oslots);
+ if (!exactAllocation) {
+ owords = DYNAMIC_WORDS_TO_SLOTS(oslots);
+ if (owords <= MIN_DYNAMIC_WORDS)
+ return JS_TRUE;
+ if (owords < LINEAR_GROWTH_STEP * 2) {
+ /*
+ * Shrink only if 1/4 of slots are left and we need to grow
+ * the array at least twice to reach the current capacity. It
+ * prevents frequent capacity growth/shrinking when slots are
+ * often removed and added.
+ */
+ if (nwords > owords / 4)
+ return JS_TRUE;
+ JS_CEILING_LOG2(log, nwords);
+ nwords = JS_BIT(log);
+ if (nwords < MIN_DYNAMIC_WORDS)
+ nwords = MIN_DYNAMIC_WORDS;
+ } else {
+ /*
+ * Shrink only if we free at least 2 linear allocation
+ * segments, to prevent growth/shrinking resonance.
+ */
+ if (nwords > owords - LINEAR_GROWTH_STEP * 2)
+ return JS_TRUE;
+ nwords = JS_ROUNDUP(nwords, LINEAR_GROWTH_STEP);
+ }
+ }
+
+ /* We avoid JS_realloc not to report a failed shrink attempt. */
+ slots = (jsval *)realloc(old, nwords * sizeof(jsval));
+ if (!slots)
+ slots = old;
+ }
+
+ nslots = DYNAMIC_WORDS_TO_SLOTS(nwords);
+ *slots++ = (jsval)nslots;
+ obj->dslots = slots;
+
+ /* If we're extending an allocation, initialize free slots. */
+ for (i = oslots; i < nslots; i++)
+ slots[i - JS_INITIAL_NSLOTS] = JSVAL_VOID;
+
+ return JS_TRUE;
+
+#undef LINEAR_GROWTH_STEP
+#undef MIN_DYNAMIC_WORDS
+}
+
+extern JSBool
+js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp)
+{
+ JSProtoKey key;
+ JSAtom *atom;
+
+ key = JSCLASS_CACHED_PROTO_KEY(clasp);
+ if (key != JSProto_Null) {
+ *idp = INT_TO_JSID(key);
+ } else if (clasp->flags & JSCLASS_IS_ANONYMOUS) {
+ *idp = INT_TO_JSID(JSProto_Object);
+ } else {
+ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+ if (!atom)
+ return JS_FALSE;
+ *idp = ATOM_TO_JSID(atom);
+ }
+ return JS_TRUE;
+}
+
+JSObject *
+js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
+ uintN objectSize)
+{
+ jsid id;
+
+ /* Bootstrap the ur-object, and make it the default prototype object. */
+ if (!proto) {
+ if (!js_GetClassId(cx, clasp, &id))
+ return NULL;
+ if (!js_GetClassPrototype(cx, parent, id, &proto))
+ return NULL;
+ if (!proto &&
+ !js_GetClassPrototype(cx, parent, INT_TO_JSID(JSProto_Object),
+ &proto)) {
+ return NULL;
+ }
+ }
+
+ return js_NewObjectWithGivenProto(cx, clasp, proto, parent, objectSize);
+}
+
+JSObject *
+js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN objectSize)
+{
+ JSObject *obj;
+ JSObjectOps *ops;
+ JSObjectMap *map;
+ JSClass *protoclasp;
+ uint32 nslots, i;
+ JSTempValueRooter tvr;
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_CREATE_START_ENABLED())
+ jsdtrace_object_create_start(cx->fp, clasp);
+#endif
+
+ /* Currently only functions can have non-standard allocation size. */
+ if (clasp == &js_FunctionClass) {
+ if (objectSize == 0)
+ objectSize = sizeof(JSFunction);
+ else
+ JS_ASSERT(objectSize == sizeof(JSObject));
+ } else {
+ JS_ASSERT(objectSize == 0);
+ objectSize = sizeof(JSObject);
+ }
+
+ /*
+ * Allocate an object from the GC heap and initialize all its fields before
+ * doing any operation that can potentially trigger GC.
+ */
+ obj = (JSObject *) js_NewGCThing(cx, GCX_OBJECT, objectSize);
+ if (!obj)
+ goto earlybad;
+
+ obj->map = NULL;
+ obj->dslots = NULL;
+
+ /*
+ * Set the class slot with the initial value of the system and delegate
+ * flags set to false.
+ */
+ JS_ASSERT(((jsuword) clasp & 3) == 0);
+ obj->classword = jsuword(clasp);
+ JS_ASSERT(!STOBJ_IS_DELEGATE(obj));
+ JS_ASSERT(!STOBJ_IS_SYSTEM(obj));
+
+ /* Set the proto and parent properties. */
+ STOBJ_SET_PROTO(obj, proto);
+ STOBJ_SET_PARENT(obj, parent);
+
+ /* Initialize the remaining fixed slots. */
+ for (i = JSSLOT_PRIVATE; i != JS_INITIAL_NSLOTS; ++i)
+ obj->fslots[i] = JSVAL_VOID;
+
+#ifdef DEBUG
+ memset((uint8 *) obj + sizeof(JSObject), JS_FREE_PATTERN,
+ objectSize - sizeof(JSObject));
+#endif
+
+ /*
+ * Root obj to prevent it from being collected out from under this call to
+ * js_NewObject. There's a possibilty of GC under the objectHook call-out
+ * further below.
+ */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);
+
+ /* Always call the class's getObjectOps hook if it has one. */
+ ops = clasp->getObjectOps
+ ? clasp->getObjectOps(cx, clasp)
+ : &js_ObjectOps;
+
+ /*
+ * Default parent to the parent of the prototype, which was set from
+ * the parent of the prototype's constructor.
+ */
+ if (proto && !parent)
+ STOBJ_SET_PARENT(obj, OBJ_GET_PARENT(cx, proto));
+
+ /*
+ * Share proto's map only if it has the same JSObjectOps, and only if
+ * proto's class has the same private and reserved slots as obj's map
+ * and class have. We assume that if prototype and object are of the
+ * same class, they always have the same number of computed reserved
+ * slots (returned via clasp->reserveSlots); otherwise, prototype and
+ * object classes must have the same (null or not) reserveSlots hook.
+ */
+ if (proto &&
+ (map = proto->map)->ops == ops &&
+ ((protoclasp = OBJ_GET_CLASS(cx, proto)) == clasp ||
+ (!((protoclasp->flags ^ clasp->flags) &
+ (JSCLASS_HAS_PRIVATE |
+ (JSCLASS_RESERVED_SLOTS_MASK << JSCLASS_RESERVED_SLOTS_SHIFT))) &&
+ protoclasp->reserveSlots == clasp->reserveSlots)))
+ {
+ /* Share the given prototype's map. */
+ obj->map = js_HoldObjectMap(cx, map);
+ } else {
+ map = ops->newObjectMap(cx, 1, ops, clasp, obj);
+ if (!map)
+ goto bad;
+ obj->map = map;
+
+ /* Let ops->newObjectMap set freeslot so as to reserve slots. */
+ nslots = map->freeslot;
+ JS_ASSERT(nslots >= JSSLOT_PRIVATE);
+ if (nslots > JS_INITIAL_NSLOTS &&
+ !js_ReallocSlots(cx, obj, nslots, JS_TRUE)) {
+ js_DropObjectMap(cx, map, obj);
+ obj->map = NULL;
+ goto bad;
+ }
+ }
+
+ if (cx->debugHooks->objectHook) {
+ JS_KEEP_ATOMS(cx->runtime);
+ cx->debugHooks->objectHook(cx, obj, JS_TRUE,
+ cx->debugHooks->objectHookData);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ cx->weakRoots.newborn[GCX_OBJECT] = obj;
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
+ jsdtrace_object_create(cx, clasp, obj);
+ if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
+ jsdtrace_object_create_done(cx->fp, clasp);
+#endif
+ return obj;
+
+bad:
+ obj = NULL;
+ goto out;
+
+earlybad:
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_CREATE_ENABLED())
+ jsdtrace_object_create(cx, clasp, NULL);
+ if (JAVASCRIPT_OBJECT_CREATE_DONE_ENABLED())
+ jsdtrace_object_create_done(cx->fp, clasp);
+#endif
+ return NULL;
+}
+
+JS_BEGIN_EXTERN_C
+
+static JSObject *
+js_InitNullClass(JSContext *cx, JSObject *obj)
+{
+ JS_ASSERT(0);
+ return NULL;
+}
+
+#define JS_PROTO(name,code,init) extern JSObject *init(JSContext *, JSObject *);
+#include "jsproto.tbl"
+#undef JS_PROTO
+
+static JSObjectOp lazy_prototype_init[JSProto_LIMIT] = {
+#define JS_PROTO(name,code,init) init,
+#include "jsproto.tbl"
+#undef JS_PROTO
+};
+
+JS_END_EXTERN_C
+
+JSBool
+js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp)
+{
+ JSBool ok;
+ JSObject *tmp, *cobj;
+ JSResolvingKey rkey;
+ JSResolvingEntry *rentry;
+ uint32 generation;
+ JSObjectOp init;
+ jsval v;
+
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = tmp;
+ if (!(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL)) {
+ *objp = NULL;
+ return JS_TRUE;
+ }
+
+ ok = JS_GetReservedSlot(cx, obj, key, &v);
+ if (!ok)
+ return JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ *objp = JSVAL_TO_OBJECT(v);
+ return JS_TRUE;
+ }
+
+ rkey.obj = obj;
+ rkey.id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
+ if (!js_StartResolving(cx, &rkey, JSRESFLAG_LOOKUP, &rentry))
+ return JS_FALSE;
+ if (!rentry) {
+ /* Already caching key in obj -- suppress recursion. */
+ *objp = NULL;
+ return JS_TRUE;
+ }
+ generation = cx->resolvingTable->generation;
+
+ cobj = NULL;
+ init = lazy_prototype_init[key];
+ if (init) {
+ if (!init(cx, obj)) {
+ ok = JS_FALSE;
+ } else {
+ ok = JS_GetReservedSlot(cx, obj, key, &v);
+ if (ok && !JSVAL_IS_PRIMITIVE(v))
+ cobj = JSVAL_TO_OBJECT(v);
+ }
+ }
+
+ js_StopResolving(cx, &rkey, JSRESFLAG_LOOKUP, rentry, generation);
+ *objp = cobj;
+ return ok;
+}
+
+JSBool
+js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj)
+{
+ JS_ASSERT(!OBJ_GET_PARENT(cx, obj));
+ if (!(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL))
+ return JS_TRUE;
+
+ return JS_SetReservedSlot(cx, obj, key, OBJECT_TO_JSVAL(cobj));
+}
+
+JSBool
+js_FindClassObject(JSContext *cx, JSObject *start, jsid id, jsval *vp)
+{
+ JSObject *obj, *cobj, *pobj;
+ JSProtoKey key;
+ JSProperty *prop;
+ jsval v;
+ JSScopeProperty *sprop;
+
+ if (start || (cx->fp && (start = cx->fp->scopeChain) != NULL)) {
+ /* Find the topmost object in the scope chain. */
+ do {
+ obj = start;
+ start = OBJ_GET_PARENT(cx, obj);
+ } while (start);
+ } else {
+ obj = cx->globalObject;
+ if (!obj) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ }
+
+ OBJ_TO_INNER_OBJECT(cx, obj);
+ if (!obj)
+ return JS_FALSE;
+
+ if (JSID_IS_INT(id)) {
+ key = (JSProtoKey) JSID_TO_INT(id);
+ JS_ASSERT(key != JSProto_Null);
+ if (!js_GetClassObject(cx, obj, key, &cobj))
+ return JS_FALSE;
+ if (cobj) {
+ *vp = OBJECT_TO_JSVAL(cobj);
+ return JS_TRUE;
+ }
+ id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
+ }
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ if (js_LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_CLASSNAME,
+ &pobj, &prop) < 0) {
+ return JS_FALSE;
+ }
+ v = JSVAL_VOID;
+ if (prop) {
+ if (OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))) {
+ v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+ if (JSVAL_IS_PRIMITIVE(v))
+ v = JSVAL_VOID;
+ }
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ *vp = v;
+ return JS_TRUE;
+}
+
+JSObject *
+js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv)
+{
+ jsid id;
+ jsval cval, rval;
+ JSTempValueRooter argtvr, tvr;
+ JSObject *obj, *ctor;
+
+ JS_PUSH_TEMP_ROOT(cx, argc, argv, &argtvr);
+
+ if (!js_GetClassId(cx, clasp, &id) ||
+ !js_FindClassObject(cx, parent, id, &cval)) {
+ JS_POP_TEMP_ROOT(cx, &argtvr);
+ return NULL;
+ }
+
+ if (JSVAL_IS_PRIMITIVE(cval)) {
+ js_ReportIsNotFunction(cx, &cval, JSV2F_CONSTRUCT | JSV2F_SEARCH_STACK);
+ JS_POP_TEMP_ROOT(cx, &argtvr);
+ return NULL;
+ }
+
+ /*
+ * Protect cval in case a crazy getter for .prototype uproots it. After
+ * this point, all control flow must exit through label out with obj set.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, cval, &tvr);
+ MUST_FLOW_THROUGH("out");
+
+ /*
+ * If proto or parent are NULL, set them to Constructor.prototype and/or
+ * Constructor.__parent__, just like JSOP_NEW does.
+ */
+ ctor = JSVAL_TO_OBJECT(cval);
+ if (!parent)
+ parent = OBJ_GET_PARENT(cx, ctor);
+ if (!proto) {
+ if (!OBJ_GET_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &rval)) {
+ obj = NULL;
+ goto out;
+ }
+ if (JSVAL_IS_OBJECT(rval))
+ proto = JSVAL_TO_OBJECT(rval);
+ }
+
+ obj = js_NewObject(cx, clasp, proto, parent, 0);
+ if (!obj)
+ goto out;
+
+ if (!js_InternalConstruct(cx, obj, cval, argc, argv, &rval))
+ goto bad;
+
+ if (JSVAL_IS_PRIMITIVE(rval))
+ goto out;
+ obj = JSVAL_TO_OBJECT(rval);
+
+ /*
+ * If the instance's class differs from what was requested, throw a type
+ * error. If the given class has both the JSCLASS_HAS_PRIVATE and the
+ * JSCLASS_CONSTRUCT_PROTOTYPE flags, and the instance does not have its
+ * private data set at this point, then the constructor was replaced and
+ * we should throw a type error.
+ */
+ if (OBJ_GET_CLASS(cx, obj) != clasp ||
+ (!(~clasp->flags & (JSCLASS_HAS_PRIVATE |
+ JSCLASS_CONSTRUCT_PROTOTYPE)) &&
+ !JS_GetPrivate(cx, obj))) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_WRONG_CONSTRUCTOR, clasp->name);
+ goto bad;
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ JS_POP_TEMP_ROOT(cx, &argtvr);
+ return obj;
+
+bad:
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ obj = NULL;
+ goto out;
+}
+
+void
+js_FinalizeObject(JSContext *cx, JSObject *obj)
+{
+ JSObjectMap *map;
+
+ /* Cope with stillborn objects that have no map. */
+ map = obj->map;
+ if (!map)
+ return;
+
+ if (cx->debugHooks->objectHook) {
+ cx->debugHooks->objectHook(cx, obj, JS_FALSE,
+ cx->debugHooks->objectHookData);
+ }
+
+ /* Finalize obj first, in case it needs map and slots. */
+ STOBJ_GET_CLASS(obj)->finalize(cx, obj);
+
+#ifdef INCLUDE_MOZILLA_DTRACE
+ if (JAVASCRIPT_OBJECT_FINALIZE_ENABLED())
+ jsdtrace_object_finalize(obj);
+#endif
+
+ /* Drop map and free slots. */
+ js_DropObjectMap(cx, map, obj);
+ FreeSlots(cx, obj);
+}
+
+/* XXXbe if one adds props, deletes earlier props, adds more, the last added
+ won't recycle the deleted props' slots. */
+JSBool
+js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp)
+{
+ JSObjectMap *map;
+ JSClass *clasp;
+
+ map = obj->map;
+ JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (map->freeslot == JSSLOT_FREE(clasp) && clasp->reserveSlots) {
+ /* Adjust map->freeslot to include computed reserved slots, if any. */
+ map->freeslot += clasp->reserveSlots(cx, obj);
+ }
+
+ if (map->freeslot >= STOBJ_NSLOTS(obj) &&
+ !js_ReallocSlots(cx, obj, map->freeslot + 1, JS_FALSE)) {
+ return JS_FALSE;
+ }
+
+ /* js_ReallocSlots or js_FreeSlot should set the free slots to void. */
+ JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, map->freeslot)));
+ *slotp = map->freeslot++;
+ return JS_TRUE;
+}
+
+void
+js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot)
+{
+ JSObjectMap *map;
+
+ map = obj->map;
+ JS_ASSERT(!MAP_IS_NATIVE(map) || ((JSScope *)map)->object == obj);
+ LOCKED_OBJ_SET_SLOT(obj, slot, JSVAL_VOID);
+ if (map->freeslot == slot + 1) {
+ map->freeslot = slot;
+
+ /* When shrinking, js_ReallocSlots always returns true. */
+ js_ReallocSlots(cx, obj, slot, JS_FALSE);
+ }
+}
+
+jsid
+js_CheckForStringIndex(jsid id, const jschar *cp, const jschar *end,
+ JSBool negative)
+{
+ jsuint index = JS7_UNDEC(*cp++);
+ jsuint oldIndex = 0;
+ jsuint c = 0;
+
+ if (index != 0) {
+ while (JS7_ISDEC(*cp)) {
+ oldIndex = index;
+ c = JS7_UNDEC(*cp);
+ index = 10 * index + c;
+ cp++;
+ }
+ }
+ if (cp == end &&
+ (oldIndex < (JSVAL_INT_MAX / 10) ||
+ (oldIndex == (JSVAL_INT_MAX / 10) &&
+ c <= (JSVAL_INT_MAX % 10)))) {
+ if (negative)
+ index = 0 - index;
+ id = INT_TO_JSID((jsint)index);
+ }
+ return id;
+}
+
+static JSBool
+PurgeProtoChain(JSContext *cx, JSObject *obj, jsid id)
+{
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ while (obj) {
+ if (!OBJ_IS_NATIVE(obj)) {
+ obj = OBJ_GET_PROTO(cx, obj);
+ continue;
+ }
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ if (sprop) {
+ PCMETER(JS_PROPERTY_CACHE(cx).pcpurges++);
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+ }
+ obj = LOCKED_OBJ_GET_PROTO(scope->object);
+ JS_UNLOCK_SCOPE(cx, scope);
+ }
+ return JS_FALSE;
+}
+
+static void
+PurgeScopeChain(JSContext *cx, JSObject *obj, jsid id)
+{
+ if (!OBJ_IS_DELEGATE(cx, obj))
+ return;
+
+ PurgeProtoChain(cx, OBJ_GET_PROTO(cx, obj), id);
+ while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL) {
+ if (PurgeProtoChain(cx, obj, id))
+ return;
+ }
+}
+
+JSScopeProperty *
+js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid)
+{
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ /*
+ * Purge the property cache of now-shadowed id in obj's scope chain. Do
+ * this optimistically (assuming no failure below) before locking obj, so
+ * we can lock the shadowed scope.
+ */
+ PurgeScopeChain(cx, obj, id);
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ sprop = NULL;
+ } else {
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter, slot, attrs,
+ flags, shortid);
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ return sprop;
+}
+
+JSScopeProperty *
+js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter)
+{
+ JSScope *scope;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ sprop = NULL;
+ } else {
+ sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop, attrs, mask,
+ getter, setter);
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ return sprop;
+}
+
+JSBool
+js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp)
+{
+ return js_DefineNativeProperty(cx, obj, id, value, getter, setter, attrs,
+ 0, 0, propp);
+}
+
+/*
+ * Backward compatibility requires allowing addProperty hooks to mutate the
+ * nominal initial value of a slot-full property, while GC safety wants that
+ * value to be stored before the call-out through the hook. Optimize to do
+ * both while saving cycles for classes that stub their addProperty hook.
+ */
+#define ADD_PROPERTY_HELPER(cx,clasp,obj,scope,sprop,vp,cleanup) \
+ JS_BEGIN_MACRO \
+ if ((clasp)->addProperty != JS_PropertyStub) { \
+ jsval nominal_ = *(vp); \
+ if (!(clasp)->addProperty(cx, obj, SPROP_USERID(sprop), vp)) { \
+ cleanup; \
+ } \
+ if (*(vp) != nominal_) { \
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) \
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *(vp)); \
+ } \
+ } \
+ JS_END_MACRO
+
+JSBool
+js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN shortid, JSProperty **propp)
+{
+ JSClass *clasp;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+
+#if JS_HAS_GETTER_SETTER
+ /*
+ * If defining a getter or setter, we must check for its counterpart and
+ * update the attributes and property ops. A getter or setter is really
+ * only half of a property.
+ */
+ sprop = NULL;
+ if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
+ JSObject *pobj;
+ JSProperty *prop;
+
+ /*
+ * If JS_THREADSAFE and id is found, js_LookupProperty returns with
+ * sprop non-null and pobj locked. If pobj == obj, the property is
+ * already in obj and obj has its own (mutable) scope. So if we are
+ * defining a getter whose setter was already defined, or vice versa,
+ * finish the job via js_ChangeScopePropertyAttributes, and refresh
+ * the property cache line for (obj, id) to map sprop.
+ */
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ sprop = (JSScopeProperty *) prop;
+ if (sprop &&
+ pobj == obj &&
+ (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
+ sprop = js_ChangeScopePropertyAttrs(cx, OBJ_SCOPE(obj), sprop,
+ attrs, sprop->attrs,
+ (attrs & JSPROP_GETTER)
+ ? getter
+ : sprop->getter,
+ (attrs & JSPROP_SETTER)
+ ? setter
+ : sprop->setter);
+
+ /* NB: obj == pobj, so we can share unlock code at the bottom. */
+ if (!sprop)
+ goto bad;
+ } else if (prop) {
+ /* NB: call OBJ_DROP_PROPERTY, as pobj might not be native. */
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ prop = NULL;
+ sprop = NULL;
+ }
+ }
+#endif /* JS_HAS_GETTER_SETTER */
+
+ /*
+ * Purge the property cache of now-shadowed id in obj's scope chain.
+ * Do this early, before locking obj to avoid nesting locks.
+ */
+ PurgeScopeChain(cx, obj, id);
+
+ /* Lock if object locking is required by this implementation. */
+ JS_LOCK_OBJ(cx, obj);
+
+ /* Use the object's class getter and setter by default. */
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (!getter)
+ getter = clasp->getProperty;
+ if (!setter)
+ setter = clasp->setProperty;
+
+ /* Get obj's own scope if it has one, or create a new one for obj. */
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope)
+ goto bad;
+
+ if (!sprop) {
+ /* Add a new property, or replace an existing one of the same id. */
+ if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES)
+ attrs |= JSPROP_SHARED;
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter,
+ SPROP_INVALID_SLOT, attrs, flags,
+ shortid);
+ if (!sprop)
+ goto bad;
+ }
+
+ /* Store value before calling addProperty, in case the latter GC's. */
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, sprop->slot, value);
+
+ /* XXXbe called with lock held */
+ ADD_PROPERTY_HELPER(cx, clasp, obj, scope, sprop, &value,
+ js_RemoveScopeProperty(cx, scope, id);
+ goto bad);
+
+ if (propp)
+ *propp = (JSProperty *) sprop;
+ else
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+
+bad:
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+}
+
+/*
+ * Given pc pointing after a property accessing bytecode, return true if the
+ * access is "object-detecting" in the sense used by web scripts, e.g., when
+ * checking whether document.all is defined.
+ */
+static JSBool
+Detecting(JSContext *cx, jsbytecode *pc)
+{
+ JSScript *script;
+ jsbytecode *endpc;
+ JSOp op;
+ JSAtom *atom;
+
+ if (!cx->fp)
+ return JS_FALSE;
+ script = cx->fp->script;
+ for (endpc = script->code + script->length;
+ pc < endpc;
+ pc += js_CodeSpec[op].length) {
+ /* General case: a branch or equality op follows the access. */
+ op = (JSOp) *pc;
+ if (js_CodeSpec[op].format & JOF_DETECTING)
+ return JS_TRUE;
+
+ switch (op) {
+ case JSOP_NULL:
+ /*
+ * Special case #1: handle (document.all == null). Don't sweat
+ * about JS1.2's revision of the equality operators here.
+ */
+ if (++pc < endpc)
+ return *pc == JSOP_EQ || *pc == JSOP_NE;
+ return JS_FALSE;
+
+ case JSOP_NAME:
+ /*
+ * Special case #2: handle (document.all == undefined). Don't
+ * worry about someone redefining undefined, which was added by
+ * Edition 3, so is read/write for backward compatibility.
+ */
+ GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
+ if (atom == cx->runtime->atomState.typeAtoms[JSTYPE_VOID] &&
+ (pc += js_CodeSpec[op].length) < endpc) {
+ op = (JSOp) *pc;
+ return op == JSOP_EQ || op == JSOP_NE ||
+ op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
+ }
+ return JS_FALSE;
+
+ default:
+ /*
+ * At this point, anything but an extended atom index prefix means
+ * we're not detecting.
+ */
+ if (!(js_CodeSpec[op].format & JOF_INDEXBASE))
+ return JS_FALSE;
+ break;
+ }
+ }
+ return JS_FALSE;
+}
+
+JS_FRIEND_API(JSBool)
+js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ return js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ objp, propp) >= 0;
+}
+
+#define SCOPE_DEPTH_ACCUM(bs,val) \
+ JS_SCOPE_DEPTH_METERING(JS_BASIC_STATS_ACCUM(bs, val))
+
+int
+js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+ JSObject **objp, JSProperty **propp)
+{
+ JSObject *start, *obj2, *proto;
+ int protoIndex;
+ JSScope *scope;
+ JSScopeProperty *sprop;
+ JSClass *clasp;
+ JSResolveOp resolve;
+ JSResolvingKey key;
+ JSResolvingEntry *entry;
+ uint32 generation;
+ JSNewResolveOp newresolve;
+ jsbytecode *pc;
+ const JSCodeSpec *cs;
+ uint32 format;
+ JSBool ok;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_LOOKUP_PROPERTY);
+
+ /* Search scopes starting with obj and following the prototype link. */
+ start = obj;
+ for (protoIndex = 0; ; protoIndex++) {
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ } else {
+ /* Shared prototype scope: try resolve before lookup. */
+ sprop = NULL;
+ }
+
+ /* Try obj's class resolve hook if id was not found in obj's scope. */
+ if (!sprop) {
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ resolve = clasp->resolve;
+ if (resolve != JS_ResolveStub) {
+ /* Avoid recursion on (obj, id) already being resolved on cx. */
+ key.obj = obj;
+ key.id = id;
+
+ /*
+ * Once we have successfully added an entry for (obj, key) to
+ * cx->resolvingTable, control must go through cleanup: before
+ * returning. But note that JS_DHASH_ADD may find an existing
+ * entry, in which case we bail to suppress runaway recursion.
+ */
+ if (!js_StartResolving(cx, &key, JSRESFLAG_LOOKUP, &entry)) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return -1;
+ }
+ if (!entry) {
+ /* Already resolving id in obj -- suppress recursion. */
+ JS_UNLOCK_OBJ(cx, obj);
+ goto out;
+ }
+ generation = cx->resolvingTable->generation;
+
+ /* Null *propp here so we can test it at cleanup: safely. */
+ *propp = NULL;
+
+ if (clasp->flags & JSCLASS_NEW_RESOLVE) {
+ newresolve = (JSNewResolveOp)resolve;
+ if (flags == JSRESOLVE_INFER && cx->fp && cx->fp->regs) {
+ flags = 0;
+ pc = cx->fp->regs->pc;
+ cs = &js_CodeSpec[*pc];
+ format = cs->format;
+ if (JOF_MODE(format) != JOF_NAME)
+ flags |= JSRESOLVE_QUALIFIED;
+ if ((format & (JOF_SET | JOF_FOR)) ||
+ (cx->fp->flags & JSFRAME_ASSIGNING)) {
+ flags |= JSRESOLVE_ASSIGNING;
+ } else {
+ pc += cs->length;
+ if (Detecting(cx, pc))
+ flags |= JSRESOLVE_DETECTING;
+ }
+ if (format & JOF_DECLARING)
+ flags |= JSRESOLVE_DECLARING;
+ }
+ obj2 = (clasp->flags & JSCLASS_NEW_RESOLVE_GETS_START)
+ ? start
+ : NULL;
+ JS_UNLOCK_OBJ(cx, obj);
+
+ /* Protect id and all atoms from a GC nested in resolve. */
+ JS_KEEP_ATOMS(cx->runtime);
+ ok = newresolve(cx, obj, ID_TO_VALUE(id), flags, &obj2);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ if (!ok)
+ goto cleanup;
+
+ JS_LOCK_OBJ(cx, obj);
+ if (obj2) {
+ /* Resolved: juggle locks and lookup id again. */
+ if (obj2 != obj) {
+ JS_UNLOCK_OBJ(cx, obj);
+ if (OBJ_IS_NATIVE(obj2))
+ JS_LOCK_OBJ(cx, obj2);
+ }
+ protoIndex = 0;
+ for (proto = start; proto && proto != obj2;
+ proto = OBJ_GET_PROTO(cx, proto)) {
+ protoIndex++;
+ }
+ scope = OBJ_SCOPE(obj2);
+ if (!MAP_IS_NATIVE(&scope->map)) {
+ /* Whoops, newresolve handed back a foreign obj2. */
+ JS_ASSERT(obj2 != obj);
+ ok = OBJ_LOOKUP_PROPERTY(cx, obj2, id, objp, propp);
+ if (!ok || *propp)
+ goto cleanup;
+ JS_LOCK_OBJ(cx, obj2);
+ } else {
+ /*
+ * Require that obj2 have its own scope now, as we
+ * do for old-style resolve. If it doesn't, then
+ * id was not truly resolved, and we'll find it in
+ * the proto chain, or miss it if obj2's proto is
+ * not on obj's proto chain. That last case is a
+ * "too bad!" case.
+ */
+ if (scope->object == obj2)
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ }
+ if (sprop) {
+ JS_ASSERT(obj2 == scope->object);
+ obj = obj2;
+ } else if (obj2 != obj) {
+ if (OBJ_IS_NATIVE(obj2))
+ JS_UNLOCK_OBJ(cx, obj2);
+ JS_LOCK_OBJ(cx, obj);
+ }
+ }
+ } else {
+ /*
+ * Old resolve always requires id re-lookup if obj owns
+ * its scope after resolve returns.
+ */
+ JS_UNLOCK_OBJ(cx, obj);
+ ok = resolve(cx, obj, ID_TO_VALUE(id));
+ if (!ok)
+ goto cleanup;
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(MAP_IS_NATIVE(&scope->map));
+ if (scope->object == obj)
+ sprop = SCOPE_GET_PROPERTY(scope, id);
+ }
+
+ cleanup:
+ js_StopResolving(cx, &key, JSRESFLAG_LOOKUP, entry, generation);
+ if (!ok)
+ return -1;
+ if (*propp)
+ return protoIndex;
+ }
+ }
+
+ if (sprop) {
+ SCOPE_DEPTH_ACCUM(&cx->runtime->protoLookupDepthStats, protoIndex);
+ JS_ASSERT(OBJ_SCOPE(obj) == scope);
+ *objp = scope->object; /* XXXbe hide in jsscope.[ch] */
+
+ *propp = (JSProperty *) sprop;
+ return protoIndex;
+ }
+
+ proto = LOCKED_OBJ_GET_PROTO(obj);
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!proto)
+ break;
+ if (!OBJ_IS_NATIVE(proto)) {
+ if (!OBJ_LOOKUP_PROPERTY(cx, proto, id, objp, propp))
+ return -1;
+ return protoIndex + 1;
+ }
+ obj = proto;
+ }
+
+out:
+ *objp = NULL;
+ *propp = NULL;
+ return protoIndex;
+}
+
+int
+js_FindPropertyHelper(JSContext *cx, jsid id, JSObject **objp,
+ JSObject **pobjp, JSProperty **propp,
+ JSPropCacheEntry **entryp)
+{
+ JSObject *obj, *pobj, *lastobj;
+ uint32 shape;
+ int scopeIndex, protoIndex;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ obj = cx->fp->scopeChain;
+ shape = OBJ_SHAPE(obj);
+ for (scopeIndex = 0; ; scopeIndex++) {
+ if (obj->map->ops->lookupProperty == js_LookupProperty) {
+ protoIndex =
+ js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ &pobj, &prop);
+ } else {
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return -1;
+ protoIndex = -1;
+ }
+
+ if (prop) {
+ if (entryp) {
+ if (protoIndex >= 0 && OBJ_IS_NATIVE(pobj)) {
+ sprop = (JSScopeProperty *) prop;
+ js_FillPropertyCache(cx, cx->fp->scopeChain, shape,
+ scopeIndex, protoIndex, pobj, sprop,
+ entryp);
+ } else {
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ *entryp = NULL;
+ }
+ }
+ SCOPE_DEPTH_ACCUM(&rt->scopeSearchDepthStats, scopeIndex);
+ *objp = obj;
+ *pobjp = pobj;
+ *propp = prop;
+ return scopeIndex;
+ }
+
+ lastobj = obj;
+ obj = OBJ_GET_PARENT(cx, obj);
+ if (!obj)
+ break;
+ }
+
+ *objp = lastobj;
+ *pobjp = NULL;
+ *propp = NULL;
+ return scopeIndex;
+}
+
+JS_FRIEND_API(JSBool)
+js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
+ JSProperty **propp)
+{
+ return js_FindPropertyHelper(cx, id, objp, pobjp, propp, NULL) >= 0;
+}
+
+JSObject *
+js_FindIdentifierBase(JSContext *cx, jsid id, JSPropCacheEntry *entry)
+{
+ JSObject *obj, *pobj;
+ JSProperty *prop;
+
+ /*
+ * Look for id's property along the "with" statement chain and the
+ * statically-linked scope chain.
+ */
+ if (js_FindPropertyHelper(cx, id, &obj, &pobj, &prop, &entry) < 0)
+ return NULL;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return obj;
+ }
+
+ /*
+ * Use the top-level scope from the scope chain, which won't end in the
+ * same scope as cx->globalObject for cross-context function calls.
+ */
+ JS_ASSERT(obj);
+
+ /*
+ * Property not found. Give a strict warning if binding an undeclared
+ * top-level variable.
+ */
+ if (JS_HAS_STRICT_OPTION(cx)) {
+ JSString *str = JSVAL_TO_STRING(ID_TO_VALUE(id));
+ const char *bytes = js_GetStringBytes(cx, str);
+
+ if (!bytes ||
+ !JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ js_GetErrorMessage, NULL,
+ JSMSG_UNDECLARED_VAR, bytes)) {
+ return NULL;
+ }
+ }
+
+ return obj;
+}
+
+JSBool
+js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
+ JSScopeProperty *sprop, jsval *vp)
+{
+ JSScope *scope;
+ uint32 slot;
+ int32 sample;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(OBJ_IS_NATIVE(pobj));
+ JS_ASSERT(JS_IS_OBJ_LOCKED(cx, pobj));
+ scope = OBJ_SCOPE(pobj);
+ JS_ASSERT(scope->object == pobj);
+
+ slot = sprop->slot;
+ *vp = (slot != SPROP_INVALID_SLOT)
+ ? LOCKED_OBJ_GET_SLOT(pobj, slot)
+ : JSVAL_VOID;
+ if (SPROP_HAS_STUB_GETTER(sprop))
+ return JS_TRUE;
+
+ sample = cx->runtime->propertyRemovals;
+ JS_UNLOCK_SCOPE(cx, scope);
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
+ ok = SPROP_GET(cx, sprop, obj, pobj, vp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+
+ JS_LOCK_SCOPE(cx, scope);
+ JS_ASSERT(scope->object == pobj);
+ if (SLOT_IN_SCOPE(slot, scope) &&
+ (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
+ SCOPE_GET_PROPERTY(scope, sprop->id) == sprop)) {
+ LOCKED_OBJ_SET_SLOT(pobj, slot, *vp);
+ }
+
+ return JS_TRUE;
+}
+
+JSBool
+js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, jsval *vp)
+{
+ JSScope *scope;
+ uint32 slot;
+ int32 sample;
+ JSTempValueRooter tvr;
+ bool ok;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(scope->object == obj);
+
+ slot = sprop->slot;
+ if (slot != SPROP_INVALID_SLOT) {
+ OBJ_CHECK_SLOT(obj, slot);
+
+ /* If sprop has a stub setter, keep scope locked and just store *vp. */
+ if (SPROP_HAS_STUB_SETTER(sprop))
+ goto set_slot;
+ } else {
+ /*
+ * Allow API consumers to create shared properties with stub setters.
+ * Such properties lack value storage, so setting them is like writing
+ * to /dev/null.
+ */
+ if (SPROP_HAS_STUB_SETTER(sprop))
+ return JS_TRUE;
+ }
+
+ sample = cx->runtime->propertyRemovals;
+ JS_UNLOCK_SCOPE(cx, scope);
+ JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr);
+ ok = SPROP_SET(cx, sprop, obj, obj, vp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+
+ JS_LOCK_SCOPE(cx, scope);
+ JS_ASSERT(scope->object == obj);
+ if (SLOT_IN_SCOPE(slot, scope) &&
+ (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
+ SCOPE_GET_PROPERTY(scope, sprop->id) == sprop)) {
+ set_slot:
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, *vp);
+ }
+
+ return JS_TRUE;
+}
+
+JSBool
+js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp)
+{
+ uint32 shape;
+ int protoIndex;
+ JSObject *obj2;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_GET_PROPERTY);
+
+ shape = OBJ_SHAPE(obj);
+ protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ &obj2, &prop);
+ if (protoIndex < 0)
+ return JS_FALSE;
+ if (!prop) {
+ jsbytecode *pc;
+
+ *vp = JSVAL_VOID;
+
+ if (!OBJ_GET_CLASS(cx, obj)->getProperty(cx, obj, ID_TO_VALUE(id), vp))
+ return JS_FALSE;
+
+ if (entryp) {
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ *entryp = NULL;
+ }
+
+ /*
+ * Give a strict warning if foo.bar is evaluated by a script for an
+ * object foo with no property named 'bar'.
+ */
+ if (JSVAL_IS_VOID(*vp) && cx->fp && cx->fp->regs) {
+ JSOp op;
+ uintN flags;
+
+ pc = cx->fp->regs->pc;
+ op = (JSOp) *pc;
+ if (op == JSOP_GETXPROP) {
+ flags = JSREPORT_ERROR;
+ } else {
+ if (!JS_HAS_STRICT_OPTION(cx) ||
+ (op != JSOP_GETPROP && op != JSOP_GETELEM)) {
+ return JS_TRUE;
+ }
+
+ /*
+ * XXX do not warn about missing __iterator__ as the function
+ * may be called from JS_GetMethodById. See bug 355145.
+ */
+ if (id == ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom))
+ return JS_TRUE;
+
+ /* Kludge to allow (typeof foo == "undefined") tests. */
+ JS_ASSERT(cx->fp->script);
+ pc += js_CodeSpec[op].length;
+ if (Detecting(cx, pc))
+ return JS_TRUE;
+
+ flags = JSREPORT_WARNING | JSREPORT_STRICT;
+ }
+
+ /* Ok, bad undefined property reference: whine about it. */
+ if (!js_ReportValueErrorFlags(cx, flags, JSMSG_UNDEFINED_PROP,
+ JSDVG_IGNORE_STACK, ID_TO_VALUE(id),
+ NULL, NULL, NULL)) {
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+ }
+
+ if (!OBJ_IS_NATIVE(obj2)) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return OBJ_GET_PROPERTY(cx, obj2, id, vp);
+ }
+
+ sprop = (JSScopeProperty *) prop;
+ if (!js_NativeGet(cx, obj, obj2, sprop, vp))
+ return JS_FALSE;
+
+ if (entryp)
+ js_FillPropertyCache(cx, obj, shape, 0, protoIndex, obj2, sprop, entryp);
+ JS_UNLOCK_OBJ(cx, obj2);
+ return JS_TRUE;
+}
+
+JSBool
+js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return js_GetPropertyHelper(cx, obj, id, vp, NULL);
+}
+
+JSBool
+js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp)
+{
+ uint32 shape;
+ int protoIndex;
+ JSObject *pobj;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSScope *scope;
+ uintN attrs, flags;
+ intN shortid;
+ JSClass *clasp;
+ JSPropertyOp getter, setter;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_SET_PROPERTY);
+
+ shape = OBJ_SHAPE(obj);
+ protoIndex = js_LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags,
+ &pobj, &prop);
+ if (protoIndex < 0)
+ return JS_FALSE;
+
+ if (prop && !OBJ_IS_NATIVE(pobj)) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ prop = NULL;
+ }
+ sprop = (JSScopeProperty *) prop;
+
+ /*
+ * Now either sprop is null, meaning id was not found in obj or one of its
+ * prototypes; or sprop is non-null, meaning id was found in pobj's scope.
+ * If JS_THREADSAFE and sprop is non-null, then scope is locked, and sprop
+ * is held: we must OBJ_DROP_PROPERTY or JS_UNLOCK_SCOPE before we return
+ * (the two are equivalent for native objects, but we use JS_UNLOCK_SCOPE
+ * because it is cheaper).
+ */
+ attrs = JSPROP_ENUMERATE;
+ flags = 0;
+ shortid = 0;
+ clasp = OBJ_GET_CLASS(cx, obj);
+ getter = clasp->getProperty;
+ setter = clasp->setProperty;
+
+ if (sprop) {
+ /*
+ * Set scope for use below. It was locked by js_LookupProperty, and
+ * we know pobj owns it (i.e., scope->object == pobj). Therefore we
+ * optimize JS_UNLOCK_OBJ(cx, pobj) into JS_UNLOCK_SCOPE(cx, scope).
+ */
+ scope = OBJ_SCOPE(pobj);
+
+ attrs = sprop->attrs;
+ if ((attrs & JSPROP_READONLY) ||
+ (SCOPE_IS_SEALED(scope) && pobj == obj)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /*
+ * Here, we'll either return true or goto read_only_error, which
+ * reports a strict warning or throws an error. So we redefine
+ * the |flags| local variable to be JSREPORT_* flags to pass to
+ * JS_ReportErrorFlagsAndNumberUC at label read_only_error. We
+ * must likewise re-task flags further below for the other 'goto
+ * read_only_error;' case.
+ */
+ flags = JSREPORT_ERROR;
+ if (attrs & JSPROP_READONLY) {
+ if (!JS_HAS_STRICT_OPTION(cx)) {
+ /* Just return true per ECMA if not in strict mode. */
+ PCMETER(!entryp || JS_PROPERTY_CACHE(cx).rofills++);
+ return JS_TRUE;
+ }
+
+ /* Strict mode: report a read-only strict warning. */
+ flags = JSREPORT_STRICT | JSREPORT_WARNING;
+ }
+ goto read_only_error;
+ }
+
+ if (pobj != obj) {
+ /*
+ * We found id in a prototype object: prepare to share or shadow.
+ *
+ * NB: Thanks to the immutable, garbage-collected property tree
+ * maintained by jsscope.c in cx->runtime, we needn't worry about
+ * sprop going away behind our back after we've unlocked scope.
+ */
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ /*
+ * Don't clone a shared prototype property. Don't fill it in the
+ * property cache either, since the JSOP_SETPROP/JSOP_SETNAME code
+ * in js_Interpret does not handle shared or prototype properties.
+ * Shared prototype properties require more hit qualification than
+ * the fast-path code for those ops, which is targeted on direct,
+ * slot-based properties.
+ */
+ if (attrs & JSPROP_SHARED) {
+ if (entryp) {
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ *entryp = NULL;
+ }
+
+ if (SPROP_HAS_STUB_SETTER(sprop) &&
+ !(sprop->attrs & JSPROP_GETTER)) {
+ return JS_TRUE;
+ }
+
+ return !!SPROP_SET(cx, sprop, obj, pobj, vp);
+ }
+
+ /* Restore attrs to the ECMA default for new properties. */
+ attrs = JSPROP_ENUMERATE;
+
+ /*
+ * Preserve the shortid, getter, and setter when shadowing any
+ * property that has a shortid. An old API convention requires
+ * that the property's getter and setter functions receive the
+ * shortid, not id, when they are called on the shadow we are
+ * about to create in obj's scope.
+ */
+ if (sprop->flags & SPROP_HAS_SHORTID) {
+ flags = SPROP_HAS_SHORTID;
+ shortid = sprop->shortid;
+ getter = sprop->getter;
+ setter = sprop->setter;
+ }
+
+ /*
+ * Forget we found the proto-property now that we've copied any
+ * needed member values.
+ */
+ sprop = NULL;
+ }
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ } else {
+ scope = NULL;
+#endif
+ }
+
+ if (!sprop) {
+ if (SCOPE_IS_SEALED(OBJ_SCOPE(obj)) && OBJ_SCOPE(obj)->object == obj) {
+ flags = JSREPORT_ERROR;
+ goto read_only_error;
+ }
+
+ /*
+ * Purge the property cache of now-shadowed id in obj's scope chain.
+ * Do this early, before locking obj to avoid nesting locks.
+ */
+ PurgeScopeChain(cx, obj, id);
+
+ /* Find or make a property descriptor with the right heritage. */
+ JS_LOCK_OBJ(cx, obj);
+ scope = js_GetMutableScope(cx, obj);
+ if (!scope) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+ if (clasp->flags & JSCLASS_SHARE_ALL_PROPERTIES)
+ attrs |= JSPROP_SHARED;
+ sprop = js_AddScopeProperty(cx, scope, id, getter, setter,
+ SPROP_INVALID_SLOT, attrs, flags, shortid);
+ if (!sprop) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+
+ /*
+ * Initialize the new property value (passed to setter) to undefined.
+ * Note that we store before calling addProperty, to match the order
+ * in js_DefineNativeProperty.
+ */
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
+ LOCKED_OBJ_SET_SLOT(obj, sprop->slot, JSVAL_VOID);
+
+ /* XXXbe called with obj locked */
+ ADD_PROPERTY_HELPER(cx, clasp, obj, scope, sprop, vp,
+ js_RemoveScopeProperty(cx, scope, id);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE);
+ }
+
+ if (!js_NativeSet(cx, obj, sprop, vp))
+ return JS_FALSE;
+
+ if (entryp) {
+ if (!(attrs & JSPROP_SHARED))
+ js_FillPropertyCache(cx, obj, shape, 0, 0, obj, sprop, entryp);
+ else
+ PCMETER(JS_PROPERTY_CACHE(cx).nofills++);
+ }
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+
+ read_only_error:
+ return js_ReportValueErrorFlags(cx, flags, JSMSG_READ_ONLY,
+ JSDVG_IGNORE_STACK, ID_TO_VALUE(id), NULL,
+ NULL, NULL);
+}
+
+JSBool
+js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return js_SetPropertyHelper(cx, obj, id, vp, NULL);
+}
+
+JSBool
+js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool noprop, ok;
+ JSScopeProperty *sprop;
+
+ noprop = !prop;
+ if (noprop) {
+ if (!js_LookupProperty(cx, obj, id, &obj, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ *attrsp = 0;
+ return JS_TRUE;
+ }
+ if (!OBJ_IS_NATIVE(obj)) {
+ ok = OBJ_GET_ATTRIBUTES(cx, obj, id, prop, attrsp);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+ }
+ }
+ sprop = (JSScopeProperty *)prop;
+ *attrsp = sprop->attrs;
+ if (noprop)
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return JS_TRUE;
+}
+
+JSBool
+js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool noprop, ok;
+ JSScopeProperty *sprop;
+
+ noprop = !prop;
+ if (noprop) {
+ if (!js_LookupProperty(cx, obj, id, &obj, &prop))
+ return JS_FALSE;
+ if (!prop)
+ return JS_TRUE;
+ if (!OBJ_IS_NATIVE(obj)) {
+ ok = OBJ_SET_ATTRIBUTES(cx, obj, id, prop, attrsp);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+ }
+ }
+ sprop = (JSScopeProperty *)prop;
+ sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, *attrsp, 0,
+ sprop->getter, sprop->setter);
+ if (noprop)
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return (sprop != NULL);
+}
+
+JSBool
+js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ JSObject *proto;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ JSScope *scope;
+ JSBool ok;
+
+ *rval = JSVAL_TRUE;
+
+ /* Convert string indices to integers if appropriate. */
+ CHECK_FOR_STRING_INDEX(id);
+ JS_COUNT_OPERATION(cx, JSOW_DELETE_PROPERTY);
+
+ if (!js_LookupProperty(cx, obj, id, &proto, &prop))
+ return JS_FALSE;
+ if (!prop || proto != obj) {
+ /*
+ * If the property was found in a native prototype, check whether it's
+ * shared and permanent. Such a property stands for direct properties
+ * in all delegating objects, matching ECMA semantics without bloating
+ * each delegating object.
+ */
+ if (prop) {
+ if (OBJ_IS_NATIVE(proto)) {
+ sprop = (JSScopeProperty *)prop;
+ if (SPROP_IS_SHARED_PERMANENT(sprop))
+ *rval = JSVAL_FALSE;
+ }
+ OBJ_DROP_PROPERTY(cx, proto, prop);
+ if (*rval == JSVAL_FALSE)
+ return JS_TRUE;
+ }
+
+ /*
+ * If no property, or the property comes unshared or impermanent from
+ * a prototype, call the class's delProperty hook, passing rval as the
+ * result parameter.
+ */
+ return OBJ_GET_CLASS(cx, obj)->delProperty(cx, obj, ID_TO_VALUE(id),
+ rval);
+ }
+
+ sprop = (JSScopeProperty *)prop;
+ if (sprop->attrs & JSPROP_PERMANENT) {
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ *rval = JSVAL_FALSE;
+ return JS_TRUE;
+ }
+
+ /* XXXbe called with obj locked */
+ if (!LOCKED_OBJ_GET_CLASS(obj)->delProperty(cx, obj, SPROP_USERID(sprop),
+ rval)) {
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return JS_FALSE;
+ }
+
+ scope = OBJ_SCOPE(obj);
+ if (SPROP_HAS_VALID_SLOT(sprop, scope))
+ GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
+
+ ok = js_RemoveScopeProperty(cx, scope, id);
+ OBJ_DROP_PROPERTY(cx, obj, prop);
+ return ok;
+}
+
+JSBool
+js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+{
+ jsval v, save;
+ JSString *str;
+
+ v = save = OBJECT_TO_JSVAL(obj);
+ switch (hint) {
+ case JSTYPE_STRING:
+ /*
+ * Propagate the exception if js_TryMethod finds an appropriate
+ * method, and calling that method returned failure.
+ */
+ if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0, NULL,
+ &v)) {
+ return JS_FALSE;
+ }
+
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v))
+ return JS_FALSE;
+ }
+ break;
+
+ default:
+ if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, hint, &v))
+ return JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ JSType type = JS_TypeOfValue(cx, v);
+ if (type == hint ||
+ (type == JSTYPE_FUNCTION && hint == JSTYPE_OBJECT)) {
+ goto out;
+ }
+ if (!js_TryMethod(cx, obj, cx->runtime->atomState.toStringAtom, 0,
+ NULL, &v)) {
+ return JS_FALSE;
+ }
+ }
+ break;
+ }
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ /* Avoid recursive death when decompiling in js_ReportValueError. */
+ if (hint == JSTYPE_STRING) {
+ str = JS_InternString(cx, OBJ_GET_CLASS(cx, obj)->name);
+ if (!str)
+ return JS_FALSE;
+ } else {
+ str = NULL;
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO,
+ JSDVG_SEARCH_STACK, save, str,
+ (hint == JSTYPE_VOID)
+ ? "primitive type"
+ : JS_TYPE_STR(hint));
+ return JS_FALSE;
+ }
+out:
+ *vp = v;
+ return JS_TRUE;
+}
+
+/*
+ * Private type used to enumerate properties of a native JS object. It is
+ * allocated as necessary from JSENUMERATE_INIT and is freed when running the
+ * GC. The structure is not allocated when there are no enumerable properties
+ * in the object. Instead for the empty enumerator the code uses JSVAL_ZERO as
+ * the enumeration state.
+ *
+ * JSRuntime.nativeEnumCache caches the enumerators using scope's shape to
+ * avoid repeated scanning of scopes for enumerable properties. The cache
+ * entry is either JSNativeEnumerator* or, for the empty enumerator, the shape
+ * value itself. The latter is stored as (shape << 1) | 1 to ensure that it is
+ * always different from JSNativeEnumerator* values.
+ */
+struct JSNativeEnumerator {
+ /*
+ * The index into the ids array. It runs from the length down to 1 when
+ * the enumerator is running. It is 0 when the enumerator is finished and
+ * can be reused on a cache hit. Its type is jsword, not uint32, for
+ * compatibility with js_CompareAndSwap.
+ */
+ jsword cursor;
+
+ uint32 length; /* length of ids array */
+ uint32 shape; /* "shape" number -- see jsscope.h */
+ JSNativeEnumerator *next; /* list linking */
+ jsid ids[1]; /* enumeration id array */
+};
+
+/* The tagging of shape values requires one bit. */
+JS_STATIC_ASSERT((jsuword) SHAPE_OVERFLOW_BIT <=
+ ((jsuword) 1 << (JS_BITS_PER_WORD - 1)));
+
+static inline size_t
+NativeEnumeratorSize(uint32 length)
+{
+ JS_ASSERT(length != 0);
+ return offsetof(JSNativeEnumerator, ids) + (size_t) length * sizeof(jsid);
+}
+
+/*
+ * This function is used to enumerate the properties of native JSObjects
+ * and those host objects that do not define a JSNewEnumerateOp-style iterator
+ * function.
+ */
+JSBool
+js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSClass *clasp;
+ JSEnumerateOp enumerate;
+ JSNativeEnumerator *ne;
+ uint32 length, shape;
+ size_t allocated;
+ JSScope *scope;
+ jsuword *cachep, oldcache;
+ JSScopeProperty *sprop;
+ jsid *ids;
+ jsword newcursor;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ enumerate = clasp->enumerate;
+ if (clasp->flags & JSCLASS_NEW_ENUMERATE) {
+ JS_ASSERT(enumerate != JS_EnumerateStub);
+ return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);
+ }
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (!enumerate(cx, obj))
+ return JS_FALSE;
+
+ /*
+ * The set of all property ids is pre-computed when the iterator is
+ * initialized to avoid problems caused by properties being deleted
+ * during the iteration.
+ *
+ * Use a do-while(0) loop to avoid too many nested ifs. If ne is null
+ * after the loop, it indicates an empty enumerator. If allocated is
+ * not zero after the loop, we add the newly allocated ne to the cache
+ * and runtime->nativeEnumerators list.
+ */
+ ne = NULL;
+ length = 0;
+ allocated = (size_t) 0;
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ do {
+ /*
+ * If this object shares a scope with its prototype, don't
+ * enumerate its properties. Otherwise they will be enumerated
+ * a second time when the prototype object is enumerated.
+ */
+ if (scope->object != obj) {
+#ifdef __GNUC__
+ cachep = NULL; /* suppress bogus gcc warnings */
+#endif
+ break;
+ }
+
+ ENUM_CACHE_METER(nativeEnumProbes);
+ shape = scope->shape;
+ JS_ASSERT(shape < SHAPE_OVERFLOW_BIT);
+ cachep = &cx->runtime->
+ nativeEnumCache[NATIVE_ENUM_CACHE_HASH(shape)];
+ oldcache = *cachep;
+ if (oldcache & (jsuword) 1) {
+ if ((uint32) (oldcache >> 1) == shape) {
+ /* scope has a shape with no enumerable properties. */
+ break;
+ }
+ } else if (oldcache != (jsuword) 0) {
+ /*
+ * We can safely read ne->shape without taking the GC lock as
+ * ne is deleted only when running the GC and ne->shape is
+ * read-only after initialization.
+ */
+ ne = (JSNativeEnumerator *) *cachep;
+ JS_ASSERT(ne->length >= 1);
+ if (ne->shape == shape) {
+ /*
+ * Check that ne is not running with another enumerator
+ * and, if so, reuse and mark it as running from now.
+ */
+ length = ne->length;
+ if (js_CompareAndSwap(&ne->cursor, 0, length))
+ break;
+ length = 0;
+ }
+ ne = NULL;
+ }
+ ENUM_CACHE_METER(nativeEnumMisses);
+
+ /* Count all enumerable properties in object's scope. */
+ JS_ASSERT(length == 0);
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if ((sprop->attrs & JSPROP_ENUMERATE) &&
+ !(sprop->flags & SPROP_IS_ALIAS) &&
+ (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
+ SCOPE_HAS_PROPERTY(scope, sprop))) {
+ length++;
+ }
+ }
+ if (length == 0) {
+ /* cache the scope without enumerable properties. */
+ *cachep = ((jsuword) shape << 1) | (jsuword) 1;
+ break;
+ }
+
+ allocated = NativeEnumeratorSize(length);
+ ne = (JSNativeEnumerator *) JS_malloc(cx, allocated);
+ if (!ne) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+ ne->cursor = length;
+ ne->length = length;
+ ne->shape = shape;
+ ids = ne->ids;
+ for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
+ if ((sprop->attrs & JSPROP_ENUMERATE) &&
+ !(sprop->flags & SPROP_IS_ALIAS) &&
+ (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
+ SCOPE_HAS_PROPERTY(scope, sprop))) {
+ JS_ASSERT(ids < ne->ids + length);
+ *ids++ = sprop->id;
+ }
+ }
+ JS_ASSERT(ids == ne->ids + length);
+ } while (0);
+ JS_UNLOCK_SCOPE(cx, scope);
+
+ if (!ne) {
+ JS_ASSERT(length == 0);
+ JS_ASSERT(allocated == 0);
+ *statep = JSVAL_ZERO;
+ } else {
+ JS_ASSERT(length != 0);
+ JS_ASSERT(ne->cursor == (jsword) length);
+ if (allocated != 0) {
+ JS_LOCK_GC(cx->runtime);
+ if (!js_AddAsGCBytes(cx, allocated)) {
+ /* js_AddAsGCBytes releases the GC lock on failures. */
+ JS_free(cx, ne);
+ return JS_FALSE;
+ }
+ ne->next = cx->runtime->nativeEnumerators;
+ cx->runtime->nativeEnumerators = ne;
+ JS_ASSERT(((jsuword) ne & (jsuword) 1) == (jsuword) 0);
+ *cachep = (jsuword) ne;
+ JS_UNLOCK_GC(cx->runtime);
+ }
+ *statep = PRIVATE_TO_JSVAL(ne);
+ }
+ if (idp)
+ *idp = INT_TO_JSVAL(length);
+ break;
+
+ case JSENUMERATE_NEXT:
+ case JSENUMERATE_DESTROY:
+ if (*statep == JSVAL_ZERO) {
+ *statep = JSVAL_NULL;
+ break;
+ }
+ ne = (JSNativeEnumerator *) JSVAL_TO_PRIVATE(*statep);
+ JS_ASSERT(ne->length >= 1);
+ JS_ASSERT(ne->cursor >= 1);
+
+ /*
+ * We must not access ne->cursor when we set it to zero as it means
+ * that ne is free and another thread can grab it from the cache. So
+ * we set the state to JSVAL_ZERO in the NEXT case to avoid touching
+ * ne->length again in the DESTROY case.
+ */
+ if (enum_op == JSENUMERATE_NEXT) {
+ newcursor = ne->cursor - 1;
+ *idp = ne->ids[newcursor];
+ ne->cursor = newcursor;
+ if (newcursor == 0)
+ *statep = JSVAL_ZERO;
+ } else {
+ /* The enumerator has not iterated over all ids. */
+ ne->cursor = 0;
+ }
+ break;
+ }
+ return JS_TRUE;
+}
+
+void
+js_TraceNativeEnumerators(JSTracer *trc)
+{
+ JSRuntime *rt;
+ JSNativeEnumerator **nep, *ne;
+ jsid *cursor, *end;
+
+ /*
+ * Purge native enumerators cached by shape id, which we are about to
+ * re-number completely when tracing is done for the GC.
+ */
+ rt = trc->context->runtime;
+ if (IS_GC_MARKING_TRACER(trc)) {
+ memset(&rt->nativeEnumCache, 0, sizeof rt->nativeEnumCache);
+#ifdef JS_DUMP_ENUM_CACHE_STATS
+ printf("nativeEnumCache hit rate %g%%\n",
+ 100.0 * (rt->nativeEnumProbes - rt->nativeEnumMisses) /
+ rt->nativeEnumProbes);
+#endif
+ }
+
+ nep = &rt->nativeEnumerators;
+ while ((ne = *nep) != NULL) {
+ JS_ASSERT(ne->length != 0);
+ if (ne->cursor != 0) {
+ /* Trace ids of the running enumerator. */
+ cursor = ne->ids;
+ end = cursor + ne->length;
+ do {
+ TRACE_ID(trc, *cursor);
+ } while (++cursor != end);
+ } else if (IS_GC_MARKING_TRACER(trc)) {
+ js_RemoveAsGCBytes(rt, NativeEnumeratorSize(ne->length));
+ *nep = ne->next;
+ JS_free(trc->context, ne);
+ continue;
+ }
+ nep = &ne->next;
+ }
+}
+
+JSBool
+js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp)
+{
+ JSBool writing;
+ JSObject *pobj;
+ JSProperty *prop;
+ JSClass *clasp;
+ JSScopeProperty *sprop;
+ JSSecurityCallbacks *callbacks;
+ JSCheckAccessOp check;
+
+ writing = (mode & JSACC_WRITE) != 0;
+ switch (mode & JSACC_TYPEMASK) {
+ case JSACC_PROTO:
+ pobj = obj;
+ if (!writing)
+ *vp = OBJECT_TO_JSVAL(OBJ_GET_PROTO(cx, obj));
+ *attrsp = JSPROP_PERMANENT;
+ break;
+
+ case JSACC_PARENT:
+ JS_ASSERT(!writing);
+ pobj = obj;
+ *vp = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, obj));
+ *attrsp = JSPROP_READONLY | JSPROP_PERMANENT;
+ break;
+
+ default:
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop))
+ return JS_FALSE;
+ if (!prop) {
+ if (!writing)
+ *vp = JSVAL_VOID;
+ *attrsp = 0;
+ pobj = obj;
+ break;
+ }
+
+ if (!OBJ_IS_NATIVE(pobj)) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+
+ /* Avoid diverging for non-natives that reuse js_CheckAccess. */
+ if (pobj->map->ops->checkAccess == js_CheckAccess) {
+ if (!writing) {
+ *vp = JSVAL_VOID;
+ *attrsp = 0;
+ }
+ break;
+ }
+ return OBJ_CHECK_ACCESS(cx, pobj, id, mode, vp, attrsp);
+ }
+
+ sprop = (JSScopeProperty *)prop;
+ *attrsp = sprop->attrs;
+ if (!writing) {
+ *vp = (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)))
+ ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
+ : JSVAL_VOID;
+ }
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+
+ /*
+ * If obj's class has a stub (null) checkAccess hook, use the per-runtime
+ * checkObjectAccess callback, if configured.
+ *
+ * We don't want to require all classes to supply a checkAccess hook; we
+ * need that hook only for certain classes used when precompiling scripts
+ * and functions ("brutal sharing"). But for general safety of built-in
+ * magic properties such as __proto__ and __parent__, we route all access
+ * checks, even for classes that stub out checkAccess, through the global
+ * checkObjectAccess hook. This covers precompilation-based sharing and
+ * (possibly unintended) runtime sharing across trust boundaries.
+ */
+ clasp = OBJ_GET_CLASS(cx, pobj);
+ check = clasp->checkAccess;
+ if (!check) {
+ callbacks = JS_GetSecurityCallbacks(cx);
+ check = callbacks ? callbacks->checkObjectAccess : NULL;
+ }
+ return !check || check(cx, pobj, ID_TO_VALUE(id), mode, vp);
+}
+
+#ifdef JS_THREADSAFE
+void
+js_DropProperty(JSContext *cx, JSObject *obj, JSProperty *prop)
+{
+ JS_UNLOCK_OBJ(cx, obj);
+}
+#endif
+
+#ifdef NARCISSUS
+static JSBool
+GetCurrentExecutionContext(JSContext *cx, JSObject *obj, jsval *rval)
+{
+ JSObject *tmp;
+ jsval xcval;
+
+ while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
+ obj = tmp;
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .ExecutionContextAtom),
+ &xcval)) {
+ return JS_FALSE;
+ }
+ if (JSVAL_IS_PRIMITIVE(xcval)) {
+ JS_ReportError(cx, "invalid ExecutionContext in global object");
+ return JS_FALSE;
+ }
+ if (!OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(xcval),
+ ATOM_TO_JSID(cx->runtime->atomState.currentAtom),
+ rval)) {
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+#endif
+
+JSBool
+js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2]));
+ if (!clasp->call) {
+#ifdef NARCISSUS
+ JSObject *callee, *args;
+ jsval fval, nargv[3];
+ JSBool ok;
+
+ callee = JSVAL_TO_OBJECT(argv[-2]);
+ if (!OBJ_GET_PROPERTY(cx, callee,
+ ATOM_TO_JSID(cx->runtime->atomState.__call__Atom),
+ &fval)) {
+ return JS_FALSE;
+ }
+ if (VALUE_IS_FUNCTION(cx, fval)) {
+ if (!GetCurrentExecutionContext(cx, obj, &nargv[2]))
+ return JS_FALSE;
+ args = js_GetArgsObject(cx, cx->fp);
+ if (!args)
+ return JS_FALSE;
+ nargv[0] = OBJECT_TO_JSVAL(obj);
+ nargv[1] = OBJECT_TO_JSVAL(args);
+ return js_InternalCall(cx, callee, fval, 3, nargv, rval);
+ }
+ if (JSVAL_IS_OBJECT(fval) && JSVAL_TO_OBJECT(fval) != callee) {
+ argv[-2] = fval;
+ ok = js_Call(cx, obj, argc, argv, rval);
+ argv[-2] = OBJECT_TO_JSVAL(callee);
+ return ok;
+ }
+#endif
+ js_ReportIsNotFunction(cx, &argv[-2], cx->fp->flags & JSFRAME_ITERATOR);
+ return JS_FALSE;
+ }
+ return clasp->call(cx, obj, argc, argv, rval);
+}
+
+JSBool
+js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[-2]));
+ if (!clasp->construct) {
+#ifdef NARCISSUS
+ JSObject *callee, *args;
+ jsval cval, nargv[2];
+ JSBool ok;
+
+ callee = JSVAL_TO_OBJECT(argv[-2]);
+ if (!OBJ_GET_PROPERTY(cx, callee,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .__construct__Atom),
+ &cval)) {
+ return JS_FALSE;
+ }
+ if (VALUE_IS_FUNCTION(cx, cval)) {
+ if (!GetCurrentExecutionContext(cx, obj, &nargv[1]))
+ return JS_FALSE;
+ args = js_GetArgsObject(cx, cx->fp);
+ if (!args)
+ return JS_FALSE;
+ nargv[0] = OBJECT_TO_JSVAL(args);
+ return js_InternalCall(cx, callee, cval, 2, nargv, rval);
+ }
+ if (JSVAL_IS_OBJECT(cval) && JSVAL_TO_OBJECT(cval) != callee) {
+ argv[-2] = cval;
+ ok = js_Call(cx, obj, argc, argv, rval);
+ argv[-2] = OBJECT_TO_JSVAL(callee);
+ return ok;
+ }
+#endif
+ js_ReportIsNotFunction(cx, &argv[-2], JSV2F_CONSTRUCT);
+ return JS_FALSE;
+ }
+ return clasp->construct(cx, obj, argc, argv, rval);
+}
+
+JSBool
+js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->hasInstance)
+ return clasp->hasInstance(cx, obj, v, bp);
+#ifdef NARCISSUS
+ {
+ jsval fval, rval;
+
+ if (!OBJ_GET_PROPERTY(cx, obj,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .__hasInstance__Atom),
+ &fval)) {
+ return JS_FALSE;
+ }
+ if (VALUE_IS_FUNCTION(cx, fval)) {
+ if (!js_InternalCall(cx, obj, fval, 1, &v, &rval))
+ return JS_FALSE;
+ *bp = js_ValueToBoolean(rval);
+ return JS_TRUE;
+ }
+ }
+#endif
+ js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
+ JSDVG_SEARCH_STACK, OBJECT_TO_JSVAL(obj), NULL);
+ return JS_FALSE;
+}
+
+JSBool
+js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSObject *obj2;
+
+ *bp = JS_FALSE;
+ if (JSVAL_IS_PRIMITIVE(v))
+ return JS_TRUE;
+ obj2 = JSVAL_TO_OBJECT(v);
+ while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL) {
+ if (obj2 == obj) {
+ *bp = JS_TRUE;
+ break;
+ }
+ }
+ return JS_TRUE;
+}
+
+JSBool
+js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
+ JSObject **protop)
+{
+ jsval v;
+ JSObject *ctor;
+
+ if (!js_FindClassObject(cx, scope, id, &v))
+ return JS_FALSE;
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ ctor = JSVAL_TO_OBJECT(v);
+ if (!OBJ_GET_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &v)) {
+ return JS_FALSE;
+ }
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ /*
+ * Set the newborn root in case v is otherwise unreferenced.
+ * It's ok to overwrite newborn roots here, since the getter
+ * called just above could have. Unlike the common GC rooting
+ * model, our callers do not have to protect protop thanks to
+ * this newborn root, since they all immediately create a new
+ * instance that delegates to this object, or just query the
+ * prototype for its class.
+ */
+ cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(v);
+ }
+ }
+ *protop = JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : NULL;
+ return JS_TRUE;
+}
+
+/*
+ * For shared precompilation of function objects, we support cloning on entry
+ * to an execution context in which the function declaration or expression
+ * should be processed as if it were not precompiled, where the precompiled
+ * function's scope chain does not match the execution context's. The cloned
+ * function object carries its execution-context scope in its parent slot; it
+ * links to the precompiled function (the "clone-parent") via its proto slot.
+ *
+ * Note that this prototype-based delegation leaves an unchecked access path
+ * from the clone to the clone-parent's 'constructor' property. If the clone
+ * lives in a less privileged or shared scope than the clone-parent, this is
+ * a security hole, a sharing hazard, or both. Therefore we check all such
+ * accesses with the following getter/setter pair, which we use when defining
+ * 'constructor' in f.prototype for all function objects f.
+ */
+static JSBool
+CheckCtorGetAccess(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSAtom *atom;
+ uintN attrs;
+
+ atom = cx->runtime->atomState.constructorAtom;
+ JS_ASSERT(id == ATOM_TO_JSID(atom));
+ return OBJ_CHECK_ACCESS(cx, obj, ATOM_TO_JSID(atom), JSACC_READ,
+ vp, &attrs);
+}
+
+static JSBool
+CheckCtorSetAccess(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSAtom *atom;
+ uintN attrs;
+
+ atom = cx->runtime->atomState.constructorAtom;
+ JS_ASSERT(id == ATOM_TO_JSID(atom));
+ return OBJ_CHECK_ACCESS(cx, obj, ATOM_TO_JSID(atom), JSACC_WRITE,
+ vp, &attrs);
+}
+
+JSBool
+js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
+ uintN attrs)
+{
+ /*
+ * Use the given attributes for the prototype property of the constructor,
+ * as user-defined constructors have a DontDelete prototype (which may be
+ * reset), while native or "system" constructors have DontEnum | ReadOnly |
+ * DontDelete.
+ */
+ if (!OBJ_DEFINE_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ OBJECT_TO_JSVAL(proto),
+ JS_PropertyStub, JS_PropertyStub,
+ attrs, NULL)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * ECMA says that Object.prototype.constructor, or f.prototype.constructor
+ * for a user-defined function f, is DontEnum.
+ */
+ return OBJ_DEFINE_PROPERTY(cx, proto,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .constructorAtom),
+ OBJECT_TO_JSVAL(ctor),
+ CheckCtorGetAccess, CheckCtorSetAccess,
+ 0, NULL);
+}
+
+JSBool
+js_PrimitiveToObject(JSContext *cx, jsval *vp)
+{
+ JSClass *clasp;
+ JSObject *obj;
+
+ /* Table to map primitive value's tag into the corresponding class. */
+ JS_STATIC_ASSERT(JSVAL_INT == 1);
+ JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
+ JS_STATIC_ASSERT(JSVAL_STRING == 4);
+ JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);
+ static JSClass *const PrimitiveClasses[] = {
+ &js_NumberClass, /* INT */
+ &js_NumberClass, /* DOUBLE */
+ &js_NumberClass, /* INT */
+ &js_StringClass, /* STRING */
+ &js_NumberClass, /* INT */
+ &js_BooleanClass, /* BOOLEAN */
+ &js_NumberClass /* INT */
+ };
+
+ JS_ASSERT(!JSVAL_IS_OBJECT(*vp));
+ JS_ASSERT(!JSVAL_IS_VOID(*vp));
+ clasp = PrimitiveClasses[JSVAL_TAG(*vp) - 1];
+ obj = js_NewObject(cx, clasp, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, *vp);
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+JSBool
+js_ValueToObject(JSContext *cx, jsval v, JSObject **objp)
+{
+ JSObject *obj;
+
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
+ obj = NULL;
+ } else if (JSVAL_IS_OBJECT(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_OBJECT, &v))
+ return JS_FALSE;
+ if (JSVAL_IS_OBJECT(v))
+ obj = JSVAL_TO_OBJECT(v);
+ } else {
+ if (!js_PrimitiveToObject(cx, &v))
+ return JS_FALSE;
+ obj = JSVAL_TO_OBJECT(v);
+ }
+ *objp = obj;
+ return JS_TRUE;
+}
+
+JSObject *
+js_ValueToNonNullObject(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+
+ if (!js_ValueToObject(cx, v, &obj))
+ return NULL;
+ if (!obj)
+ js_ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, v, NULL);
+ return obj;
+}
+
+JSBool
+js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval)
+{
+ jsval argv[1];
+
+ argv[0] = ATOM_KEY(cx->runtime->atomState.typeAtoms[type]);
+ return js_TryMethod(cx, obj, cx->runtime->atomState.valueOfAtom, 1, argv,
+ rval);
+}
+
+JSBool
+js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN argc, jsval *argv, jsval *rval)
+{
+ JSErrorReporter older;
+ jsid id;
+ jsval fval;
+ JSBool ok;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ /*
+ * Report failure only if an appropriate method was found, and calling it
+ * returned failure. We propagate failure in this case to make exceptions
+ * behave properly.
+ */
+ older = JS_SetErrorReporter(cx, NULL);
+ id = ATOM_TO_JSID(atom);
+ fval = JSVAL_VOID;
+#if JS_HAS_XML_SUPPORT
+ if (OBJECT_IS_XML(cx, obj)) {
+ JSXMLObjectOps *ops;
+
+ ops = (JSXMLObjectOps *) obj->map->ops;
+ obj = ops->getMethod(cx, obj, id, &fval);
+ ok = (obj != NULL);
+ } else
+#endif
+ {
+ ok = OBJ_GET_PROPERTY(cx, obj, id, &fval);
+ }
+ if (!ok)
+ JS_ClearPendingException(cx);
+ JS_SetErrorReporter(cx, older);
+
+ return JSVAL_IS_PRIMITIVE(fval) ||
+ js_InternalCall(cx, obj, fval, argc, argv, rval);
+}
+
+#if JS_HAS_XDR
+
+JSBool
+js_XDRObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSContext *cx;
+ JSAtom *atom;
+ JSClass *clasp;
+ uint32 classId, classDef;
+ JSProtoKey protoKey;
+ jsid classKey;
+ JSObject *proto;
+
+ cx = xdr->cx;
+ atom = NULL;
+ if (xdr->mode == JSXDR_ENCODE) {
+ clasp = OBJ_GET_CLASS(cx, *objp);
+ classId = JS_XDRFindClassIdByName(xdr, clasp->name);
+ classDef = !classId;
+ if (classDef) {
+ if (!JS_XDRRegisterClass(xdr, clasp, &classId))
+ return JS_FALSE;
+ protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
+ if (protoKey != JSProto_Null) {
+ classDef |= (protoKey << 1);
+ } else {
+ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
+ if (!atom)
+ return JS_FALSE;
+ }
+ }
+ } else {
+ clasp = NULL; /* quell GCC overwarning */
+ classDef = 0;
+ }
+
+ /*
+ * XDR a flag word, which could be 0 for a class use, in which case no
+ * name follows, only the id in xdr's class registry; 1 for a class def,
+ * in which case the flag word is followed by the class name transferred
+ * from or to atom; or a value greater than 1, an odd number that when
+ * divided by two yields the JSProtoKey for class. In the last case, as
+ * in the 0 classDef case, no name is transferred via atom.
+ */
+ if (!JS_XDRUint32(xdr, &classDef))
+ return JS_FALSE;
+ if (classDef == 1 && !js_XDRStringAtom(xdr, &atom))
+ return JS_FALSE;
+
+ if (!JS_XDRUint32(xdr, &classId))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ if (classDef) {
+ /* NB: we know that JSProto_Null is 0 here, for backward compat. */
+ protoKey = (JSProtoKey) (classDef >> 1);
+ classKey = (protoKey != JSProto_Null)
+ ? INT_TO_JSID(protoKey)
+ : ATOM_TO_JSID(atom);
+ if (!js_GetClassPrototype(cx, NULL, classKey, &proto))
+ return JS_FALSE;
+ clasp = OBJ_GET_CLASS(cx, proto);
+ if (!JS_XDRRegisterClass(xdr, clasp, &classId))
+ return JS_FALSE;
+ } else {
+ clasp = JS_XDRFindClassById(xdr, classId);
+ if (!clasp) {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%ld", (long)classId);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_FIND_CLASS, numBuf);
+ return JS_FALSE;
+ }
+ }
+ }
+
+ if (!clasp->xdrObject) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_XDR_CLASS, clasp->name);
+ return JS_FALSE;
+ }
+ return clasp->xdrObject(xdr, objp);
+}
+
+#endif /* JS_HAS_XDR */
+
+#ifdef JS_DUMP_SCOPE_METERS
+
+#include <stdio.h>
+
+JSBasicStats js_entry_count_bs = JS_INIT_STATIC_BASIC_STATS;
+
+static void
+MeterEntryCount(uintN count)
+{
+ JS_BASIC_STATS_ACCUM(&js_entry_count_bs, count);
+}
+
+void
+js_DumpScopeMeters(JSRuntime *rt)
+{
+ static FILE *logfp;
+ if (!logfp)
+ logfp = fopen("/tmp/scope.stats", "a");
+
+ {
+ double mean, sigma;
+
+ mean = JS_MeanAndStdDevBS(&js_entry_count_bs, &sigma);
+
+ fprintf(logfp, "scopes %u entries %g mean %g sigma %g max %u",
+ js_entry_count_bs.num, js_entry_count_bs.sum, mean, sigma,
+ js_entry_count_bs.max);
+ }
+
+ JS_DumpHistogram(&js_entry_count_bs, logfp);
+ JS_BASIC_STATS_INIT(&js_entry_count_bs);
+ fflush(logfp);
+}
+#endif
+
+#ifdef DEBUG
+void
+js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
+{
+ JSObject *obj;
+ uint32 slot;
+ JSScope *scope;
+ jsval nval;
+ JSScopeProperty *sprop;
+ JSClass *clasp;
+ uint32 key;
+ const char *slotname;
+
+ JS_ASSERT(trc->debugPrinter == js_PrintObjectSlotName);
+ obj = (JSObject *)trc->debugPrintArg;
+ slot = (uint32)trc->debugPrintIndex;
+
+ if (OBJ_IS_NATIVE(obj)) {
+ scope = OBJ_SCOPE(obj);
+ sprop = SCOPE_LAST_PROP(scope);
+ while (sprop && sprop->slot != slot)
+ sprop = sprop->parent;
+ } else {
+ sprop = NULL;
+ }
+
+ if (!sprop) {
+ switch (slot) {
+ case JSSLOT_PROTO:
+ JS_snprintf(buf, bufsize, "__proto__");
+ break;
+ case JSSLOT_PARENT:
+ JS_snprintf(buf, bufsize, "__parent__");
+ break;
+ default:
+ slotname = NULL;
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (clasp->flags & JSCLASS_IS_GLOBAL) {
+ key = slot - JSSLOT_START(clasp);
+#define JS_PROTO(name,code,init) \
+ if ((code) == key) { slotname = js_##name##_str; goto found; }
+#include "jsproto.tbl"
+#undef JS_PROTO
+ }
+ found:
+ if (slotname)
+ JS_snprintf(buf, bufsize, "CLASS_OBJECT(%s)", slotname);
+ else
+ JS_snprintf(buf, bufsize, "**UNKNOWN SLOT %ld**", (long)slot);
+ break;
+ }
+ } else {
+ nval = ID_TO_VALUE(sprop->id);
+ if (JSVAL_IS_INT(nval)) {
+ JS_snprintf(buf, bufsize, "%ld", (long)JSVAL_TO_INT(nval));
+ } else if (JSVAL_IS_STRING(nval)) {
+ js_PutEscapedString(buf, bufsize, JSVAL_TO_STRING(nval), 0);
+ } else {
+ JS_snprintf(buf, bufsize, "**FINALIZED ATOM KEY**");
+ }
+ }
+}
+#endif
+
+void
+js_TraceObject(JSTracer *trc, JSObject *obj)
+{
+ JSContext *cx;
+ JSScope *scope;
+ JSBool traceScope;
+ JSScopeProperty *sprop;
+ JSClass *clasp;
+ size_t nslots, i;
+ jsval v;
+
+ JS_ASSERT(OBJ_IS_NATIVE(obj));
+ cx = trc->context;
+ scope = OBJ_SCOPE(obj);
+
+ traceScope = (scope->object == obj);
+ if (!traceScope) {
+ JSObject *pobj = obj;
+
+ /*
+ * Because obj does not own scope, we should be able to assert that an
+ * object on obj's prototype chain does -- or scope's properties might
+ * go untraced. It indeed turns out that you can disconnect an object
+ * from the prototype object whose scope it shares, so we may have to
+ * mark scope even though scope->object != obj.
+ */
+ while ((pobj = LOCKED_OBJ_GET_PROTO(pobj)) != NULL) {
+ if (pobj == scope->object)
+ break;
+ }
+ JS_ASSERT_IF(pobj, OBJ_SCOPE(pobj) == scope);
+ traceScope = !pobj;
+ }
+
+ if (traceScope) {
+#ifdef JS_DUMP_SCOPE_METERS
+ MeterEntryCount(scope->entryCount);
+#endif
+
+ sprop = SCOPE_LAST_PROP(scope);
+ if (sprop) {
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, sprop));
+
+ /* Regenerate property cache shape ids if GC'ing. */
+ if (IS_GC_MARKING_TRACER(trc)) {
+ uint32 shape, oldshape;
+
+ shape = ++cx->runtime->shapeGen;
+ JS_ASSERT(shape != 0);
+
+ if (!(sprop->flags & SPROP_MARK)) {
+ oldshape = sprop->shape;
+ sprop->shape = shape;
+ sprop->flags |= SPROP_FLAG_SHAPE_REGEN;
+ if (scope->shape != oldshape) {
+ shape = ++cx->runtime->shapeGen;
+ JS_ASSERT(shape != 0);
+ }
+ }
+
+ scope->shape = shape;
+ }
+
+ /* Trace scope's property tree ancestor line. */
+ do {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ !SCOPE_HAS_PROPERTY(scope, sprop)) {
+ continue;
+ }
+ TRACE_SCOPE_PROPERTY(trc, sprop);
+ } while ((sprop = sprop->parent) != NULL);
+ }
+ }
+
+ if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList))
+ js_TraceWatchPoints(trc, obj);
+
+ /* No one runs while the GC is running, so we can use LOCKED_... here. */
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ if (clasp->mark) {
+ if (clasp->flags & JSCLASS_MARK_IS_TRACE)
+ ((JSTraceOp) clasp->mark)(trc, obj);
+ else if (IS_GC_MARKING_TRACER(trc))
+ (void) clasp->mark(cx, obj, trc);
+ }
+
+ /*
+ * An unmutated object that shares a prototype object's scope. We can't
+ * tell how many slots are in use in obj by looking at its scope, so we
+ * use STOBJ_NSLOTS(obj).
+ *
+ * NB: In case clasp->mark mutates something, leave this code here --
+ * don't move it up and unify it with the |if (!traceScope)| section
+ * above.
+ */
+ nslots = STOBJ_NSLOTS(obj);
+ if (scope->object == obj && scope->map.freeslot < nslots)
+ nslots = scope->map.freeslot;
+
+ for (i = 0; i != nslots; ++i) {
+ v = STOBJ_GET_SLOT(obj, i);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_DETAILS(trc, js_PrintObjectSlotName, obj, i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+}
+
+void
+js_Clear(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope;
+ uint32 i, n;
+
+ /*
+ * Clear our scope and the property cache of all obj's properties only if
+ * obj owns the scope (i.e., not if obj is unmutated and therefore sharing
+ * its prototype's scope). NB: we do not clear any reserved slots lying
+ * below JSSLOT_FREE(clasp).
+ */
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (scope->object == obj) {
+ /* Now that we're done using scope->lastProp/table, clear scope. */
+ js_ClearScope(cx, scope);
+
+ /* Clear slot values and reset freeslot so we're consistent. */
+ i = STOBJ_NSLOTS(obj);
+ n = JSSLOT_FREE(LOCKED_OBJ_GET_CLASS(obj));
+ while (--i >= n)
+ STOBJ_SET_SLOT(obj, i, JSVAL_VOID);
+ scope->map.freeslot = n;
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+}
+
+jsval
+js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot)
+{
+ jsval v;
+
+ JS_LOCK_OBJ(cx, obj);
+ v = (slot < STOBJ_NSLOTS(obj)) ? STOBJ_GET_SLOT(obj, slot) : JSVAL_VOID;
+ JS_UNLOCK_OBJ(cx, obj);
+ return v;
+}
+
+JSBool
+js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v)
+{
+ JSScope *scope;
+ uint32 nslots;
+ JSClass *clasp;
+
+ JS_LOCK_OBJ(cx, obj);
+ scope = OBJ_SCOPE(obj);
+ if (slot >= JS_INITIAL_NSLOTS && !obj->dslots) {
+ /*
+ * At this point, obj may or may not own scope. If some path calls
+ * js_GetMutableScope but does not add a slot-owning property, then
+ * scope->object == obj but obj->dslots will be null. If obj shares a
+ * prototype's scope, then we cannot update scope->map here. Instead
+ * we rely on STOBJ_NSLOTS(obj) to get the number of available slots
+ * in obj after we allocate dynamic slots.
+ *
+ * See js_TraceObject, before the slot tracing, where we make a special
+ * case for unmutated (scope->object != obj) objects.
+ */
+ clasp = LOCKED_OBJ_GET_CLASS(obj);
+ nslots = JSSLOT_FREE(clasp);
+ if (clasp->reserveSlots)
+ nslots += clasp->reserveSlots(cx, obj);
+ JS_ASSERT(slot < nslots);
+ if (!js_ReallocSlots(cx, obj, nslots, JS_TRUE)) {
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_FALSE;
+ }
+ }
+
+ /* Whether or not we grew nslots, we may need to advance freeslot. */
+ if (scope->object == obj && slot >= scope->map.freeslot)
+ scope->map.freeslot = slot + 1;
+
+ STOBJ_SET_SLOT(obj, slot, v);
+ JS_UNLOCK_SCOPE(cx, scope);
+ return JS_TRUE;
+}
+
+JSObject *
+js_GetWrappedObject(JSContext *cx, JSObject *obj)
+{
+ JSClass *clasp;
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->flags & JSCLASS_IS_EXTENDED) {
+ JSExtendedClass *xclasp;
+ JSObject *obj2;
+
+ xclasp = (JSExtendedClass *)clasp;
+ if (xclasp->wrappedObject && (obj2 = xclasp->wrappedObject(cx, obj)))
+ return obj2;
+ }
+ return obj;
+}
+
+#if DEBUG
+
+/*
+ * Routines to print out values during debugging. These are FRIEND_API to help
+ * the debugger find them and to support temporarily hacking js_Dump* calls
+ * into other code.
+ */
+
+void
+dumpChars(const jschar *s, size_t n)
+{
+ size_t i;
+
+ if (n == (size_t) -1) {
+ while (s[++n]) ;
+ }
+
+ fputc('"', stderr);
+ for (i = 0; i < n; i++) {
+ if (s[i] == '\n')
+ fprintf(stderr, "\\n");
+ else if (s[i] == '\t')
+ fprintf(stderr, "\\t");
+ else if (s[i] >= 32 && s[i] < 127)
+ fputc(s[i], stderr);
+ else if (s[i] <= 255)
+ fprintf(stderr, "\\x%02x", (unsigned int) s[i]);
+ else
+ fprintf(stderr, "\\u%04x", (unsigned int) s[i]);
+ }
+ fputc('"', stderr);
+}
+
+JS_FRIEND_API(void)
+js_DumpChars(const jschar *s, size_t n)
+{
+ fprintf(stderr, "jschar * (%p) = ", (void *) s);
+ dumpChars(s, n);
+ fputc('\n', stderr);
+}
+
+void
+dumpString(JSString *str)
+{
+ dumpChars(JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+}
+
+JS_FRIEND_API(void)
+js_DumpString(JSString *str)
+{
+ fprintf(stderr, "JSString* (%p) = jschar * (%p) = ",
+ (void *) str, (void *) JSSTRING_CHARS(str));
+ dumpString(str);
+ fputc('\n', stderr);
+}
+
+JS_FRIEND_API(void)
+js_DumpAtom(JSAtom *atom)
+{
+ fprintf(stderr, "JSAtom* (%p) = ", (void *) atom);
+ js_DumpValue(ATOM_KEY(atom));
+}
+
+void
+dumpValue(jsval val)
+{
+ if (JSVAL_IS_NULL(val)) {
+ fprintf(stderr, "null");
+ } else if (JSVAL_IS_VOID(val)) {
+ fprintf(stderr, "undefined");
+ } else if (JSVAL_IS_OBJECT(val)) {
+ JSObject *obj = JSVAL_TO_OBJECT(val);
+ JSClass *cls = STOBJ_GET_CLASS(obj);
+ fprintf(stderr, "<%s%s at %p>",
+ cls->name,
+ cls == &js_ObjectClass ? "" : " object",
+ obj);
+ } else if (JSVAL_IS_INT(val)) {
+ fprintf(stderr, "%d", JSVAL_TO_INT(val));
+ } else if (JSVAL_IS_STRING(val)) {
+ dumpString(JSVAL_TO_STRING(val));
+ } else if (JSVAL_IS_DOUBLE(val)) {
+ fprintf(stderr, "%g", *JSVAL_TO_DOUBLE(val));
+ } else if (val == JSVAL_TRUE) {
+ fprintf(stderr, "true");
+ } else if (val == JSVAL_FALSE) {
+ fprintf(stderr, "false");
+ } else if (val == JSVAL_HOLE) {
+ fprintf(stderr, "hole");
+ } else {
+ /* jsvals are pointer-sized, and %p is portable */
+ fprintf(stderr, "unrecognized jsval %p", (void *) val);
+ }
+}
+
+JS_FRIEND_API(void)
+js_DumpValue(jsval val)
+{
+ fprintf(stderr, "jsval %d (%p) = ", (int) val, (void *) val);
+ dumpValue(val);
+ fputc('\n', stderr);
+}
+
+JS_FRIEND_API(void)
+js_DumpId(jsid id)
+{
+ fprintf(stderr, "id %d (%p) = ", (int) id, (void *) id);
+ dumpValue(ID_TO_VALUE(id));
+ fputc('\n', stderr);
+}
+
+static void
+dumpScopeProp(JSScopeProperty *sprop)
+{
+ jsid id = sprop->id;
+ uint8 attrs = sprop->attrs;
+
+ fprintf(stderr, " ");
+ if (attrs & JSPROP_ENUMERATE) fprintf(stderr, "enumerate ");
+ if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly ");
+ if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent ");
+ if (attrs & JSPROP_GETTER) fprintf(stderr, "getter ");
+ if (attrs & JSPROP_SETTER) fprintf(stderr, "setter ");
+ if (attrs & JSPROP_SHARED) fprintf(stderr, "shared ");
+ if (sprop->flags & SPROP_IS_ALIAS) fprintf(stderr, "alias ");
+ if (JSID_IS_ATOM(id))
+ dumpString(JSVAL_TO_STRING(ID_TO_VALUE(id)));
+ else if (JSID_IS_INT(id))
+ fprintf(stderr, "%d", (int) JSID_TO_INT(id));
+ else
+ fprintf(stderr, "unknown jsid %p", (void *) id);
+ fprintf(stderr, ": slot %d", sprop->slot);
+ fprintf(stderr, "\n");
+}
+
+JS_FRIEND_API(void)
+js_DumpObject(JSObject *obj)
+{
+ uint32 i, slots;
+ JSClass *clasp;
+ jsuint reservedEnd;
+ JSBool sharesScope = JS_FALSE;
+
+ fprintf(stderr, "object %p\n", (void *) obj);
+ clasp = STOBJ_GET_CLASS(obj);
+ fprintf(stderr, "class %p %s\n", (void *)clasp, clasp->name);
+
+ /* OBJ_IS_DENSE_ARRAY ignores the cx argument. */
+ if (OBJ_IS_DENSE_ARRAY(BOGUS_CX, obj)) {
+ slots = JS_MIN((jsuint) obj->fslots[JSSLOT_ARRAY_LENGTH],
+ ARRAY_DENSE_LENGTH(obj));
+ fprintf(stderr, "elements\n");
+ for (i = 0; i < slots; i++) {
+ fprintf(stderr, " %3d: ", i);
+ dumpValue(obj->dslots[i]);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ return;
+ }
+
+ if (OBJ_IS_NATIVE(obj)) {
+ JSScope *scope = OBJ_SCOPE(obj);
+ JSObject *proto = STOBJ_GET_PROTO(obj);
+
+ if (SCOPE_IS_SEALED(scope))
+ fprintf(stderr, "sealed\n");
+
+ sharesScope = (scope->object != obj);
+ if (sharesScope) {
+ fprintf(stderr, "no own properties - see proto (%s at %p)\n",
+ STOBJ_GET_CLASS(proto)->name, proto);
+ } else {
+ fprintf(stderr, "properties:\n");
+ for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope); sprop;
+ sprop = sprop->parent) {
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope) ||
+ SCOPE_HAS_PROPERTY(scope, sprop)) {
+ dumpScopeProp(sprop);
+ }
+ }
+ }
+ } else {
+ if (!OBJ_IS_NATIVE(obj))
+ fprintf(stderr, "not native\n");
+ }
+
+ fprintf(stderr, "slots:\n");
+ reservedEnd = JSSLOT_PRIVATE;
+ if (clasp->flags & JSCLASS_HAS_PRIVATE)
+ reservedEnd++;
+ reservedEnd += JSCLASS_RESERVED_SLOTS(clasp);
+ slots = sharesScope ? reservedEnd : obj->map->freeslot;
+ for (i = 0; i < slots; i++) {
+ fprintf(stderr, " %3d ", i);
+ if (i == JSSLOT_PRIVATE && (clasp->flags & JSCLASS_HAS_PRIVATE)) {
+ fprintf(stderr, "(private) = %p\n",
+ JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, i)));
+ continue;
+ }
+ if (i == JSSLOT_PROTO)
+ fprintf(stderr, "(proto) ");
+ else if (i == JSSLOT_PARENT)
+ fprintf(stderr, "(parent) ");
+ else if (i < reservedEnd)
+ fprintf(stderr, "(reserved) ");
+ fprintf(stderr, "= ");
+ dumpValue(STOBJ_GET_SLOT(obj, i));
+ fputc('\n', stderr);
+ }
+ fputc('\n', stderr);
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsobj.h b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.h
new file mode 100644
index 0000000..59a354f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsobj.h
@@ -0,0 +1,735 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsobj_h___
+#define jsobj_h___
+/*
+ * JS object definitions.
+ *
+ * A JS object consists of a possibly-shared object descriptor containing
+ * ordered property names, called the map; and a dense vector of property
+ * values, called slots. The map/slot pointer pair is GC'ed, while the map
+ * is reference counted and the slot vector is malloc'ed.
+ */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+struct JSObjectMap {
+ jsrefcount nrefs; /* count of all referencing objects */
+ JSObjectOps *ops; /* high level object operation vtable */
+ uint32 freeslot; /* index of next free slot in object */
+};
+
+/* Shorthand macros for frequently-made calls. */
+#define OBJ_LOOKUP_PROPERTY(cx,obj,id,objp,propp) \
+ (obj)->map->ops->lookupProperty(cx,obj,id,objp,propp)
+#define OBJ_DEFINE_PROPERTY(cx,obj,id,value,getter,setter,attrs,propp) \
+ (obj)->map->ops->defineProperty(cx,obj,id,value,getter,setter,attrs,propp)
+#define OBJ_GET_PROPERTY(cx,obj,id,vp) \
+ (obj)->map->ops->getProperty(cx,obj,id,vp)
+#define OBJ_SET_PROPERTY(cx,obj,id,vp) \
+ (obj)->map->ops->setProperty(cx,obj,id,vp)
+#define OBJ_GET_ATTRIBUTES(cx,obj,id,prop,attrsp) \
+ (obj)->map->ops->getAttributes(cx,obj,id,prop,attrsp)
+#define OBJ_SET_ATTRIBUTES(cx,obj,id,prop,attrsp) \
+ (obj)->map->ops->setAttributes(cx,obj,id,prop,attrsp)
+#define OBJ_DELETE_PROPERTY(cx,obj,id,rval) \
+ (obj)->map->ops->deleteProperty(cx,obj,id,rval)
+#define OBJ_DEFAULT_VALUE(cx,obj,hint,vp) \
+ (obj)->map->ops->defaultValue(cx,obj,hint,vp)
+#define OBJ_ENUMERATE(cx,obj,enum_op,statep,idp) \
+ (obj)->map->ops->enumerate(cx,obj,enum_op,statep,idp)
+#define OBJ_CHECK_ACCESS(cx,obj,id,mode,vp,attrsp) \
+ (obj)->map->ops->checkAccess(cx,obj,id,mode,vp,attrsp)
+
+/* These four are time-optimized to avoid stub calls. */
+#define OBJ_THIS_OBJECT(cx,obj) \
+ ((obj)->map->ops->thisObject \
+ ? (obj)->map->ops->thisObject(cx,obj) \
+ : (obj))
+#define OBJ_DROP_PROPERTY(cx,obj,prop) \
+ ((obj)->map->ops->dropProperty \
+ ? (obj)->map->ops->dropProperty(cx,obj,prop) \
+ : (void)0)
+#define OBJ_GET_REQUIRED_SLOT(cx,obj,slot) \
+ ((obj)->map->ops->getRequiredSlot \
+ ? (obj)->map->ops->getRequiredSlot(cx, obj, slot) \
+ : JSVAL_VOID)
+#define OBJ_SET_REQUIRED_SLOT(cx,obj,slot,v) \
+ ((obj)->map->ops->setRequiredSlot \
+ ? (obj)->map->ops->setRequiredSlot(cx, obj, slot, v) \
+ : JS_TRUE)
+
+#define OBJ_TO_INNER_OBJECT(cx,obj) \
+ JS_BEGIN_MACRO \
+ JSClass *clasp_ = OBJ_GET_CLASS(cx, obj); \
+ if (clasp_->flags & JSCLASS_IS_EXTENDED) { \
+ JSExtendedClass *xclasp_ = (JSExtendedClass*)clasp_; \
+ if (xclasp_->innerObject) \
+ obj = xclasp_->innerObject(cx, obj); \
+ } \
+ JS_END_MACRO
+
+#define OBJ_TO_OUTER_OBJECT(cx,obj) \
+ JS_BEGIN_MACRO \
+ JSClass *clasp_ = OBJ_GET_CLASS(cx, obj); \
+ if (clasp_->flags & JSCLASS_IS_EXTENDED) { \
+ JSExtendedClass *xclasp_ = (JSExtendedClass*)clasp_; \
+ if (xclasp_->outerObject) \
+ obj = xclasp_->outerObject(cx, obj); \
+ } \
+ JS_END_MACRO
+
+#define JS_INITIAL_NSLOTS 5
+
+/*
+ * When JSObject.dslots is not null, JSObject.dslots[-1] records the number of
+ * available slots.
+ */
+struct JSObject {
+ JSObjectMap *map;
+ jsuword classword;
+ jsval fslots[JS_INITIAL_NSLOTS];
+ jsval *dslots; /* dynamically allocated slots */
+};
+
+#define JSSLOT_PROTO 0
+#define JSSLOT_PARENT 1
+#define JSSLOT_PRIVATE 2
+#define JSSLOT_START(clasp) (((clasp)->flags & JSCLASS_HAS_PRIVATE) \
+ ? JSSLOT_PRIVATE + 1 \
+ : JSSLOT_PARENT + 1)
+
+#define JSSLOT_FREE(clasp) (JSSLOT_START(clasp) \
+ + JSCLASS_RESERVED_SLOTS(clasp))
+
+/*
+ * STOBJ prefix means Single Threaded Object. Use the following fast macros to
+ * directly manipulate slots in obj when only one thread can access obj and
+ * when obj->map->freeslot can be inconsistent with slots.
+ */
+
+#define STOBJ_NSLOTS(obj) \
+ ((obj)->dslots ? (uint32)(obj)->dslots[-1] : (uint32)JS_INITIAL_NSLOTS)
+
+#define STOBJ_GET_SLOT(obj,slot) \
+ ((slot) < JS_INITIAL_NSLOTS \
+ ? (obj)->fslots[(slot)] \
+ : (JS_ASSERT((slot) < (uint32)(obj)->dslots[-1]), \
+ (obj)->dslots[(slot) - JS_INITIAL_NSLOTS]))
+
+#define STOBJ_SET_SLOT(obj,slot,value) \
+ ((slot) < JS_INITIAL_NSLOTS \
+ ? (obj)->fslots[(slot)] = (value) \
+ : (JS_ASSERT((slot) < (uint32)(obj)->dslots[-1]), \
+ (obj)->dslots[(slot) - JS_INITIAL_NSLOTS] = (value)))
+
+#define STOBJ_GET_PROTO(obj) \
+ JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PROTO])
+#define STOBJ_SET_PROTO(obj,proto) \
+ (void)(STOBJ_NULLSAFE_SET_DELEGATE(proto), \
+ (obj)->fslots[JSSLOT_PROTO] = OBJECT_TO_JSVAL(proto))
+#define STOBJ_CLEAR_PROTO(obj) \
+ ((obj)->fslots[JSSLOT_PROTO] = JSVAL_NULL)
+
+#define STOBJ_GET_PARENT(obj) \
+ JSVAL_TO_OBJECT((obj)->fslots[JSSLOT_PARENT])
+#define STOBJ_SET_PARENT(obj,parent) \
+ (void)(STOBJ_NULLSAFE_SET_DELEGATE(parent), \
+ (obj)->fslots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(parent))
+#define STOBJ_CLEAR_PARENT(obj) \
+ ((obj)->fslots[JSSLOT_PARENT] = JSVAL_NULL)
+
+/*
+ * We use JSObject.classword to store both JSClass* and the delegate and system
+ * flags in the two least significant bits. We do *not* synchronize updates of
+ * obj->classword -- API clients must take care.
+ */
+#define STOBJ_GET_CLASS(obj) ((JSClass *)((obj)->classword & ~3))
+#define STOBJ_IS_DELEGATE(obj) (((obj)->classword & 1) != 0)
+#define STOBJ_SET_DELEGATE(obj) ((obj)->classword |= 1)
+#define STOBJ_NULLSAFE_SET_DELEGATE(obj) \
+ (!(obj) || STOBJ_SET_DELEGATE((JSObject*)obj))
+#define STOBJ_IS_SYSTEM(obj) (((obj)->classword & 2) != 0)
+#define STOBJ_SET_SYSTEM(obj) ((obj)->classword |= 2)
+
+#define STOBJ_GET_PRIVATE(obj) \
+ (JS_ASSERT(JSVAL_IS_INT(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE))), \
+ JSVAL_TO_PRIVATE(STOBJ_GET_SLOT(obj, JSSLOT_PRIVATE)))
+
+#define OBJ_CHECK_SLOT(obj,slot) \
+ JS_ASSERT(slot < (obj)->map->freeslot)
+
+#define LOCKED_OBJ_GET_SLOT(obj,slot) \
+ (OBJ_CHECK_SLOT(obj, slot), STOBJ_GET_SLOT(obj, slot))
+#define LOCKED_OBJ_SET_SLOT(obj,slot,value) \
+ (OBJ_CHECK_SLOT(obj, slot), STOBJ_SET_SLOT(obj, slot, value))
+
+/*
+ * NB: Don't call LOCKED_OBJ_SET_SLOT or STOBJ_SET_SLOT for a write to a slot
+ * that may contain a function reference already, or where the new value is a
+ * function ref, and the object's scope may be branded with a property cache
+ * structural type capability that distinguishes versions of the object with
+ * and without the function property. Instead use LOCKED_OBJ_WRITE_BARRIER or
+ * a fast inline equivalent (JSOP_SETNAME/JSOP_SETPROP cases in jsinterp.c).
+ */
+#define LOCKED_OBJ_WRITE_BARRIER(cx,obj,slot,newval) \
+ JS_BEGIN_MACRO \
+ JSScope *scope_ = OBJ_SCOPE(obj); \
+ JS_ASSERT(scope_->object == (obj)); \
+ GC_WRITE_BARRIER(cx, scope_, LOCKED_OBJ_GET_SLOT(obj, slot), newval); \
+ LOCKED_OBJ_SET_SLOT(obj, slot, newval); \
+ JS_END_MACRO
+
+#define LOCKED_OBJ_GET_PROTO(obj) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PROTO), STOBJ_GET_PROTO(obj))
+#define LOCKED_OBJ_SET_PROTO(obj,proto) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PROTO), STOBJ_SET_PROTO(obj, proto))
+
+#define LOCKED_OBJ_GET_PARENT(obj) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_GET_PARENT(obj))
+#define LOCKED_OBJ_SET_PARENT(obj,parent) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PARENT), STOBJ_SET_PARENT(obj, parent))
+
+#define LOCKED_OBJ_GET_CLASS(obj) \
+ STOBJ_GET_CLASS(obj)
+
+#define LOCKED_OBJ_GET_PRIVATE(obj) \
+ (OBJ_CHECK_SLOT(obj, JSSLOT_PRIVATE), STOBJ_GET_PRIVATE(obj))
+
+#ifdef JS_THREADSAFE
+
+/* Thread-safe functions and wrapper macros for accessing slots in obj. */
+#define OBJ_GET_SLOT(cx,obj,slot) \
+ (OBJ_CHECK_SLOT(obj, slot), \
+ (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx) \
+ ? LOCKED_OBJ_GET_SLOT(obj, slot) \
+ : js_GetSlotThreadSafe(cx, obj, slot))
+
+#define OBJ_SET_SLOT(cx,obj,slot,value) \
+ JS_BEGIN_MACRO \
+ OBJ_CHECK_SLOT(obj, slot); \
+ if (OBJ_IS_NATIVE(obj) && OBJ_SCOPE(obj)->title.ownercx == cx) \
+ LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, value); \
+ else \
+ js_SetSlotThreadSafe(cx, obj, slot, value); \
+ JS_END_MACRO
+
+/*
+ * If thread-safe, define an OBJ_GET_SLOT wrapper that bypasses, for a native
+ * object, the lock-free "fast path" test of (OBJ_SCOPE(obj)->ownercx == cx),
+ * to avoid needlessly switching from lock-free to lock-full scope when doing
+ * GC on a different context from the last one to own the scope. The caller
+ * in this case is probably a JSClass.mark function, e.g., fun_mark, or maybe
+ * a finalizer.
+ *
+ * The GC runs only when all threads except the one on which the GC is active
+ * are suspended at GC-safe points, so calling STOBJ_GET_SLOT from the GC's
+ * thread is safe when rt->gcRunning is set. See jsgc.c for details.
+ */
+#define THREAD_IS_RUNNING_GC(rt, thread) \
+ ((rt)->gcRunning && (rt)->gcThread == (thread))
+
+#define CX_THREAD_IS_RUNNING_GC(cx) \
+ THREAD_IS_RUNNING_GC((cx)->runtime, (cx)->thread)
+
+#else /* !JS_THREADSAFE */
+
+#define OBJ_GET_SLOT(cx,obj,slot) LOCKED_OBJ_GET_SLOT(obj,slot)
+#define OBJ_SET_SLOT(cx,obj,slot,value) LOCKED_OBJ_WRITE_BARRIER(cx,obj,slot, \
+ value)
+
+#endif /* !JS_THREADSAFE */
+
+/* Thread-safe delegate, proto, parent, and class access macros. */
+#define OBJ_IS_DELEGATE(cx,obj) STOBJ_IS_DELEGATE(obj)
+#define OBJ_SET_DELEGATE(cx,obj) STOBJ_SET_DELEGATE(obj)
+
+#define OBJ_GET_PROTO(cx,obj) STOBJ_GET_PROTO(obj)
+#define OBJ_SET_PROTO(cx,obj,proto) STOBJ_SET_PROTO(obj, proto)
+#define OBJ_CLEAR_PROTO(cx,obj) STOBJ_CLEAR_PROTO(obj)
+
+#define OBJ_GET_PARENT(cx,obj) STOBJ_GET_PARENT(obj)
+#define OBJ_SET_PARENT(cx,obj,parent) STOBJ_SET_PARENT(obj, parent)
+#define OBJ_CLEAR_PARENT(cx,obj) STOBJ_CLEAR_PARENT(obj)
+
+/*
+ * Class is invariant and comes from the fixed clasp member. Thus no locking
+ * is necessary to read it. Same for the private slot.
+ */
+#define OBJ_GET_CLASS(cx,obj) STOBJ_GET_CLASS(obj)
+#define OBJ_GET_PRIVATE(cx,obj) STOBJ_GET_PRIVATE(obj)
+
+/* Test whether a map or object is native. */
+#define MAP_IS_NATIVE(map) \
+ JS_LIKELY((map)->ops == &js_ObjectOps || \
+ (map)->ops->newObjectMap == js_ObjectOps.newObjectMap)
+
+#define OBJ_IS_NATIVE(obj) MAP_IS_NATIVE((obj)->map)
+
+extern JS_FRIEND_DATA(JSObjectOps) js_ObjectOps;
+extern JS_FRIEND_DATA(JSObjectOps) js_WithObjectOps;
+extern JSClass js_ObjectClass;
+extern JSClass js_WithClass;
+extern JSClass js_BlockClass;
+
+/*
+ * Block scope object macros. The slots reserved by js_BlockClass are:
+ *
+ * JSSLOT_PRIVATE JSStackFrame * active frame pointer or null
+ * JSSLOT_BLOCK_DEPTH int depth of block slots in frame
+ *
+ * After JSSLOT_BLOCK_DEPTH come one or more slots for the block locals.
+ *
+ * A With object is like a Block object, in that both have one reserved slot
+ * telling the stack depth of the relevant slots (the slot whose value is the
+ * object named in the with statement, the slots containing the block's local
+ * variables); and both have a private slot referring to the JSStackFrame in
+ * whose activation they were created (or null if the with or block object
+ * outlives the frame).
+ */
+#define JSSLOT_BLOCK_DEPTH (JSSLOT_PRIVATE + 1)
+
+#define OBJ_IS_CLONED_BLOCK(obj) \
+ (OBJ_SCOPE(obj)->object != (obj))
+#define OBJ_BLOCK_COUNT(cx,obj) \
+ (OBJ_SCOPE(obj)->entryCount)
+#define OBJ_BLOCK_DEPTH(cx,obj) \
+ JSVAL_TO_INT(STOBJ_GET_SLOT(obj, JSSLOT_BLOCK_DEPTH))
+#define OBJ_SET_BLOCK_DEPTH(cx,obj,depth) \
+ STOBJ_SET_SLOT(obj, JSSLOT_BLOCK_DEPTH, INT_TO_JSVAL(depth))
+
+/*
+ * To make sure this slot is well-defined, always call js_NewWithObject to
+ * create a With object, don't call js_NewObject directly. When creating a
+ * With object that does not correspond to a stack slot, pass -1 for depth.
+ *
+ * When popping the stack across this object's "with" statement, client code
+ * must call JS_SetPrivate(cx, withobj, NULL).
+ */
+extern JSObject *
+js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth);
+
+/*
+ * Create a new block scope object not linked to any proto or parent object.
+ * Blocks are created by the compiler to reify let blocks and comprehensions.
+ * Only when dynamic scope is captured do they need to be cloned and spliced
+ * into an active scope chain.
+ */
+extern JSObject *
+js_NewBlockObject(JSContext *cx);
+
+extern JSObject *
+js_CloneBlockObject(JSContext *cx, JSObject *proto, JSObject *parent,
+ JSStackFrame *fp);
+
+extern JSBool
+js_PutBlockObject(JSContext *cx, JSBool normalUnwind);
+
+struct JSSharpObjectMap {
+ jsrefcount depth;
+ jsatomid sharpgen;
+ JSHashTable *table;
+};
+
+#define SHARP_BIT ((jsatomid) 1)
+#define BUSY_BIT ((jsatomid) 2)
+#define SHARP_ID_SHIFT 2
+#define IS_SHARP(he) (JS_PTR_TO_UINT32((he)->value) & SHARP_BIT)
+#define MAKE_SHARP(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)|SHARP_BIT))
+#define IS_BUSY(he) (JS_PTR_TO_UINT32((he)->value) & BUSY_BIT)
+#define MAKE_BUSY(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)|BUSY_BIT))
+#define CLEAR_BUSY(he) ((he)->value = JS_UINT32_TO_PTR(JS_PTR_TO_UINT32((he)->value)&~BUSY_BIT))
+
+extern JSHashEntry *
+js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap,
+ jschar **sp);
+
+extern void
+js_LeaveSharpObject(JSContext *cx, JSIdArray **idap);
+
+/*
+ * Mark objects stored in map if GC happens between js_EnterSharpObject
+ * and js_LeaveSharpObject. GC calls this when map->depth > 0.
+ */
+extern void
+js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
+
+extern JSBool
+js_HasOwnPropertyHelper(JSContext *cx, JSLookupPropOp lookup, uintN argc,
+ jsval *vp);
+
+extern JSBool
+js_HasOwnProperty(JSContext *cx, JSLookupPropOp lookup, JSObject *obj, jsid id,
+ jsval *vp);
+
+extern JSBool
+js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSObject *
+js_InitBlockClass(JSContext *cx, JSObject* obj);
+
+extern JSObject *
+js_InitEval(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitObjectClass(JSContext *cx, JSObject *obj);
+
+/* Select Object.prototype method names shared between jsapi.c and jsobj.c. */
+extern const char js_watch_str[];
+extern const char js_unwatch_str[];
+extern const char js_hasOwnProperty_str[];
+extern const char js_isPrototypeOf_str[];
+extern const char js_propertyIsEnumerable_str[];
+extern const char js_defineGetter_str[];
+extern const char js_defineSetter_str[];
+extern const char js_lookupGetter_str[];
+extern const char js_lookupSetter_str[];
+
+extern void
+js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp);
+
+extern JSObjectMap *
+js_NewObjectMap(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj);
+
+extern void
+js_DestroyObjectMap(JSContext *cx, JSObjectMap *map);
+
+extern JSObjectMap *
+js_HoldObjectMap(JSContext *cx, JSObjectMap *map);
+
+extern JSObjectMap *
+js_DropObjectMap(JSContext *cx, JSObjectMap *map, JSObject *obj);
+
+extern JSBool
+js_GetClassId(JSContext *cx, JSClass *clasp, jsid *idp);
+
+extern JSObject *
+js_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent,
+ uintN objectSize);
+
+/*
+ * See jsapi.h, JS_NewObjectWithGivenProto.
+ *
+ * objectSize is either the explicit size for the allocated object or 0
+ * indicating to use the default size based on object's class.
+ */
+extern JSObject *
+js_NewObjectWithGivenProto(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN objectSize);
+
+/*
+ * Fast access to immutable standard objects (constructors and prototypes).
+ */
+extern JSBool
+js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
+ JSObject **objp);
+
+extern JSBool
+js_SetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject *cobj);
+
+extern JSBool
+js_FindClassObject(JSContext *cx, JSObject *start, jsid id, jsval *vp);
+
+extern JSObject *
+js_ConstructObject(JSContext *cx, JSClass *clasp, JSObject *proto,
+ JSObject *parent, uintN argc, jsval *argv);
+
+extern void
+js_FinalizeObject(JSContext *cx, JSObject *obj);
+
+extern JSBool
+js_AllocSlot(JSContext *cx, JSObject *obj, uint32 *slotp);
+
+extern void
+js_FreeSlot(JSContext *cx, JSObject *obj, uint32 slot);
+
+/* JSVAL_INT_MAX as a string */
+#define JSVAL_INT_MAX_STRING "1073741823"
+
+#define CHECK_FOR_STRING_INDEX(id) \
+ JS_BEGIN_MACRO \
+ if (JSID_IS_ATOM(id)) { \
+ JSAtom *atom_ = JSID_TO_ATOM(id); \
+ JSString *str_ = ATOM_TO_STRING(atom_); \
+ const jschar *s_ = JSFLATSTR_CHARS(str_); \
+ JSBool negative_ = (*s_ == '-'); \
+ if (negative_) s_++; \
+ if (JS7_ISDEC(*s_)) { \
+ size_t n_ = JSFLATSTR_LENGTH(str_) - negative_; \
+ if (n_ <= sizeof(JSVAL_INT_MAX_STRING) - 1) \
+ id = js_CheckForStringIndex(id, s_, s_ + n_, negative_); \
+ } \
+ } \
+ JS_END_MACRO
+
+extern jsid
+js_CheckForStringIndex(jsid id, const jschar *cp, const jschar *end,
+ JSBool negative);
+
+/*
+ * Find or create a property named by id in obj's scope, with the given getter
+ * and setter, slot, attributes, and other members.
+ */
+extern JSScopeProperty *
+js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid);
+
+/*
+ * Change sprop to have the given attrs, getter, and setter in scope, morphing
+ * it into a potentially new JSScopeProperty. Return a pointer to the changed
+ * or identical property.
+ */
+extern JSScopeProperty *
+js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter);
+
+/*
+ * On error, return false. On success, if propp is non-null, return true with
+ * obj locked and with a held property in *propp; if propp is null, return true
+ * but release obj's lock first. Therefore all callers who pass non-null propp
+ * result parameters must later call OBJ_DROP_PROPERTY(cx, obj, *propp) both to
+ * drop the held property, and to release the lock on obj.
+ */
+extern JSBool
+js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp);
+
+extern JSBool
+js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ uintN flags, intN shortid, JSProperty **propp);
+
+/*
+ * Unlike js_DefineProperty, propp must be non-null. On success, and if id was
+ * found, return true with *objp non-null and locked, and with a held property
+ * stored in *propp. If successful but id was not found, return true with both
+ * *objp and *propp null. Therefore all callers who receive a non-null *propp
+ * must later call OBJ_DROP_PROPERTY(cx, *objp, *propp).
+ */
+extern JS_FRIEND_API(JSBool)
+js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp);
+
+/*
+ * Specialized subroutine that allows caller to preset JSRESOLVE_* flags and
+ * returns the index along the prototype chain in which *propp was found, or
+ * the last index if not found, or -1 on error.
+ */
+extern int
+js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
+ JSObject **objp, JSProperty **propp);
+
+extern int
+js_FindPropertyHelper(JSContext *cx, jsid id, JSObject **objp,
+ JSObject **pobjp, JSProperty **propp,
+ JSPropCacheEntry **entryp);
+
+/*
+ * Return the index along the scope chain in which id was found, or the last
+ * index if not found, or -1 on error.
+ */
+extern JS_FRIEND_API(JSBool)
+js_FindProperty(JSContext *cx, jsid id, JSObject **objp, JSObject **pobjp,
+ JSProperty **propp);
+
+extern JSObject *
+js_FindIdentifierBase(JSContext *cx, jsid id, JSPropCacheEntry *entry);
+
+extern JSObject *
+js_FindVariableScope(JSContext *cx, JSFunction **funp);
+
+/*
+ * NB: js_NativeGet and js_NativeSet are called with the scope containing sprop
+ * (pobj's scope for Get, obj's for Set) locked, and on successful return, that
+ * scope is again locked. But on failure, both functions return false with the
+ * scope containing sprop unlocked.
+ */
+extern JSBool
+js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
+ JSScopeProperty *sprop, jsval *vp);
+
+extern JSBool
+js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, jsval *vp);
+
+extern JSBool
+js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp);
+
+extern JSBool
+js_GetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
+ JSPropCacheEntry **entryp);
+
+extern JSBool
+js_SetProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp);
+
+extern JSBool
+js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp);
+
+extern JSBool
+js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval);
+
+extern JSBool
+js_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp);
+
+extern JSBool
+js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp);
+
+extern void
+js_TraceNativeEnumerators(JSTracer *trc);
+
+extern JSBool
+js_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp);
+
+extern JSBool
+js_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JSBool
+js_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+extern JSBool
+js_SetProtoOrParent(JSContext *cx, JSObject *obj, uint32 slot, JSObject *pobj);
+
+extern JSBool
+js_IsDelegate(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+extern JSBool
+js_GetClassPrototype(JSContext *cx, JSObject *scope, jsid id,
+ JSObject **protop);
+
+extern JSBool
+js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto,
+ uintN attrs);
+
+/*
+ * Wrap boolean, number or string as Boolean, Number or String object.
+ * *vp must not be an object, null or undefined.
+ */
+extern JSBool
+js_PrimitiveToObject(JSContext *cx, jsval *vp);
+
+extern JSBool
+js_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
+
+extern JSObject *
+js_ValueToNonNullObject(JSContext *cx, jsval v);
+
+extern JSBool
+js_TryValueOf(JSContext *cx, JSObject *obj, JSType type, jsval *rval);
+
+extern JSBool
+js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
+ uintN argc, jsval *argv, jsval *rval);
+
+extern JSBool
+js_XDRObject(JSXDRState *xdr, JSObject **objp);
+
+extern void
+js_TraceObject(JSTracer *trc, JSObject *obj);
+
+extern void
+js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
+
+extern void
+js_Clear(JSContext *cx, JSObject *obj);
+
+extern jsval
+js_GetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot);
+
+extern JSBool
+js_SetRequiredSlot(JSContext *cx, JSObject *obj, uint32 slot, jsval v);
+
+/*
+ * Precondition: obj must be locked.
+ */
+extern JSBool
+js_ReallocSlots(JSContext *cx, JSObject *obj, uint32 nslots,
+ JSBool exactAllocation);
+
+extern JSObject *
+js_CheckScopeChainValidity(JSContext *cx, JSObject *scopeobj, const char *caller);
+
+extern JSBool
+js_CheckPrincipalsAccess(JSContext *cx, JSObject *scopeobj,
+ JSPrincipals *principals, JSAtom *caller);
+
+/* Infallible -- returns its argument if there is no wrapped object. */
+extern JSObject *
+js_GetWrappedObject(JSContext *cx, JSObject *obj);
+
+/* NB: Infallible. */
+extern const char *
+js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
+ JSPrincipals *principals, uintN *linenop);
+
+#ifdef DEBUG
+JS_FRIEND_API(void) js_DumpChars(const jschar *s, size_t n);
+JS_FRIEND_API(void) js_DumpString(JSString *str);
+JS_FRIEND_API(void) js_DumpAtom(JSAtom *atom);
+JS_FRIEND_API(void) js_DumpValue(jsval val);
+JS_FRIEND_API(void) js_DumpId(jsid id);
+JS_FRIEND_API(void) js_DumpObject(JSObject *obj);
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsobj_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/json.cpp b/tools/node_modules/expresso/deps/jscoverage/js/json.cpp
new file mode 100644
index 0000000..e6cd28a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/json.cpp
@@ -0,0 +1,954 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey JSON.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert Sayre <sayrer@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "jsapi.h"
+#include "jsarena.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsdtoa.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsprf.h"
+#include "jsscan.h"
+#include "jsstr.h"
+#include "jstypes.h"
+#include "jsutil.h"
+
+#include "json.h"
+
+JSClass js_JSONClass = {
+ js_JSON_str,
+ JSCLASS_HAS_CACHED_PROTO(JSProto_JSON),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+JSBool
+js_json_parse(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *s = NULL;
+ jsval *argv = vp + 2;
+
+ // Must throw an Error if there isn't a first arg
+ if (!JS_ConvertArguments(cx, argc, argv, "S", &s))
+ return JS_FALSE;
+
+
+ JSONParser *jp = js_BeginJSONParse(cx, vp);
+ JSBool ok = jp != NULL;
+
+ if (ok) {
+ ok = js_ConsumeJSONText(cx, jp, JS_GetStringChars(s), JS_GetStringLength(s));
+ ok &= js_FinishJSONParse(cx, jp);
+ }
+
+ if (!ok)
+ JS_ReportError(cx, "Error parsing JSON");
+
+ return ok;
+}
+
+class StringifyClosure : JSAutoTempValueRooter
+{
+public:
+ StringifyClosure(JSContext *cx, size_t len, jsval *vec)
+ : JSAutoTempValueRooter(cx, len, vec), cx(cx), s(vec)
+ {
+ }
+
+ JSContext *cx;
+ jsval *s;
+};
+
+static JSBool
+WriteCallback(const jschar *buf, uint32 len, void *data)
+{
+ StringifyClosure *sc = static_cast<StringifyClosure*>(data);
+ JSString *s1 = JSVAL_TO_STRING(sc->s[0]);
+ JSString *s2 = js_NewStringCopyN(sc->cx, buf, len);
+ if (!s2)
+ return JS_FALSE;
+
+ sc->s[1] = STRING_TO_JSVAL(s2);
+
+ s1 = js_ConcatStrings(sc->cx, s1, s2);
+ if (!s1)
+ return JS_FALSE;
+
+ sc->s[0] = STRING_TO_JSVAL(s1);
+ sc->s[1] = JSVAL_VOID;
+
+ return JS_TRUE;
+}
+
+JSBool
+js_json_stringify(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval *argv = vp + 2;
+
+ // Must throw an Error if there isn't a first arg
+ if (!JS_ConvertArguments(cx, argc, argv, "o", &obj))
+ return JS_FALSE;
+
+ // Only use objects and arrays as the root for now
+ *vp = OBJECT_TO_JSVAL(obj);
+
+ JSBool ok = js_TryJSON(cx, vp);
+ JSType type;
+ if (!ok ||
+ JSVAL_IS_PRIMITIVE(*vp) ||
+ ((type = JS_TypeOfValue(cx, *vp)) == JSTYPE_FUNCTION ||
+ type == JSTYPE_XML)) {
+ JS_ReportError(cx, "Invalid argument");
+ return JS_FALSE;
+ }
+
+ JSString *s = JS_NewStringCopyN(cx, "", 0);
+ if (!s)
+ ok = JS_FALSE;
+
+ if (ok) {
+ jsval vec[2] = {STRING_TO_JSVAL(s), JSVAL_VOID};
+ StringifyClosure sc(cx, 2, vec);
+ JSAutoTempValueRooter resultTvr(cx, 1, sc.s);
+ ok = js_Stringify(cx, vp, NULL, &WriteCallback, &sc, 0);
+ *vp = *sc.s;
+ }
+
+ return ok;
+}
+
+JSBool
+js_TryJSON(JSContext *cx, jsval *vp)
+{
+ // Checks whether the return value implements toJSON()
+ JSBool ok = JS_TRUE;
+
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ JSObject *obj = JSVAL_TO_OBJECT(*vp);
+ ok = js_TryMethod(cx, obj, cx->runtime->atomState.toJSONAtom, 0, NULL, vp);
+ }
+
+ return ok;
+}
+
+
+static const jschar quote = jschar('"');
+static const jschar backslash = jschar('\\');
+static const jschar unicodeEscape[] = {'\\', 'u', '0', '0'};
+
+static JSBool
+write_string(JSContext *cx, JSONWriteCallback callback, void *data, const jschar *buf, uint32 len)
+{
+ if (!callback(&quote, 1, data))
+ return JS_FALSE;
+
+ uint32 mark = 0;
+ uint32 i;
+ for (i = 0; i < len; ++i) {
+ if (buf[i] == quote || buf[i] == backslash) {
+ if (!callback(&buf[mark], i - mark, data) || !callback(&backslash, 1, data) ||
+ !callback(&buf[i], 1, data)) {
+ return JS_FALSE;
+ }
+ mark = i + 1;
+ } else if (buf[i] <= 31 || buf[i] == 127) {
+ if (!callback(&buf[mark], i - mark, data) || !callback(unicodeEscape, 4, data))
+ return JS_FALSE;
+ char ubuf[3];
+ size_t len = JS_snprintf(ubuf, sizeof(ubuf), "%.2x", buf[i]);
+ JS_ASSERT(len == 2);
+ jschar wbuf[3];
+ size_t wbufSize = JS_ARRAY_LENGTH(wbuf);
+ if (!js_InflateStringToBuffer(cx, ubuf, len, wbuf, &wbufSize) ||
+ !callback(wbuf, wbufSize, data)) {
+ return JS_FALSE;
+ }
+ mark = i + 1;
+ }
+ }
+
+ if (mark < len && !callback(&buf[mark], len - mark, data))
+ return JS_FALSE;
+
+ if (!callback(&quote, 1, data))
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+JSBool
+js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data, uint32 depth)
+{
+ if (depth > JSON_MAX_DEPTH)
+ return JS_FALSE; /* encoding error */
+
+ JSBool ok = JS_TRUE;
+ JSObject *obj = JSVAL_TO_OBJECT(*vp);
+ JSBool isArray = JS_IsArrayObject(cx, obj);
+ jschar output = jschar(isArray ? '[' : '{');
+ if (!callback(&output, 1, data))
+ return JS_FALSE;
+
+ JSObject *iterObj = NULL;
+ jsint i = 0;
+ jsuint length = 0;
+
+ if (isArray) {
+ if (!js_GetLengthProperty(cx, obj, &length))
+ return JS_FALSE;
+ } else {
+ if (!js_ValueToIterator(cx, JSITER_ENUMERATE, vp))
+ return JS_FALSE;
+ iterObj = JSVAL_TO_OBJECT(*vp);
+ }
+
+ jsval outputValue = JSVAL_VOID;
+ JSAutoTempValueRooter tvr(cx, 1, &outputValue);
+
+ jsval key;
+ JSBool memberWritten = JS_FALSE;
+ do {
+ outputValue = JSVAL_VOID;
+
+ if (isArray) {
+ if ((jsuint)i >= length)
+ break;
+ ok = OBJ_GET_PROPERTY(cx, obj, INT_TO_JSID(i), &outputValue);
+ i++;
+ } else {
+ ok = js_CallIteratorNext(cx, iterObj, &key);
+ if (!ok)
+ break;
+ if (key == JSVAL_HOLE)
+ break;
+
+ JSString *ks;
+ if (JSVAL_IS_STRING(key)) {
+ ks = JSVAL_TO_STRING(key);
+ } else {
+ ks = js_ValueToString(cx, key);
+ if (!ks) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+
+ ok = JS_GetUCProperty(cx, obj, JS_GetStringChars(ks),
+ JS_GetStringLength(ks), &outputValue);
+ }
+
+ if (!ok)
+ break;
+
+ // if this is an array, holes are transmitted as null
+ if (isArray && outputValue == JSVAL_VOID) {
+ outputValue = JSVAL_NULL;
+ } else if (JSVAL_IS_OBJECT(outputValue)) {
+ ok = js_TryJSON(cx, &outputValue);
+ if (!ok)
+ break;
+ }
+
+ // elide undefined values
+ if (outputValue == JSVAL_VOID)
+ continue;
+
+ // output a comma unless this is the first member to write
+ if (memberWritten) {
+ output = jschar(',');
+ ok = callback(&output, 1, data);
+ if (!ok)
+ break;
+ }
+ memberWritten = JS_TRUE;
+
+ JSType type = JS_TypeOfValue(cx, outputValue);
+
+ // Can't encode these types, so drop them
+ if (type == JSTYPE_FUNCTION || type == JSTYPE_XML)
+ break;
+
+ // Be careful below, this string is weakly rooted.
+ JSString *s;
+
+ // If this isn't an array, we need to output a key
+ if (!isArray) {
+ s = js_ValueToString(cx, key);
+ if (!s) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
+ if (!ok)
+ break;
+
+ output = jschar(':');
+ ok = callback(&output, 1, data);
+ if (!ok)
+ break;
+ }
+
+ if (!JSVAL_IS_PRIMITIVE(outputValue)) {
+ // recurse
+ ok = js_Stringify(cx, &outputValue, replacer, callback, data, depth + 1);
+ } else {
+ JSString *outputString;
+ s = js_ValueToString(cx, outputValue);
+ if (!s) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ if (type == JSTYPE_STRING) {
+ ok = write_string(cx, callback, data, JS_GetStringChars(s), JS_GetStringLength(s));
+ if (!ok)
+ break;
+
+ continue;
+ }
+
+ if (type == JSTYPE_NUMBER) {
+ if (JSVAL_IS_DOUBLE(outputValue)) {
+ jsdouble d = *JSVAL_TO_DOUBLE(outputValue);
+ if (!JSDOUBLE_IS_FINITE(d))
+ outputString = JS_NewStringCopyN(cx, "null", 4);
+ else
+ outputString = s;
+ } else {
+ outputString = s;
+ }
+ } else if (type == JSTYPE_BOOLEAN) {
+ outputString = s;
+ } else if (JSVAL_IS_NULL(outputValue)) {
+ outputString = JS_NewStringCopyN(cx, "null", 4);
+ } else {
+ ok = JS_FALSE; // encoding error
+ break;
+ }
+
+ if (!outputString) {
+ ok = JS_FALSE;
+ break;
+ }
+
+ ok = callback(JS_GetStringChars(outputString), JS_GetStringLength(outputString), data);
+ }
+ } while (ok);
+
+ if (iterObj) {
+ // Always close the iterator, but make sure not to stomp on OK
+ ok &= js_CloseIterator(cx, *vp);
+ // encoding error or propagate? FIXME: Bug 408838.
+ }
+
+ if (!ok) {
+ JS_ReportError(cx, "Error during JSON encoding");
+ return JS_FALSE;
+ }
+
+ output = jschar(isArray ? ']' : '}');
+ ok = callback(&output, 1, data);
+
+ return ok;
+}
+
+// helper to determine whether a character could be part of a number
+static JSBool IsNumChar(jschar c)
+{
+ return ((c <= '9' && c >= '0') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E');
+}
+
+JSONParser *
+js_BeginJSONParse(JSContext *cx, jsval *rootVal)
+{
+ if (!cx)
+ return NULL;
+
+ JSObject *arr = js_NewArrayObject(cx, 0, NULL);
+ if (!arr)
+ return NULL;
+
+ JSONParser *jp = (JSONParser*) JS_malloc(cx, sizeof(JSONParser));
+ if (!jp)
+ return NULL;
+ jp->buffer = NULL;
+
+ jp->objectStack = arr;
+ if (!js_AddRoot(cx, &jp->objectStack, "JSON parse stack"))
+ goto bad;
+
+ jp->hexChar = 0;
+ jp->numHex = 0;
+ jp->statep = jp->stateStack;
+ *jp->statep = JSON_PARSE_STATE_INIT;
+ jp->rootVal = rootVal;
+
+ jp->objectKey = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
+ if (!jp->objectKey)
+ goto bad;
+ js_InitStringBuffer(jp->objectKey);
+
+ jp->buffer = (JSStringBuffer*) JS_malloc(cx, sizeof(JSStringBuffer));
+ if (!jp->buffer)
+ goto bad;
+ js_InitStringBuffer(jp->buffer);
+
+ return jp;
+bad:
+ JS_free(cx, jp->buffer);
+ JS_free(cx, jp);
+ return NULL;
+}
+
+JSBool
+js_FinishJSONParse(JSContext *cx, JSONParser *jp)
+{
+ if (!jp)
+ return JS_TRUE;
+
+ if (jp->objectKey)
+ js_FinishStringBuffer(jp->objectKey);
+ JS_free(cx, jp->objectKey);
+
+ if (jp->buffer)
+ js_FinishStringBuffer(jp->buffer);
+ JS_free(cx, jp->buffer);
+
+ if (!js_RemoveRoot(cx->runtime, &jp->objectStack))
+ return JS_FALSE;
+ JSBool ok = *jp->statep == JSON_PARSE_STATE_FINISHED;
+ JS_free(cx, jp);
+
+ return ok;
+}
+
+static JSBool
+PushState(JSONParser *jp, JSONParserState state)
+{
+ if (*jp->statep == JSON_PARSE_STATE_FINISHED)
+ return JS_FALSE; // extra input
+
+ jp->statep++;
+ if ((uint32)(jp->statep - jp->stateStack) >= JS_ARRAY_LENGTH(jp->stateStack))
+ return JS_FALSE; // too deep
+
+ *jp->statep = state;
+
+ return JS_TRUE;
+}
+
+static JSBool
+PopState(JSONParser *jp)
+{
+ jp->statep--;
+ if (jp->statep < jp->stateStack) {
+ jp->statep = jp->stateStack;
+ return JS_FALSE;
+ }
+
+ if (*jp->statep == JSON_PARSE_STATE_INIT)
+ *jp->statep = JSON_PARSE_STATE_FINISHED;
+
+ return JS_TRUE;
+}
+
+static JSBool
+PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, jsval value)
+{
+ JSAutoTempValueRooter tvr(cx, 1, &value);
+
+ JSBool ok;
+ if (OBJ_IS_ARRAY(cx, parent)) {
+ jsuint len;
+ ok = js_GetLengthProperty(cx, parent, &len);
+ if (ok) {
+ ok = OBJ_DEFINE_PROPERTY(cx, parent, INT_TO_JSID(len), value,
+ NULL, NULL, JSPROP_ENUMERATE, NULL);
+ }
+ } else {
+ ok = JS_DefineUCProperty(cx, parent, jp->objectKey->base,
+ STRING_BUFFER_OFFSET(jp->objectKey), value,
+ NULL, NULL, JSPROP_ENUMERATE);
+ js_FinishStringBuffer(jp->objectKey);
+ js_InitStringBuffer(jp->objectKey);
+ }
+
+ return ok;
+}
+
+static JSBool
+PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
+{
+ jsuint len;
+ if (!js_GetLengthProperty(cx, jp->objectStack, &len))
+ return JS_FALSE;
+ if (len >= JSON_MAX_DEPTH)
+ return JS_FALSE; // decoding error
+
+ jsval v = OBJECT_TO_JSVAL(obj);
+ JSAutoTempValueRooter tvr(cx, v);
+
+ // Check if this is the root object
+ if (len == 0) {
+ *jp->rootVal = v;
+ // This property must be enumerable to keep the array dense
+ if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(0), *jp->rootVal,
+ NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+ }
+
+ jsval p;
+ if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len - 1), &p))
+ return JS_FALSE;
+
+ JS_ASSERT(JSVAL_IS_OBJECT(p));
+ JSObject *parent = JSVAL_TO_OBJECT(p);
+ if (!PushValue(cx, jp, parent, OBJECT_TO_JSVAL(obj)))
+ return JS_FALSE;
+
+ // This property must be enumerable to keep the array dense
+ if (!OBJ_DEFINE_PROPERTY(cx, jp->objectStack, INT_TO_JSID(len), v,
+ NULL, NULL, JSPROP_ENUMERATE, NULL)) {
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+static JSObject *
+GetTopOfObjectStack(JSContext *cx, JSONParser *jp)
+{
+ jsuint length;
+ if (!js_GetLengthProperty(cx, jp->objectStack, &length))
+ return NULL;
+
+ jsval o;
+ if (!OBJ_GET_PROPERTY(cx, jp->objectStack, INT_TO_JSID(length - 1), &o))
+ return NULL;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(o));
+ return JSVAL_TO_OBJECT(o);
+}
+
+static JSBool
+OpenObject(JSContext *cx, JSONParser *jp)
+{
+ JSObject *obj = js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ return PushObject(cx, jp, obj);
+}
+
+static JSBool
+OpenArray(JSContext *cx, JSONParser *jp)
+{
+ // Add an array to an existing array or object
+ JSObject *arr = js_NewArrayObject(cx, 0, NULL);
+ if (!arr)
+ return JS_FALSE;
+
+ return PushObject(cx, jp, arr);
+}
+
+static JSBool
+CloseObject(JSContext *cx, JSONParser *jp)
+{
+ jsuint len;
+ if (!js_GetLengthProperty(cx, jp->objectStack, &len))
+ return JS_FALSE;
+ if (!js_SetLengthProperty(cx, jp->objectStack, len - 1))
+ return JS_FALSE;
+
+ return JS_TRUE;
+}
+
+static JSBool
+CloseArray(JSContext *cx, JSONParser *jp)
+{
+ return CloseObject(cx, jp);
+}
+
+static JSBool
+HandleNumber(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
+{
+ const jschar *ep;
+ double val;
+ if (!js_strtod(cx, buf, buf + len, &ep, &val) || ep != buf + len)
+ return JS_FALSE;
+
+ JSBool ok;
+ jsval numVal;
+ JSObject *obj = GetTopOfObjectStack(cx, jp);
+ if (obj && JS_NewNumberValue(cx, val, &numVal))
+ ok = PushValue(cx, jp, obj, numVal);
+ else
+ ok = JS_FALSE; // decode error
+
+ return ok;
+}
+
+static JSBool
+HandleString(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
+{
+ JSObject *obj = GetTopOfObjectStack(cx, jp);
+ JSString *str = js_NewStringCopyN(cx, buf, len);
+ if (!obj || !str)
+ return JS_FALSE;
+
+ return PushValue(cx, jp, obj, STRING_TO_JSVAL(str));
+}
+
+static JSBool
+HandleKeyword(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
+{
+ jsval keyword;
+ JSTokenType tt = js_CheckKeyword(buf, len);
+ if (tt != TOK_PRIMARY)
+ return JS_FALSE;
+
+ if (buf[0] == 'n')
+ keyword = JSVAL_NULL;
+ else if (buf[0] == 't')
+ keyword = JSVAL_TRUE;
+ else if (buf[0] == 'f')
+ keyword = JSVAL_FALSE;
+ else
+ return JS_FALSE;
+
+ JSObject *obj = GetTopOfObjectStack(cx, jp);
+ if (!obj)
+ return JS_FALSE;
+
+ return PushValue(cx, jp, obj, keyword);
+}
+
+static JSBool
+HandleData(JSContext *cx, JSONParser *jp, JSONDataType type)
+{
+ JSBool ok = JS_FALSE;
+
+ if (!STRING_BUFFER_OK(jp->buffer))
+ return JS_FALSE;
+
+ switch (type) {
+ case JSON_DATA_STRING:
+ ok = HandleString(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ break;
+
+ case JSON_DATA_KEYSTRING:
+ js_AppendUCString(jp->objectKey, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ ok = STRING_BUFFER_OK(jp->objectKey);
+ break;
+
+ case JSON_DATA_NUMBER:
+ ok = HandleNumber(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ break;
+
+ case JSON_DATA_KEYWORD:
+ ok = HandleKeyword(cx, jp, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer));
+ break;
+
+ default:
+ JS_NOT_REACHED("Should have a JSON data type");
+ }
+
+ js_FinishStringBuffer(jp->buffer);
+ js_InitStringBuffer(jp->buffer);
+
+ return ok;
+}
+
+JSBool
+js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len)
+{
+ uint32 i;
+
+ if (*jp->statep == JSON_PARSE_STATE_INIT) {
+ PushState(jp, JSON_PARSE_STATE_OBJECT_VALUE);
+ }
+
+ for (i = 0; i < len; i++) {
+ jschar c = data[i];
+ switch (*jp->statep) {
+ case JSON_PARSE_STATE_VALUE :
+ if (c == ']') {
+ // empty array
+ if (!PopState(jp))
+ return JS_FALSE;
+ if (*jp->statep != JSON_PARSE_STATE_ARRAY)
+ return JS_FALSE; // unexpected char
+ if (!CloseArray(cx, jp) || !PopState(jp))
+ return JS_FALSE;
+ break;
+ }
+
+ if (c == '}') {
+ // we should only find these in OBJECT_KEY state
+ return JS_FALSE; // unexpected failure
+ }
+
+ if (c == '"') {
+ *jp->statep = JSON_PARSE_STATE_STRING;
+ break;
+ }
+
+ if (IsNumChar(c)) {
+ *jp->statep = JSON_PARSE_STATE_NUMBER;
+ js_AppendChar(jp->buffer, c);
+ break;
+ }
+
+ if (JS7_ISLET(c)) {
+ *jp->statep = JSON_PARSE_STATE_KEYWORD;
+ js_AppendChar(jp->buffer, c);
+ break;
+ }
+
+ // fall through in case the value is an object or array
+ case JSON_PARSE_STATE_OBJECT_VALUE :
+ if (c == '{') {
+ *jp->statep = JSON_PARSE_STATE_OBJECT;
+ if (!OpenObject(cx, jp) || !PushState(jp, JSON_PARSE_STATE_OBJECT_PAIR))
+ return JS_FALSE;
+ } else if (c == '[') {
+ *jp->statep = JSON_PARSE_STATE_ARRAY;
+ if (!OpenArray(cx, jp) || !PushState(jp, JSON_PARSE_STATE_VALUE))
+ return JS_FALSE;
+ } else if (!JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_OBJECT :
+ if (c == '}') {
+ if (!CloseObject(cx, jp) || !PopState(jp))
+ return JS_FALSE;
+ } else if (c == ',') {
+ if (!PushState(jp, JSON_PARSE_STATE_OBJECT_PAIR))
+ return JS_FALSE;
+ } else if (c == ']' || !JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_ARRAY :
+ if (c == ']') {
+ if (!CloseArray(cx, jp) || !PopState(jp))
+ return JS_FALSE;
+ } else if (c == ',') {
+ if (!PushState(jp, JSON_PARSE_STATE_VALUE))
+ return JS_FALSE;
+ } else if (!JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_OBJECT_PAIR :
+ if (c == '"') {
+ // we want to be waiting for a : when the string has been read
+ *jp->statep = JSON_PARSE_STATE_OBJECT_IN_PAIR;
+ if (!PushState(jp, JSON_PARSE_STATE_STRING))
+ return JS_FALSE;
+ } else if (c == '}') {
+ // pop off the object pair state and the object state
+ if (!CloseObject(cx, jp) || !PopState(jp) || !PopState(jp))
+ return JS_FALSE;
+ } else if (c == ']' || !JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_OBJECT_IN_PAIR:
+ if (c == ':') {
+ *jp->statep = JSON_PARSE_STATE_VALUE;
+ } else if (!JS_ISXMLSPACE(c)) {
+ return JS_FALSE; // unexpected
+ }
+ break;
+
+ case JSON_PARSE_STATE_STRING:
+ if (c == '"') {
+ if (!PopState(jp))
+ return JS_FALSE;
+ JSONDataType jdt;
+ if (*jp->statep == JSON_PARSE_STATE_OBJECT_IN_PAIR) {
+ jdt = JSON_DATA_KEYSTRING;
+ } else {
+ jdt = JSON_DATA_STRING;
+ }
+ if (!HandleData(cx, jp, jdt))
+ return JS_FALSE;
+ } else if (c == '\\') {
+ *jp->statep = JSON_PARSE_STATE_STRING_ESCAPE;
+ } else {
+ js_AppendChar(jp->buffer, c);
+ }
+ break;
+
+ case JSON_PARSE_STATE_STRING_ESCAPE:
+ switch (c) {
+ case '"':
+ case '\\':
+ case '/':
+ break;
+ case 'b' : c = '\b'; break;
+ case 'f' : c = '\f'; break;
+ case 'n' : c = '\n'; break;
+ case 'r' : c = '\r'; break;
+ case 't' : c = '\t'; break;
+ default :
+ if (c == 'u') {
+ jp->numHex = 0;
+ jp->hexChar = 0;
+ *jp->statep = JSON_PARSE_STATE_STRING_HEX;
+ continue;
+ } else {
+ return JS_FALSE; // unexpected
+ }
+ }
+
+ js_AppendChar(jp->buffer, c);
+ *jp->statep = JSON_PARSE_STATE_STRING;
+ break;
+
+ case JSON_PARSE_STATE_STRING_HEX:
+ if (('0' <= c) && (c <= '9'))
+ jp->hexChar = (jp->hexChar << 4) | (c - '0');
+ else if (('a' <= c) && (c <= 'f'))
+ jp->hexChar = (jp->hexChar << 4) | (c - 'a' + 0x0a);
+ else if (('A' <= c) && (c <= 'F'))
+ jp->hexChar = (jp->hexChar << 4) | (c - 'A' + 0x0a);
+ else
+ return JS_FALSE; // unexpected
+
+ if (++(jp->numHex) == 4) {
+ js_AppendChar(jp->buffer, jp->hexChar);
+ jp->hexChar = 0;
+ jp->numHex = 0;
+ *jp->statep = JSON_PARSE_STATE_STRING;
+ }
+ break;
+
+ case JSON_PARSE_STATE_KEYWORD:
+ if (JS7_ISLET(c)) {
+ js_AppendChar(jp->buffer, c);
+ } else {
+ // this character isn't part of the keyword, process it again
+ i--;
+ if (!PopState(jp))
+ return JS_FALSE;
+
+ if (!HandleData(cx, jp, JSON_DATA_KEYWORD))
+ return JS_FALSE;
+ }
+ break;
+
+ case JSON_PARSE_STATE_NUMBER:
+ if (IsNumChar(c)) {
+ js_AppendChar(jp->buffer, c);
+ } else {
+ // this character isn't part of the number, process it again
+ i--;
+ if (!PopState(jp))
+ return JS_FALSE;
+ if (!HandleData(cx, jp, JSON_DATA_NUMBER))
+ return JS_FALSE;
+ }
+ break;
+
+ case JSON_PARSE_STATE_FINISHED:
+ if (!JS_ISXMLSPACE(c))
+ return JS_FALSE; // extra input
+
+ break;
+
+ default:
+ JS_NOT_REACHED("Invalid JSON parser state");
+ }
+ }
+
+ return JS_TRUE;
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+json_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = ATOM_KEY(CLASS_ATOM(cx, JSON));
+ return JS_TRUE;
+}
+#endif
+
+static JSFunctionSpec json_static_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, json_toSource, 0, 0),
+#endif
+ JS_FN("parse", js_json_parse, 0, 0),
+ JS_FN("stringify", js_json_stringify, 0, 0),
+ JS_FS_END
+};
+
+JSObject *
+js_InitJSONClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *JSON;
+
+ JSON = JS_NewObject(cx, &js_JSONClass, NULL, obj);
+ if (!JSON)
+ return NULL;
+ if (!JS_DefineProperty(cx, obj, js_JSON_str, OBJECT_TO_JSVAL(JSON),
+ JS_PropertyStub, JS_PropertyStub, 0))
+ return NULL;
+
+ if (!JS_DefineFunctions(cx, JSON, json_static_methods))
+ return NULL;
+
+ return JSON;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/json.h b/tools/node_modules/expresso/deps/jscoverage/js/json.h
new file mode 100644
index 0000000..b2fc729
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/json.h
@@ -0,0 +1,107 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey JSON.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Robert Sayre <sayrer@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef json_h___
+#define json_h___
+/*
+ * JS JSON functions.
+ */
+
+#define JSON_MAX_DEPTH 2048
+#define JSON_PARSER_BUFSIZE 1024
+
+JS_BEGIN_EXTERN_C
+
+extern JSClass js_JSONClass;
+
+extern JSObject *
+js_InitJSONClass(JSContext *cx, JSObject *obj);
+
+extern JSBool
+js_Stringify(JSContext *cx, jsval *vp, JSObject *replacer,
+ JSONWriteCallback callback, void *data, uint32 depth);
+
+extern JSBool js_TryJSON(JSContext *cx, jsval *vp);
+
+enum JSONParserState {
+ JSON_PARSE_STATE_INIT,
+ JSON_PARSE_STATE_OBJECT_VALUE,
+ JSON_PARSE_STATE_VALUE,
+ JSON_PARSE_STATE_OBJECT,
+ JSON_PARSE_STATE_OBJECT_PAIR,
+ JSON_PARSE_STATE_OBJECT_IN_PAIR,
+ JSON_PARSE_STATE_ARRAY,
+ JSON_PARSE_STATE_STRING,
+ JSON_PARSE_STATE_STRING_ESCAPE,
+ JSON_PARSE_STATE_STRING_HEX,
+ JSON_PARSE_STATE_NUMBER,
+ JSON_PARSE_STATE_KEYWORD,
+ JSON_PARSE_STATE_FINISHED
+};
+
+enum JSONDataType {
+ JSON_DATA_STRING,
+ JSON_DATA_KEYSTRING,
+ JSON_DATA_NUMBER,
+ JSON_DATA_KEYWORD
+};
+
+struct JSONParser {
+ /* Used while handling \uNNNN in strings */
+ jschar hexChar;
+ uint8 numHex;
+
+ JSONParserState *statep;
+ JSONParserState stateStack[JSON_MAX_DEPTH];
+ jsval *rootVal;
+ JSStringBuffer *objectKey;
+ JSStringBuffer *buffer;
+ JSObject *objectStack;
+};
+
+extern JSONParser *
+js_BeginJSONParse(JSContext *cx, jsval *rootVal);
+
+extern JSBool
+js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len);
+
+extern JSBool
+js_FinishJSONParse(JSContext *cx, JSONParser *jp);
+
+JS_END_EXTERN_C
+
+#endif /* json_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp
new file mode 100644
index 0000000..a3227dc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.cpp
@@ -0,0 +1,5304 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS bytecode descriptors, disassemblers, and decompilers.
+ */
+#include "jsstddef.h"
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsdtoa.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsiter.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+#include "jstracer.h"
+
+#include "jsautooplen.h"
+
+/* Verify JSOP_XXX_LENGTH constant definitions. */
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ JS_STATIC_ASSERT(op##_LENGTH == length);
+#include "jsopcode.tbl"
+#undef OPDEF
+
+static const char js_incop_strs[][3] = {"++", "--"};
+static const char js_for_each_str[] = "for each";
+
+const JSCodeSpec js_CodeSpec[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ {length,nuses,ndefs,prec,format},
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+
+uintN js_NumCodeSpecs = JS_ARRAY_LENGTH(js_CodeSpec);
+
+/*
+ * Each element of the array is either a source literal associated with JS
+ * bytecode or null.
+ */
+static const char *CodeToken[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ token,
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+
+#if defined(DEBUG) || defined(JS_JIT_SPEW)
+/*
+ * Array of JS bytecode names used by DEBUG-only js_Disassemble and by
+ * JIT debug spew.
+ */
+const char *js_CodeName[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ name,
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+#endif
+
+/************************************************************************/
+
+static ptrdiff_t
+GetJumpOffset(jsbytecode *pc, jsbytecode *pc2)
+{
+ uint32 type;
+
+ type = JOF_OPTYPE(*pc);
+ if (JOF_TYPE_IS_EXTENDED_JUMP(type))
+ return GET_JUMPX_OFFSET(pc2);
+ return GET_JUMP_OFFSET(pc2);
+}
+
+uintN
+js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
+ ptrdiff_t pcoff)
+{
+ JSOp op;
+ uintN span, base;
+
+ op = (JSOp)*pc;
+ if (op == JSOP_TRAP)
+ op = JS_GetTrapOpcode(cx, script, pc);
+ JS_ASSERT(js_CodeSpec[op].length >= 1 + pcoff + UINT16_LEN);
+
+ /*
+ * We need to detect index base prefix. It presents when resetbase
+ * follows the bytecode.
+ */
+ span = js_CodeSpec[op].length;
+ base = 0;
+ if (pc - script->code + span < script->length) {
+ if (pc[span] == JSOP_RESETBASE) {
+ base = GET_INDEXBASE(pc - JSOP_INDEXBASE_LENGTH);
+ } else if (pc[span] == JSOP_RESETBASE0) {
+ JS_ASSERT(JSOP_INDEXBASE1 <= pc[-1] || pc[-1] <= JSOP_INDEXBASE3);
+ base = (pc[-1] - JSOP_INDEXBASE1 + 1) << 16;
+ }
+ }
+ return base + GET_UINT16(pc + pcoff);
+}
+
+uintN
+js_GetVariableBytecodeLength(jsbytecode *pc)
+{
+ JSOp op;
+ uintN jmplen, ncases;
+ jsint low, high;
+
+ op = (JSOp) *pc;
+ JS_ASSERT(js_CodeSpec[op].length == -1);
+ switch (op) {
+ case JSOP_TABLESWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto do_table;
+ case JSOP_TABLESWITCH:
+ jmplen = JUMP_OFFSET_LEN;
+ do_table:
+ /* Structure: default-jump case-low case-high case1-jump ... */
+ pc += jmplen;
+ low = GET_JUMP_OFFSET(pc);
+ pc += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc);
+ ncases = (uintN)(high - low + 1);
+ return 1 + jmplen + INDEX_LEN + INDEX_LEN + ncases * jmplen;
+
+ case JSOP_LOOKUPSWITCHX:
+ jmplen = JUMPX_OFFSET_LEN;
+ goto do_lookup;
+ default:
+ JS_ASSERT(op == JSOP_LOOKUPSWITCH);
+ jmplen = JUMP_OFFSET_LEN;
+ do_lookup:
+ /* Structure: default-jump case-count (case1-value case1-jump) ... */
+ pc += jmplen;
+ ncases = GET_UINT16(pc);
+ return 1 + jmplen + INDEX_LEN + ncases * (INDEX_LEN + jmplen);
+ }
+}
+
+uintN
+js_GetVariableStackUseLength(JSOp op, jsbytecode *pc)
+{
+ JS_ASSERT(*pc == op || *pc == JSOP_TRAP);
+ JS_ASSERT(js_CodeSpec[op].nuses == -1);
+ switch (op) {
+ case JSOP_POPN:
+ return GET_UINT16(pc);
+ case JSOP_LEAVEBLOCK:
+ return GET_UINT16(pc);
+ case JSOP_LEAVEBLOCKEXPR:
+ return GET_UINT16(pc) + 1;
+ case JSOP_NEWARRAY:
+ return GET_UINT24(pc);
+ default:
+ /* stack: fun, this, [argc arguments] */
+ JS_ASSERT(op == JSOP_NEW || op == JSOP_CALL ||
+ op == JSOP_EVAL || op == JSOP_SETCALL ||
+ op == JSOP_APPLY);
+ return 2 + GET_ARGC(pc);
+ }
+}
+
+#ifdef DEBUG
+
+JS_FRIEND_API(JSBool)
+js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp)
+{
+ jsbytecode *pc, *end;
+ uintN len;
+
+ pc = script->code;
+ end = pc + script->length;
+ while (pc < end) {
+ if (pc == script->main)
+ fputs("main:\n", fp);
+ len = js_Disassemble1(cx, script, pc,
+ PTRDIFF(pc, script->code, jsbytecode),
+ lines, fp);
+ if (!len)
+ return JS_FALSE;
+ pc += len;
+ }
+ return JS_TRUE;
+}
+
+const char *
+ToDisassemblySource(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSScopeProperty *sprop;
+ char *source;
+ const char *bytes;
+ JSString *str;
+
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) {
+ source = JS_sprintf_append(NULL, "depth %d {",
+ OBJ_BLOCK_DEPTH(cx, obj));
+ for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
+ sprop = sprop->parent) {
+ bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(sprop->id));
+ if (!bytes)
+ return NULL;
+ source = JS_sprintf_append(source, "%s: %d%s",
+ bytes, sprop->shortid,
+ sprop->parent ? ", " : "");
+ }
+ source = JS_sprintf_append(source, "}");
+ if (!source)
+ return NULL;
+ str = JS_NewString(cx, source, strlen(source));
+ if (!str)
+ return NULL;
+ return js_GetStringBytes(cx, str);
+ }
+ }
+ return js_ValueToPrintableSource(cx, v);
+}
+
+JS_FRIEND_API(uintN)
+js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
+ uintN loc, JSBool lines, FILE *fp)
+{
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t len, off, jmplen;
+ uint32 type;
+ JSAtom *atom;
+ uintN index;
+ JSObject *obj;
+ jsval v;
+ const char *bytes;
+ jsint i;
+
+ op = (JSOp)*pc;
+ if (op >= JSOP_LIMIT) {
+ char numBuf1[12], numBuf2[12];
+ JS_snprintf(numBuf1, sizeof numBuf1, "%d", op);
+ JS_snprintf(numBuf2, sizeof numBuf2, "%d", JSOP_LIMIT);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BYTECODE_TOO_BIG, numBuf1, numBuf2);
+ return 0;
+ }
+ cs = &js_CodeSpec[op];
+ len = (ptrdiff_t) cs->length;
+ fprintf(fp, "%05u:", loc);
+ if (lines)
+ fprintf(fp, "%4u", JS_PCToLineNumber(cx, script, pc));
+ fprintf(fp, " %s", js_CodeName[op]);
+ type = JOF_TYPE(cs->format);
+ switch (type) {
+ case JOF_BYTE:
+ if (op == JSOP_TRAP) {
+ op = JS_GetTrapOpcode(cx, script, pc);
+ len = (ptrdiff_t) js_CodeSpec[op].length;
+ }
+ break;
+
+ case JOF_JUMP:
+ case JOF_JUMPX:
+ off = GetJumpOffset(pc, pc);
+ fprintf(fp, " %u (%d)", loc + (intN) off, (intN) off);
+ break;
+
+ case JOF_ATOM:
+ case JOF_OBJECT:
+ case JOF_REGEXP:
+ index = js_GetIndexFromBytecode(cx, script, pc, 0);
+ if (type == JOF_ATOM) {
+ JS_GET_SCRIPT_ATOM(script, index, atom);
+ v = ATOM_KEY(atom);
+ } else {
+ if (type == JOF_OBJECT)
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ else
+ JS_GET_SCRIPT_REGEXP(script, index, obj);
+ v = OBJECT_TO_JSVAL(obj);
+ }
+ bytes = ToDisassemblySource(cx, v);
+ if (!bytes)
+ return 0;
+ fprintf(fp, " %s", bytes);
+ break;
+
+ case JOF_UINT16:
+ i = (jsint)GET_UINT16(pc);
+ goto print_int;
+
+ case JOF_TABLESWITCH:
+ case JOF_TABLESWITCHX:
+ {
+ jsbytecode *pc2;
+ jsint i, low, high;
+
+ jmplen = (type == JOF_TABLESWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ fprintf(fp, " defaultOffset %d low %d high %d", (intN) off, low, high);
+ for (i = low; i <= high; i++) {
+ off = GetJumpOffset(pc, pc2);
+ fprintf(fp, "\n\t%d: %d", i, (intN) off);
+ pc2 += jmplen;
+ }
+ len = 1 + pc2 - pc;
+ break;
+ }
+
+ case JOF_LOOKUPSWITCH:
+ case JOF_LOOKUPSWITCHX:
+ {
+ jsbytecode *pc2;
+ jsatomid npairs;
+
+ jmplen = (type == JOF_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ npairs = GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+ fprintf(fp, " offset %d npairs %u", (intN) off, (uintN) npairs);
+ while (npairs) {
+ JS_GET_SCRIPT_ATOM(script, GET_INDEX(pc2), atom);
+ pc2 += INDEX_LEN;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+
+ bytes = ToDisassemblySource(cx, ATOM_KEY(atom));
+ if (!bytes)
+ return 0;
+ fprintf(fp, "\n\t%s: %d", bytes, (intN) off);
+ npairs--;
+ }
+ len = 1 + pc2 - pc;
+ break;
+ }
+
+ case JOF_QARG:
+ fprintf(fp, " %u", GET_ARGNO(pc));
+ break;
+
+ case JOF_LOCAL:
+ fprintf(fp, " %u", GET_SLOTNO(pc));
+ break;
+
+ case JOF_SLOTATOM:
+ case JOF_SLOTOBJECT:
+ fprintf(fp, " %u", GET_SLOTNO(pc));
+ index = js_GetIndexFromBytecode(cx, script, pc, SLOTNO_LEN);
+ if (type == JOF_SLOTATOM) {
+ JS_GET_SCRIPT_ATOM(script, index, atom);
+ v = ATOM_KEY(atom);
+ } else {
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ v = OBJECT_TO_JSVAL(obj);
+ }
+ bytes = ToDisassemblySource(cx, v);
+ if (!bytes)
+ return 0;
+ fprintf(fp, " %s", bytes);
+ break;
+
+ case JOF_UINT24:
+ JS_ASSERT(op == JSOP_UINT24 || op == JSOP_NEWARRAY);
+ i = (jsint)GET_UINT24(pc);
+ goto print_int;
+
+ case JOF_UINT8:
+ i = pc[1];
+ goto print_int;
+
+ case JOF_INT8:
+ i = GET_INT8(pc);
+ goto print_int;
+
+ case JOF_INT32:
+ JS_ASSERT(op == JSOP_INT32);
+ i = GET_INT32(pc);
+ print_int:
+ fprintf(fp, " %d", i);
+ break;
+
+ default: {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_UNKNOWN_FORMAT, numBuf);
+ return 0;
+ }
+ }
+ fputs("\n", fp);
+ return len;
+}
+
+#endif /* DEBUG */
+
+/************************************************************************/
+
+/*
+ * Sprintf, but with unlimited and automatically allocated buffering.
+ */
+typedef struct Sprinter {
+ JSContext *context; /* context executing the decompiler */
+ JSArenaPool *pool; /* string allocation pool */
+ char *base; /* base address of buffer in pool */
+ size_t size; /* size of buffer allocated at base */
+ ptrdiff_t offset; /* offset of next free char in buffer */
+} Sprinter;
+
+#define INIT_SPRINTER(cx, sp, ap, off) \
+ ((sp)->context = cx, (sp)->pool = ap, (sp)->base = NULL, (sp)->size = 0, \
+ (sp)->offset = off)
+
+#define OFF2STR(sp,off) ((sp)->base + (off))
+#define STR2OFF(sp,str) ((str) - (sp)->base)
+#define RETRACT(sp,str) ((sp)->offset = STR2OFF(sp, str))
+
+static JSBool
+SprintEnsureBuffer(Sprinter *sp, size_t len)
+{
+ ptrdiff_t nb;
+ char *base;
+
+ nb = (sp->offset + len + 1) - sp->size;
+ if (nb < 0)
+ return JS_TRUE;
+ base = sp->base;
+ if (!base) {
+ JS_ARENA_ALLOCATE_CAST(base, char *, sp->pool, nb);
+ } else {
+ JS_ARENA_GROW_CAST(base, char *, sp->pool, sp->size, nb);
+ }
+ if (!base) {
+ js_ReportOutOfScriptQuota(sp->context);
+ return JS_FALSE;
+ }
+ sp->base = base;
+ sp->size += nb;
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+SprintPut(Sprinter *sp, const char *s, size_t len)
+{
+ ptrdiff_t offset;
+ char *bp;
+
+ /* Allocate space for s, including the '\0' at the end. */
+ if (!SprintEnsureBuffer(sp, len))
+ return -1;
+
+ /* Advance offset and copy s into sp's buffer. */
+ offset = sp->offset;
+ sp->offset += len;
+ bp = sp->base + offset;
+ memmove(bp, s, len);
+ bp[len] = 0;
+ return offset;
+}
+
+static ptrdiff_t
+SprintCString(Sprinter *sp, const char *s)
+{
+ return SprintPut(sp, s, strlen(s));
+}
+
+static ptrdiff_t
+SprintString(Sprinter *sp, JSString *str)
+{
+ jschar *chars;
+ size_t length, size;
+ ptrdiff_t offset;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0)
+ return sp->offset;
+
+ size = js_GetDeflatedStringLength(sp->context, chars, length);
+ if (size == (size_t)-1 || !SprintEnsureBuffer(sp, size))
+ return -1;
+
+ offset = sp->offset;
+ sp->offset += size;
+ js_DeflateStringToBuffer(sp->context, chars, length, sp->base + offset,
+ &size);
+ sp->base[sp->offset] = 0;
+ return offset;
+}
+
+
+static ptrdiff_t
+Sprint(Sprinter *sp, const char *format, ...)
+{
+ va_list ap;
+ char *bp;
+ ptrdiff_t offset;
+
+ va_start(ap, format);
+ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
+ va_end(ap);
+ if (!bp) {
+ JS_ReportOutOfMemory(sp->context);
+ return -1;
+ }
+ offset = SprintCString(sp, bp);
+ free(bp);
+ return offset;
+}
+
+const char js_EscapeMap[] = {
+ '\b', 'b',
+ '\f', 'f',
+ '\n', 'n',
+ '\r', 'r',
+ '\t', 't',
+ '\v', 'v',
+ '"', '"',
+ '\'', '\'',
+ '\\', '\\',
+ '\0', '0'
+};
+
+#define DONT_ESCAPE 0x10000
+
+static char *
+QuoteString(Sprinter *sp, JSString *str, uint32 quote)
+{
+ JSBool dontEscape, ok;
+ jschar qc, c;
+ ptrdiff_t off, len;
+ const jschar *s, *t, *z;
+ const char *e;
+ char *bp;
+
+ /* Sample off first for later return value pointer computation. */
+ dontEscape = (quote & DONT_ESCAPE) != 0;
+ qc = (jschar) quote;
+ off = sp->offset;
+ if (qc && Sprint(sp, "%c", (char)qc) < 0)
+ return NULL;
+
+ /* Loop control variables: z points at end of string sentinel. */
+ JSSTRING_CHARS_AND_END(str, s, z);
+ for (t = s; t < z; s = ++t) {
+ /* Move t forward from s past un-quote-worthy characters. */
+ c = *t;
+ while (JS_ISPRINT(c) && c != qc && c != '\\' && c != '\t' &&
+ !(c >> 8)) {
+ c = *++t;
+ if (t == z)
+ break;
+ }
+ len = PTRDIFF(t, s, jschar);
+
+ /* Allocate space for s, including the '\0' at the end. */
+ if (!SprintEnsureBuffer(sp, len))
+ return NULL;
+
+ /* Advance sp->offset and copy s into sp's buffer. */
+ bp = sp->base + sp->offset;
+ sp->offset += len;
+ while (--len >= 0)
+ *bp++ = (char) *s++;
+ *bp = '\0';
+
+ if (t == z)
+ break;
+
+ /* Use js_EscapeMap, \u, or \x only if necessary. */
+ if (!(c >> 8) && (e = strchr(js_EscapeMap, (int)c)) != NULL) {
+ ok = dontEscape
+ ? Sprint(sp, "%c", (char)c) >= 0
+ : Sprint(sp, "\\%c", e[1]) >= 0;
+ } else {
+ ok = Sprint(sp, (c >> 8) ? "\\u%04X" : "\\x%02X", c) >= 0;
+ }
+ if (!ok)
+ return NULL;
+ }
+
+ /* Sprint the closing quote and return the quoted string. */
+ if (qc && Sprint(sp, "%c", (char)qc) < 0)
+ return NULL;
+
+ /*
+ * If we haven't Sprint'd anything yet, Sprint an empty string so that
+ * the OFF2STR below gives a valid result.
+ */
+ if (off == sp->offset && Sprint(sp, "") < 0)
+ return NULL;
+ return OFF2STR(sp, off);
+}
+
+JSString *
+js_QuoteString(JSContext *cx, JSString *str, jschar quote)
+{
+ void *mark;
+ Sprinter sprinter;
+ char *bytes;
+ JSString *escstr;
+
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
+ bytes = QuoteString(&sprinter, str, quote);
+ escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return escstr;
+}
+
+/************************************************************************/
+
+struct JSPrinter {
+ Sprinter sprinter; /* base class state */
+ JSArenaPool pool; /* string allocation pool */
+ uintN indent; /* indentation in spaces */
+ JSPackedBool pretty; /* pretty-print: indent, use newlines */
+ JSPackedBool grouped; /* in parenthesized expression context */
+ JSScript *script; /* script being printed */
+ jsbytecode *dvgfence; /* DecompileExpression fencepost */
+ jsbytecode **pcstack; /* DecompileExpression modeled stack */
+ JSFunction *fun; /* interpreted function */
+ jsuword *localNames; /* argument and variable names */
+};
+
+/*
+ * Hack another flag, a la JS_DONT_PRETTY_PRINT, into uintN indent parameters
+ * to functions such as js_DecompileFunction and js_NewPrinter. This time, as
+ * opposed to JS_DONT_PRETTY_PRINT back in the dark ages, we can assume that a
+ * uintN is at least 32 bits.
+ */
+#define JS_IN_GROUP_CONTEXT 0x10000
+
+JSPrinter *
+JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
+ uintN indent, JSBool pretty)
+{
+ JSPrinter *jp;
+
+ jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter));
+ if (!jp)
+ return NULL;
+ INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
+ JS_INIT_ARENA_POOL(&jp->pool, name, 256, 1, &cx->scriptStackQuota);
+ jp->indent = indent & ~JS_IN_GROUP_CONTEXT;
+ jp->pretty = pretty;
+ jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;
+ jp->script = NULL;
+ jp->dvgfence = NULL;
+ jp->pcstack = NULL;
+ jp->fun = fun;
+ jp->localNames = NULL;
+ if (fun && FUN_INTERPRETED(fun) && JS_GET_LOCAL_NAME_COUNT(fun)) {
+ jp->localNames = js_GetLocalNameArray(cx, fun, &jp->pool);
+ if (!jp->localNames) {
+ js_DestroyPrinter(jp);
+ return NULL;
+ }
+ }
+ return jp;
+}
+
+void
+js_DestroyPrinter(JSPrinter *jp)
+{
+ JS_FinishArenaPool(&jp->pool);
+ JS_free(jp->sprinter.context, jp);
+}
+
+JSString *
+js_GetPrinterOutput(JSPrinter *jp)
+{
+ JSContext *cx;
+ JSString *str;
+
+ cx = jp->sprinter.context;
+ if (!jp->sprinter.base)
+ return cx->runtime->emptyString;
+ str = JS_NewStringCopyZ(cx, jp->sprinter.base);
+ if (!str)
+ return NULL;
+ JS_FreeArenaPool(&jp->pool);
+ INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
+ return str;
+}
+
+/*
+ * NB: Indexed by SRC_DECL_* defines from jsemit.h.
+ */
+static const char * const var_prefix[] = {"var ", "const ", "let "};
+
+static const char *
+VarPrefix(jssrcnote *sn)
+{
+ if (sn && (SN_TYPE(sn) == SRC_DECL || SN_TYPE(sn) == SRC_GROUPASSIGN)) {
+ ptrdiff_t type = js_GetSrcNoteOffset(sn, 0);
+ if ((uintN)type <= SRC_DECL_LET)
+ return var_prefix[type];
+ }
+ return "";
+}
+
+int
+js_printf(JSPrinter *jp, const char *format, ...)
+{
+ va_list ap;
+ char *bp, *fp;
+ int cc;
+
+ if (*format == '\0')
+ return 0;
+
+ va_start(ap, format);
+
+ /* If pretty-printing, expand magic tab into a run of jp->indent spaces. */
+ if (*format == '\t') {
+ format++;
+ if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)
+ return -1;
+ }
+
+ /* Suppress newlines (must be once per format, at the end) if not pretty. */
+ fp = NULL;
+ if (!jp->pretty && format[cc = strlen(format) - 1] == '\n') {
+ fp = JS_strdup(jp->sprinter.context, format);
+ if (!fp)
+ return -1;
+ fp[cc] = '\0';
+ format = fp;
+ }
+
+ /* Allocate temp space, convert format, and put. */
+ bp = JS_vsmprintf(format, ap); /* XXX vsaprintf */
+ if (fp) {
+ JS_free(jp->sprinter.context, fp);
+ format = NULL;
+ }
+ if (!bp) {
+ JS_ReportOutOfMemory(jp->sprinter.context);
+ return -1;
+ }
+
+ cc = strlen(bp);
+ if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
+ cc = -1;
+ free(bp);
+
+ va_end(ap);
+ return cc;
+}
+
+JSBool
+js_puts(JSPrinter *jp, const char *s)
+{
+ return SprintCString(&jp->sprinter, s) >= 0;
+}
+
+/************************************************************************/
+
+typedef struct SprintStack {
+ Sprinter sprinter; /* sprinter for postfix to infix buffering */
+ ptrdiff_t *offsets; /* stack of postfix string offsets */
+ jsbytecode *opcodes; /* parallel stack of JS opcodes */
+ uintN top; /* top of stack index */
+ uintN inArrayInit; /* array initialiser/comprehension level */
+ JSBool inGenExp; /* in generator expression */
+ JSPrinter *printer; /* permanent output goes here */
+} SprintStack;
+
+/*
+ * Find the depth of the operand stack when the interpreter reaches the given
+ * pc in script. pcstack must have space for least script->depth elements. On
+ * return it will contain pointers to opcodes that populated the interpreter's
+ * current operand stack.
+ *
+ * This function cannot raise an exception or error. However, due to a risk of
+ * potential bugs when modeling the stack, the function returns -1 if it
+ * detects an inconsistency in the model. Such an inconsistency triggers an
+ * assert in a debug build.
+ */
+static intN
+ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *pc,
+ jsbytecode **pcstack);
+
+#define FAILED_EXPRESSION_DECOMPILER ((char *) 1)
+
+/*
+ * Decompile a part of expression up to the given pc. The function returns
+ * NULL on out-of-memory, or the FAILED_EXPRESSION_DECOMPILER sentinel when
+ * the decompiler fails due to a bug and/or unimplemented feature, or the
+ * decompiled string on success.
+ */
+static char *
+DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
+ jsbytecode *pc);
+
+/*
+ * Get a stacked offset from ss->sprinter.base, or if the stacked value |off|
+ * is negative, fetch the generating pc from printer->pcstack[-2 - off] and
+ * decompile the code that generated the missing value. This is used when
+ * reporting errors, where the model stack will lack |pcdepth| non-negative
+ * offsets (see DecompileExpression and DecompileCode).
+ *
+ * If the stacked offset is -1, return 0 to index the NUL padding at the start
+ * of ss->sprinter.base. If this happens, it means there is a decompiler bug
+ * to fix, but it won't violate memory safety.
+ */
+static ptrdiff_t
+GetOff(SprintStack *ss, uintN i)
+{
+ ptrdiff_t off;
+ jsbytecode *pc;
+ char *bytes;
+
+ off = ss->offsets[i];
+ if (off >= 0)
+ return off;
+
+ JS_ASSERT(off <= -2);
+ JS_ASSERT(ss->printer->pcstack);
+ if (off < -2 && ss->printer->pcstack) {
+ pc = ss->printer->pcstack[-2 - off];
+ bytes = DecompileExpression(ss->sprinter.context, ss->printer->script,
+ ss->printer->fun, pc);
+ if (!bytes)
+ return 0;
+ if (bytes != FAILED_EXPRESSION_DECOMPILER) {
+ off = SprintCString(&ss->sprinter, bytes);
+ if (off < 0)
+ off = 0;
+ ss->offsets[i] = off;
+ JS_free(ss->sprinter.context, bytes);
+ return off;
+ }
+ if (!ss->sprinter.base && SprintPut(&ss->sprinter, "", 0) >= 0) {
+ memset(ss->sprinter.base, 0, ss->sprinter.offset);
+ ss->offsets[i] = -1;
+ }
+ }
+ return 0;
+}
+
+static const char *
+GetStr(SprintStack *ss, uintN i)
+{
+ ptrdiff_t off;
+
+ /*
+ * Must call GetOff before using ss->sprinter.base, since it may be null
+ * until bootstrapped by GetOff.
+ */
+ off = GetOff(ss, i);
+ return OFF2STR(&ss->sprinter, off);
+}
+
+/*
+ * Gap between stacked strings to allow for insertion of parens and commas
+ * when auto-parenthesizing expressions and decompiling array initialisers
+ * (see the JSOP_NEWARRAY case in Decompile).
+ */
+#define PAREN_SLOP (2 + 1)
+
+/*
+ * These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETNAME,
+ * JSOP_SETPROP, and JSOP_SETELEM, respectively. They are never stored in
+ * bytecode, so they don't preempt valid opcodes.
+ */
+#define JSOP_GETPROP2 256
+#define JSOP_GETELEM2 257
+
+static void
+AddParenSlop(SprintStack *ss)
+{
+ memset(OFF2STR(&ss->sprinter, ss->sprinter.offset), 0, PAREN_SLOP);
+ ss->sprinter.offset += PAREN_SLOP;
+}
+
+static JSBool
+PushOff(SprintStack *ss, ptrdiff_t off, JSOp op)
+{
+ uintN top;
+
+ if (!SprintEnsureBuffer(&ss->sprinter, PAREN_SLOP))
+ return JS_FALSE;
+
+ /* ss->top points to the next free slot; be paranoid about overflow. */
+ top = ss->top;
+ JS_ASSERT(top < StackDepth(ss->printer->script));
+ if (top >= StackDepth(ss->printer->script)) {
+ JS_ReportOutOfMemory(ss->sprinter.context);
+ return JS_FALSE;
+ }
+
+ /* The opcodes stack must contain real bytecodes that index js_CodeSpec. */
+ ss->offsets[top] = off;
+ ss->opcodes[top] = (op == JSOP_GETPROP2) ? JSOP_GETPROP
+ : (op == JSOP_GETELEM2) ? JSOP_GETELEM
+ : (jsbytecode) op;
+ ss->top = ++top;
+ AddParenSlop(ss);
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+PopOffPrec(SprintStack *ss, uint8 prec)
+{
+ uintN top;
+ const JSCodeSpec *topcs;
+ ptrdiff_t off;
+
+ /* ss->top points to the next free slot; be paranoid about underflow. */
+ top = ss->top;
+ JS_ASSERT(top != 0);
+ if (top == 0)
+ return 0;
+
+ ss->top = --top;
+ off = GetOff(ss, top);
+ topcs = &js_CodeSpec[ss->opcodes[top]];
+ if (topcs->prec != 0 && topcs->prec < prec) {
+ ss->sprinter.offset = ss->offsets[top] = off - 2;
+ off = Sprint(&ss->sprinter, "(%s)", OFF2STR(&ss->sprinter, off));
+ } else {
+ ss->sprinter.offset = off;
+ }
+ return off;
+}
+
+static const char *
+PopStrPrec(SprintStack *ss, uint8 prec)
+{
+ ptrdiff_t off;
+
+ off = PopOffPrec(ss, prec);
+ return OFF2STR(&ss->sprinter, off);
+}
+
+static ptrdiff_t
+PopOff(SprintStack *ss, JSOp op)
+{
+ return PopOffPrec(ss, js_CodeSpec[op].prec);
+}
+
+static const char *
+PopStr(SprintStack *ss, JSOp op)
+{
+ return PopStrPrec(ss, js_CodeSpec[op].prec);
+}
+
+typedef struct TableEntry {
+ jsval key;
+ ptrdiff_t offset;
+ JSAtom *label;
+ jsint order; /* source order for stable tableswitch sort */
+} TableEntry;
+
+static JSBool
+CompareOffsets(void *arg, const void *v1, const void *v2, int *result)
+{
+ ptrdiff_t offset_diff;
+ const TableEntry *te1 = (const TableEntry *) v1,
+ *te2 = (const TableEntry *) v2;
+
+ offset_diff = te1->offset - te2->offset;
+ *result = (offset_diff == 0 ? te1->order - te2->order
+ : offset_diff < 0 ? -1
+ : 1);
+ return JS_TRUE;
+}
+
+static ptrdiff_t
+SprintDoubleValue(Sprinter *sp, jsval v, JSOp *opp)
+{
+ jsdouble d;
+ ptrdiff_t todo;
+ char *s, buf[DTOSTR_STANDARD_BUFFER_SIZE];
+
+ JS_ASSERT(JSVAL_IS_DOUBLE(v));
+ d = *JSVAL_TO_DOUBLE(v);
+ if (JSDOUBLE_IS_NEGZERO(d)) {
+ todo = SprintCString(sp, "-0");
+ *opp = JSOP_NEG;
+ } else if (!JSDOUBLE_IS_FINITE(d)) {
+ /* Don't use Infinity and NaN, they're mutable. */
+ todo = SprintCString(sp,
+ JSDOUBLE_IS_NaN(d)
+ ? "0 / 0"
+ : (d < 0)
+ ? "1 / -0"
+ : "1 / 0");
+ *opp = JSOP_DIV;
+ } else {
+ s = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, d);
+ if (!s) {
+ JS_ReportOutOfMemory(sp->context);
+ return -1;
+ }
+ JS_ASSERT(strcmp(s, js_Infinity_str) &&
+ (*s != '-' ||
+ strcmp(s + 1, js_Infinity_str)) &&
+ strcmp(s, js_NaN_str));
+ todo = Sprint(sp, s);
+ }
+ return todo;
+}
+
+static jsbytecode *
+Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop);
+
+static JSBool
+DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
+ jsbytecode *pc, ptrdiff_t switchLength,
+ ptrdiff_t defaultOffset, JSBool isCondSwitch)
+{
+ JSContext *cx;
+ JSPrinter *jp;
+ ptrdiff_t off, off2, diff, caseExprOff, todo;
+ char *lval, *rval;
+ uintN i;
+ jsval key;
+ JSString *str;
+
+ cx = ss->sprinter.context;
+ jp = ss->printer;
+
+ /* JSOP_CONDSWITCH doesn't pop, unlike JSOP_{LOOKUP,TABLE}SWITCH. */
+ off = isCondSwitch ? GetOff(ss, ss->top-1) : PopOff(ss, JSOP_NOP);
+ lval = OFF2STR(&ss->sprinter, off);
+
+ js_printf(jp, "\tswitch (%s) {\n", lval);
+
+ if (tableLength) {
+ diff = table[0].offset - defaultOffset;
+ if (diff > 0) {
+ jp->indent += 2;
+ js_printf(jp, "\t%s:\n", js_default_str);
+ jp->indent += 2;
+ if (!Decompile(ss, pc + defaultOffset, diff, JSOP_NOP))
+ return JS_FALSE;
+ jp->indent -= 4;
+ }
+
+ caseExprOff = isCondSwitch ? JSOP_CONDSWITCH_LENGTH : 0;
+
+ for (i = 0; i < tableLength; i++) {
+ off = table[i].offset;
+ off2 = (i + 1 < tableLength) ? table[i + 1].offset : switchLength;
+
+ key = table[i].key;
+ if (isCondSwitch) {
+ ptrdiff_t nextCaseExprOff;
+
+ /*
+ * key encodes the JSOP_CASE bytecode's offset from switchtop.
+ * The next case expression follows immediately, unless we are
+ * at the last case.
+ */
+ nextCaseExprOff = (ptrdiff_t)JSVAL_TO_INT(key);
+ nextCaseExprOff += js_CodeSpec[pc[nextCaseExprOff]].length;
+ jp->indent += 2;
+ if (!Decompile(ss, pc + caseExprOff,
+ nextCaseExprOff - caseExprOff, JSOP_NOP)) {
+ return JS_FALSE;
+ }
+ caseExprOff = nextCaseExprOff;
+
+ /* Balance the stack as if this JSOP_CASE matched. */
+ --ss->top;
+ } else {
+ /*
+ * key comes from an atom, not the decompiler, so we need to
+ * quote it if it's a string literal. But if table[i].label
+ * is non-null, key was constant-propagated and label is the
+ * name of the const we should show as the case label. We set
+ * key to undefined so this identifier is escaped, if required
+ * by non-ASCII characters, but not quoted, by QuoteString.
+ */
+ todo = -1;
+ if (table[i].label) {
+ str = ATOM_TO_STRING(table[i].label);
+ key = JSVAL_VOID;
+ } else if (JSVAL_IS_DOUBLE(key)) {
+ JSOp junk;
+
+ todo = SprintDoubleValue(&ss->sprinter, key, &junk);
+ str = NULL;
+ } else {
+ str = js_ValueToString(cx, key);
+ if (!str)
+ return JS_FALSE;
+ }
+ if (todo >= 0) {
+ rval = OFF2STR(&ss->sprinter, todo);
+ } else {
+ rval = QuoteString(&ss->sprinter, str, (jschar)
+ (JSVAL_IS_STRING(key) ? '"' : 0));
+ if (!rval)
+ return JS_FALSE;
+ }
+ RETRACT(&ss->sprinter, rval);
+ jp->indent += 2;
+ js_printf(jp, "\tcase %s:\n", rval);
+ }
+
+ jp->indent += 2;
+ if (off <= defaultOffset && defaultOffset < off2) {
+ diff = defaultOffset - off;
+ if (diff != 0) {
+ if (!Decompile(ss, pc + off, diff, JSOP_NOP))
+ return JS_FALSE;
+ off = defaultOffset;
+ }
+ jp->indent -= 2;
+ js_printf(jp, "\t%s:\n", js_default_str);
+ jp->indent += 2;
+ }
+ if (!Decompile(ss, pc + off, off2 - off, JSOP_NOP))
+ return JS_FALSE;
+ jp->indent -= 4;
+
+ /* Re-balance as if last JSOP_CASE or JSOP_DEFAULT mismatched. */
+ if (isCondSwitch)
+ ++ss->top;
+ }
+ }
+
+ if (defaultOffset == switchLength) {
+ jp->indent += 2;
+ js_printf(jp, "\t%s:;\n", js_default_str);
+ jp->indent -= 2;
+ }
+ js_printf(jp, "\t}\n");
+
+ /* By the end of a JSOP_CONDSWITCH, the discriminant has been popped. */
+ if (isCondSwitch)
+ --ss->top;
+ return JS_TRUE;
+}
+
+#define LOCAL_ASSERT_CUSTOM(expr, BAD_EXIT) \
+ JS_BEGIN_MACRO \
+ JS_ASSERT(expr); \
+ if (!(expr)) { BAD_EXIT; } \
+ JS_END_MACRO
+
+#define LOCAL_ASSERT_RV(expr, rv) \
+ LOCAL_ASSERT_CUSTOM(expr, return (rv))
+
+static JSAtom *
+GetArgOrVarAtom(JSPrinter *jp, uintN slot)
+{
+ JSAtom *name;
+
+ LOCAL_ASSERT_RV(jp->fun, NULL);
+ LOCAL_ASSERT_RV(slot < (uintN) JS_GET_LOCAL_NAME_COUNT(jp->fun), NULL);
+ name = JS_LOCAL_NAME_TO_ATOM(jp->localNames[slot]);
+#if !JS_HAS_DESTRUCTURING
+ LOCAL_ASSERT_RV(name, NULL);
+#endif
+ return name;
+}
+
+const char *
+GetLocal(SprintStack *ss, jsint i)
+{
+ ptrdiff_t off;
+ JSContext *cx;
+ JSScript *script;
+ jsatomid j, n;
+ JSAtom *atom;
+ JSObject *obj;
+ jsint depth, count;
+ JSScopeProperty *sprop;
+ const char *rval;
+
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, "")
+
+ off = ss->offsets[i];
+ if (off >= 0)
+ return OFF2STR(&ss->sprinter, off);
+
+ /*
+ * We must be called from js_DecompileValueGenerator (via Decompile) when
+ * dereferencing a local that's undefined or null. Search script->objects
+ * for the block containing this local by its stack index, i.
+ */
+ cx = ss->sprinter.context;
+ script = ss->printer->script;
+ LOCAL_ASSERT(script->objectsOffset != 0);
+ for (j = 0, n = JS_SCRIPT_OBJECTS(script)->length; ; j++) {
+ LOCAL_ASSERT(j < n);
+ JS_GET_SCRIPT_OBJECT(script, j, obj);
+ if (OBJ_GET_CLASS(cx, obj) == &js_BlockClass) {
+ depth = OBJ_BLOCK_DEPTH(cx, obj);
+ count = OBJ_BLOCK_COUNT(cx, obj);
+ if ((jsuint)(i - depth) < (jsuint)count)
+ break;
+ }
+ }
+
+ i -= depth;
+ for (sprop = OBJ_SCOPE(obj)->lastProp; sprop; sprop = sprop->parent) {
+ if (sprop->shortid == i)
+ break;
+ }
+
+ LOCAL_ASSERT(sprop && JSID_IS_ATOM(sprop->id));
+ atom = JSID_TO_ATOM(sprop->id);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ return rval;
+
+#undef LOCAL_ASSERT
+}
+
+static JSBool
+IsVarSlot(JSPrinter *jp, jsbytecode *pc, jsint *indexp)
+{
+ uintN slot;
+
+ slot = GET_SLOTNO(pc);
+ if (slot < jp->script->nfixed) {
+ /* The slot refers to a variable with name stored in jp->localNames. */
+ *indexp = jp->fun->nargs + slot;
+ return JS_TRUE;
+ }
+
+ /* We have a local which index is relative to the stack base. */
+ slot -= jp->script->nfixed;
+ JS_ASSERT(slot < StackDepth(jp->script));
+ *indexp = slot;
+ return JS_FALSE;
+}
+
+#if JS_HAS_DESTRUCTURING
+
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, NULL)
+#define LOAD_OP_DATA(pc) (oplen = (cs = &js_CodeSpec[op=(JSOp)*pc])->length)
+
+static jsbytecode *
+DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc);
+
+static jsbytecode *
+DecompileDestructuringLHS(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
+ JSBool *hole)
+{
+ JSContext *cx;
+ JSPrinter *jp;
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN oplen;
+ jsint i;
+ const char *lval, *xval;
+ ptrdiff_t todo;
+ JSAtom *atom;
+
+ *hole = JS_FALSE;
+ cx = ss->sprinter.context;
+ jp = ss->printer;
+ LOAD_OP_DATA(pc);
+
+ switch (op) {
+ case JSOP_POP:
+ *hole = JS_TRUE;
+ todo = SprintPut(&ss->sprinter, ", ", 2);
+ break;
+
+ case JSOP_DUP:
+ pc = DecompileDestructuring(ss, pc, endpc);
+ if (!pc)
+ return NULL;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ lval = PopStr(ss, JSOP_NOP);
+ todo = SprintCString(&ss->sprinter, lval);
+ if (op == JSOP_POPN)
+ return pc;
+ LOCAL_ASSERT(*pc == JSOP_POP);
+ break;
+
+ case JSOP_SETARG:
+ case JSOP_SETGVAR:
+ case JSOP_SETLOCAL:
+ LOCAL_ASSERT(pc[oplen] == JSOP_POP || pc[oplen] == JSOP_POPN);
+ /* FALL THROUGH */
+
+ case JSOP_SETLOCALPOP:
+ atom = NULL;
+ lval = NULL;
+ if (op == JSOP_SETARG) {
+ atom = GetArgOrVarAtom(jp, GET_SLOTNO(pc));
+ LOCAL_ASSERT(atom);
+ } else if (op == JSOP_SETGVAR) {
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
+ } else if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ } else {
+ lval = GetLocal(ss, i);
+ }
+ if (atom)
+ lval = js_AtomToPrintableString(cx, atom);
+ LOCAL_ASSERT(lval);
+ todo = SprintCString(&ss->sprinter, lval);
+ if (op != JSOP_SETLOCALPOP) {
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ if (op == JSOP_POPN)
+ return pc;
+ LOCAL_ASSERT(op == JSOP_POP);
+ }
+ break;
+
+ default:
+ /*
+ * We may need to auto-parenthesize the left-most value decompiled
+ * here, so add back PAREN_SLOP temporarily. Then decompile until the
+ * opcode that would reduce the stack depth to (ss->top-1), which we
+ * pass to Decompile encoded as -(ss->top-1) - 1 or just -ss->top for
+ * the nb parameter.
+ */
+ todo = ss->sprinter.offset;
+ ss->sprinter.offset = todo + PAREN_SLOP;
+ pc = Decompile(ss, pc, -((intN)ss->top), JSOP_NOP);
+ if (!pc)
+ return NULL;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ LOCAL_ASSERT(op == JSOP_ENUMELEM || op == JSOP_ENUMCONSTELEM);
+ xval = PopStr(ss, JSOP_NOP);
+ lval = PopStr(ss, JSOP_GETPROP);
+ ss->sprinter.offset = todo;
+ if (*lval == '\0') {
+ /* lval is from JSOP_BINDNAME, so just print xval. */
+ todo = SprintCString(&ss->sprinter, xval);
+ } else if (*xval == '\0') {
+ /* xval is from JSOP_SETCALL or JSOP_BINDXMLNAME, print lval. */
+ todo = SprintCString(&ss->sprinter, lval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(ss->opcodes[ss->top+1]) == JOF_XMLNAME)
+ ? "%s.%s"
+ : "%s[%s]",
+ lval, xval);
+ }
+ break;
+ }
+
+ if (todo < 0)
+ return NULL;
+
+ LOCAL_ASSERT(pc < endpc);
+ pc += oplen;
+ return pc;
+}
+
+/*
+ * Starting with a SRC_DESTRUCT-annotated JSOP_DUP, decompile a destructuring
+ * left-hand side object or array initialiser, including nested destructuring
+ * initialisers. On successful return, the decompilation will be pushed on ss
+ * and the return value will point to the POP or GROUP bytecode following the
+ * destructuring expression.
+ *
+ * At any point, if pc is equal to endpc and would otherwise advance, we stop
+ * immediately and return endpc.
+ */
+static jsbytecode *
+DecompileDestructuring(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc)
+{
+ ptrdiff_t head;
+ JSContext *cx;
+ JSPrinter *jp;
+ JSOp op, saveop;
+ const JSCodeSpec *cs;
+ uintN oplen;
+ jsint i, lasti;
+ jsdouble d;
+ const char *lval;
+ JSAtom *atom;
+ jssrcnote *sn;
+ JSString *str;
+ JSBool hole;
+
+ LOCAL_ASSERT(*pc == JSOP_DUP);
+ pc += JSOP_DUP_LENGTH;
+
+ /*
+ * Set head so we can rewrite '[' to '{' as needed. Back up PAREN_SLOP
+ * chars so the destructuring decompilation accumulates contiguously in
+ * ss->sprinter starting with "[".
+ */
+ head = SprintPut(&ss->sprinter, "[", 1);
+ if (head < 0 || !PushOff(ss, head, JSOP_NOP))
+ return NULL;
+ ss->sprinter.offset -= PAREN_SLOP;
+ LOCAL_ASSERT(head == ss->sprinter.offset - 1);
+ LOCAL_ASSERT(*OFF2STR(&ss->sprinter, head) == '[');
+
+ cx = ss->sprinter.context;
+ jp = ss->printer;
+ lasti = -1;
+
+ while (pc < endpc) {
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ ptrdiff_t nameoff = -1;
+#endif
+
+ LOAD_OP_DATA(pc);
+ saveop = op;
+
+ switch (op) {
+ case JSOP_POP:
+ pc += oplen;
+ goto out;
+
+ /* Handle the optimized number-pushing opcodes. */
+ case JSOP_ZERO: d = i = 0; goto do_getelem;
+ case JSOP_ONE: d = i = 1; goto do_getelem;
+ case JSOP_UINT16: d = i = GET_UINT16(pc); goto do_getelem;
+ case JSOP_UINT24: d = i = GET_UINT24(pc); goto do_getelem;
+ case JSOP_INT8: d = i = GET_INT8(pc); goto do_getelem;
+ case JSOP_INT32: d = i = GET_INT32(pc); goto do_getelem;
+
+ case JSOP_DOUBLE:
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
+ d = *ATOM_TO_DOUBLE(atom);
+ LOCAL_ASSERT(JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d));
+ i = (jsint)d;
+
+ do_getelem:
+ sn = js_GetSrcNote(jp->script, pc);
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ LOCAL_ASSERT(op == JSOP_GETELEM);
+
+ /* Distinguish object from array by opcode or source note. */
+ if (sn && SN_TYPE(sn) == SRC_INITPROP) {
+ *OFF2STR(&ss->sprinter, head) = '{';
+ if (Sprint(&ss->sprinter, "%g: ", d) < 0)
+ return NULL;
+ } else {
+ /* Sanity check for the gnarly control flow above. */
+ LOCAL_ASSERT(i == d);
+
+ /* Fill in any holes (holes at the end don't matter). */
+ while (++lasti < i) {
+ if (SprintPut(&ss->sprinter, ", ", 2) < 0)
+ return NULL;
+ }
+ }
+ break;
+
+ case JSOP_LENGTH:
+ atom = cx->runtime->atomState.lengthAtom;
+ goto do_destructure_atom;
+
+ case JSOP_CALLPROP:
+ case JSOP_GETPROP:
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, 0, atom);
+ do_destructure_atom:
+ *OFF2STR(&ss->sprinter, head) = '{';
+ str = ATOM_TO_STRING(atom);
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ nameoff = ss->sprinter.offset;
+#endif
+ if (!QuoteString(&ss->sprinter, str,
+ js_IsIdentifier(str) ? 0 : (jschar)'\'')) {
+ return NULL;
+ }
+ if (SprintPut(&ss->sprinter, ": ", 2) < 0)
+ return NULL;
+ break;
+
+ default:
+ LOCAL_ASSERT(0);
+ }
+
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+
+ /*
+ * Decompile the left-hand side expression whose bytecode starts at pc
+ * and continues for a bounded number of bytecodes or stack operations
+ * (and which in any event stops before endpc).
+ */
+ pc = DecompileDestructuringLHS(ss, pc, endpc, &hole);
+ if (!pc)
+ return NULL;
+
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (nameoff >= 0) {
+ ptrdiff_t offset, initlen;
+
+ offset = ss->sprinter.offset;
+ LOCAL_ASSERT(*OFF2STR(&ss->sprinter, offset) == '\0');
+ initlen = offset - nameoff;
+ LOCAL_ASSERT(initlen >= 4);
+
+ /* Early check to rule out odd "name: lval" length. */
+ if (((size_t)initlen & 1) == 0) {
+ size_t namelen;
+ const char *name;
+
+ /*
+ * Even "name: lval" string length: check for "x: x" and the
+ * like, and apply the shorthand if we can.
+ */
+ namelen = (size_t)(initlen - 2) >> 1;
+ name = OFF2STR(&ss->sprinter, nameoff);
+ if (!strncmp(name + namelen, ": ", 2) &&
+ !strncmp(name, name + namelen + 2, namelen)) {
+ offset -= namelen + 2;
+ *OFF2STR(&ss->sprinter, offset) = '\0';
+ ss->sprinter.offset = offset;
+ }
+ }
+ }
+#endif
+
+ if (pc == endpc || *pc != JSOP_DUP)
+ break;
+
+ /*
+ * Check for SRC_DESTRUCT on this JSOP_DUP, which would mean another
+ * destructuring initialiser abuts this one, and we should stop. This
+ * happens with source of the form '[a] = [b] = c'.
+ */
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_DESTRUCT)
+ break;
+
+ if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
+ return NULL;
+
+ pc += JSOP_DUP_LENGTH;
+ }
+
+out:
+ lval = OFF2STR(&ss->sprinter, head);
+ if (SprintPut(&ss->sprinter, (*lval == '[') ? "]" : "}", 1) < 0)
+ return NULL;
+ return pc;
+}
+
+static jsbytecode *
+DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
+ jssrcnote *sn, ptrdiff_t *todop)
+{
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN oplen, start, end, i;
+ ptrdiff_t todo;
+ JSBool hole;
+ const char *rval;
+
+ LOAD_OP_DATA(pc);
+ LOCAL_ASSERT(op == JSOP_PUSH || op == JSOP_GETLOCAL);
+
+ todo = Sprint(&ss->sprinter, "%s[", VarPrefix(sn));
+ if (todo < 0 || !PushOff(ss, todo, JSOP_NOP))
+ return NULL;
+ ss->sprinter.offset -= PAREN_SLOP;
+
+ for (;;) {
+ pc += oplen;
+ if (pc == endpc)
+ return pc;
+ pc = DecompileDestructuringLHS(ss, pc, endpc, &hole);
+ if (!pc)
+ return NULL;
+ if (pc == endpc)
+ return pc;
+ LOAD_OP_DATA(pc);
+ if (op != JSOP_PUSH && op != JSOP_GETLOCAL)
+ break;
+ if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
+ return NULL;
+ }
+
+ LOCAL_ASSERT(op == JSOP_POPN);
+ if (SprintPut(&ss->sprinter, "] = [", 5) < 0)
+ return NULL;
+
+ end = ss->top - 1;
+ start = end - GET_UINT16(pc);
+ for (i = start; i < end; i++) {
+ rval = GetStr(ss, i);
+ if (Sprint(&ss->sprinter,
+ (i == start) ? "%s" : ", %s",
+ (i == end - 1 && *rval == '\0') ? ", " : rval) < 0) {
+ return NULL;
+ }
+ }
+
+ if (SprintPut(&ss->sprinter, "]", 1) < 0)
+ return NULL;
+ ss->sprinter.offset = ss->offsets[i];
+ ss->top = start;
+ *todop = todo;
+ return pc;
+}
+
+#undef LOCAL_ASSERT
+#undef LOAD_OP_DATA
+
+#endif /* JS_HAS_DESTRUCTURING */
+
+static JSBool
+InitSprintStack(JSContext *cx, SprintStack *ss, JSPrinter *jp, uintN depth)
+{
+ size_t offsetsz, opcodesz;
+ void *space;
+
+ INIT_SPRINTER(cx, &ss->sprinter, &cx->tempPool, PAREN_SLOP);
+
+ /* Allocate the parallel (to avoid padding) offset and opcode stacks. */
+ offsetsz = depth * sizeof(ptrdiff_t);
+ opcodesz = depth * sizeof(jsbytecode);
+ JS_ARENA_ALLOCATE(space, &cx->tempPool, offsetsz + opcodesz);
+ if (!space) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ ss->offsets = (ptrdiff_t *) space;
+ ss->opcodes = (jsbytecode *) ((char *)space + offsetsz);
+
+ ss->top = ss->inArrayInit = 0;
+ ss->inGenExp = JS_FALSE;
+ ss->printer = jp;
+ return JS_TRUE;
+}
+
+/*
+ * If nb is non-negative, decompile nb bytecodes starting at pc. Otherwise
+ * the decompiler starts at pc and continues until it reaches an opcode for
+ * which decompiling would result in the stack depth equaling -(nb + 1).
+ *
+ * The nextop parameter is either JSOP_NOP or the "next" opcode in order of
+ * abstract interpretation (not necessarily physically next in a bytecode
+ * vector). So nextop is JSOP_POP for the last operand in a comma expression,
+ * or JSOP_AND for the right operand of &&.
+ */
+static jsbytecode *
+Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
+{
+ JSContext *cx;
+ JSPrinter *jp, *jp2;
+ jsbytecode *startpc, *endpc, *pc2, *done;
+ ptrdiff_t tail, todo, len, oplen, cond, next;
+ JSOp op, lastop, saveop;
+ const JSCodeSpec *cs;
+ jssrcnote *sn, *sn2;
+ const char *lval, *rval, *xval, *fmt, *token;
+ jsint i, argc;
+ char **argv;
+ JSAtom *atom;
+ JSObject *obj;
+ JSFunction *fun;
+ JSString *str;
+ JSBool ok;
+#if JS_HAS_XML_SUPPORT
+ JSBool foreach, inXML, quoteAttr;
+#else
+#define inXML JS_FALSE
+#endif
+ jsval val;
+
+ static const char exception_cookie[] = "/*EXCEPTION*/";
+ static const char retsub_pc_cookie[] = "/*RETSUB_PC*/";
+ static const char iter_cookie[] = "/*ITER*/";
+ static const char forelem_cookie[] = "/*FORELEM*/";
+ static const char with_cookie[] = "/*WITH*/";
+ static const char dot_format[] = "%s.%s";
+ static const char index_format[] = "%s[%s]";
+ static const char predot_format[] = "%s%s.%s";
+ static const char postdot_format[] = "%s.%s%s";
+ static const char preindex_format[] = "%s%s[%s]";
+ static const char postindex_format[] = "%s[%s]%s";
+ static const char ss_format[] = "%s%s";
+ static const char sss_format[] = "%s%s%s";
+
+ /* Argument and variables decompilation uses the following to share code. */
+ JS_STATIC_ASSERT(ARGNO_LEN == SLOTNO_LEN);
+
+/*
+ * Local macros
+ */
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, NULL)
+#define DECOMPILE_CODE(pc,nb) if (!Decompile(ss, pc, nb, JSOP_NOP)) return NULL
+#define NEXT_OP(pc) (((pc) + (len) == endpc) ? nextop : pc[len])
+#define TOP_STR() GetStr(ss, ss->top - 1)
+#define POP_STR() PopStr(ss, op)
+#define POP_STR_PREC(prec) PopStrPrec(ss, prec)
+
+/*
+ * Pop a condition expression for if/for/while. JSOP_IFEQ's precedence forces
+ * extra parens around assignment, which avoids a strict-mode warning.
+ */
+#define POP_COND_STR() \
+ PopStr(ss, (js_CodeSpec[ss->opcodes[ss->top - 1]].format & JOF_SET) \
+ ? JSOP_IFEQ \
+ : JSOP_NOP)
+
+/*
+ * Callers know that ATOM_IS_STRING(atom), and we leave it to the optimizer to
+ * common ATOM_TO_STRING(atom) here and near the call sites.
+ */
+#define ATOM_IS_IDENTIFIER(atom) js_IsIdentifier(ATOM_TO_STRING(atom))
+#define ATOM_IS_KEYWORD(atom) \
+ (js_CheckKeyword(JSSTRING_CHARS(ATOM_TO_STRING(atom)), \
+ JSSTRING_LENGTH(ATOM_TO_STRING(atom))) != TOK_EOF)
+
+/*
+ * Given an atom already fetched from jp->script's atom map, quote/escape its
+ * string appropriately into rval, and select fmt from the quoted and unquoted
+ * alternatives.
+ */
+#define GET_QUOTE_AND_FMT(qfmt, ufmt, rval) \
+ JS_BEGIN_MACRO \
+ jschar quote_; \
+ if (!ATOM_IS_IDENTIFIER(atom)) { \
+ quote_ = '\''; \
+ fmt = qfmt; \
+ } else { \
+ quote_ = 0; \
+ fmt = ufmt; \
+ } \
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), quote_); \
+ if (!rval) \
+ return NULL; \
+ JS_END_MACRO
+
+#define LOAD_ATOM(PCOFF) \
+ GET_ATOM_FROM_BYTECODE(jp->script, pc, PCOFF, atom)
+
+#define LOAD_OBJECT(PCOFF) \
+ GET_OBJECT_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
+
+#define LOAD_FUNCTION(PCOFF) \
+ GET_FUNCTION_FROM_BYTECODE(jp->script, pc, PCOFF, fun)
+
+#define LOAD_REGEXP(PCOFF) \
+ GET_REGEXP_FROM_BYTECODE(jp->script, pc, PCOFF, obj)
+
+#define GET_SOURCE_NOTE_ATOM(sn, atom) \
+ JS_BEGIN_MACRO \
+ jsatomid atomIndex_ = (jsatomid) js_GetSrcNoteOffset((sn), 0); \
+ \
+ LOCAL_ASSERT(atomIndex_ < jp->script->atomMap.length); \
+ (atom) = jp->script->atomMap.vector[atomIndex_]; \
+ JS_END_MACRO
+
+/*
+ * Get atom from jp->script's atom map, quote/escape its string appropriately
+ * into rval, and select fmt from the quoted and unquoted alternatives.
+ */
+#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval) \
+ JS_BEGIN_MACRO \
+ LOAD_ATOM(0); \
+ GET_QUOTE_AND_FMT(qfmt, ufmt, rval); \
+ JS_END_MACRO
+
+/*
+ * Per spec, new x(y).z means (new x(y))).z. For example new (x(y).z) must
+ * decompile with the constructor parenthesized, but new x.z should not. The
+ * normal rules give x(y).z and x.z identical precedence: both are produced by
+ * JSOP_GETPROP.
+ *
+ * Therefore, we need to know in case JSOP_NEW whether the constructor
+ * expression contains any unparenthesized function calls. So when building a
+ * MemberExpression or CallExpression, we set ss->opcodes[n] to JSOP_CALL if
+ * this is true. x(y).z gets JSOP_CALL, not JSOP_GETPROP.
+ */
+#define PROPAGATE_CALLNESS() \
+ JS_BEGIN_MACRO \
+ if (ss->opcodes[ss->top - 1] == JSOP_CALL) \
+ saveop = JSOP_CALL; \
+ JS_END_MACRO
+
+ cx = ss->sprinter.context;
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ jp = ss->printer;
+ startpc = pc;
+ endpc = (nb < 0) ? jp->script->code + jp->script->length : pc + nb;
+ tail = -1;
+ todo = -2; /* NB: different from Sprint() error return. */
+ saveop = JSOP_NOP;
+ sn = NULL;
+ rval = NULL;
+#if JS_HAS_XML_SUPPORT
+ foreach = inXML = quoteAttr = JS_FALSE;
+#endif
+
+ while (nb < 0 || pc < endpc) {
+ /*
+ * Move saveop to lastop so prefixed bytecodes can take special action
+ * while sharing maximal code. Set op and saveop to the new bytecode,
+ * use op in POP_STR to trigger automatic parenthesization, but push
+ * saveop at the bottom of the loop if this op pushes. Thus op may be
+ * set to nop or otherwise mutated to suppress auto-parens.
+ */
+ lastop = saveop;
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ if (cs->format & JOF_INDEXBASE) {
+ /*
+ * The decompiler uses js_GetIndexFromBytecode to get atoms and
+ * objects and ignores these suffix/prefix bytecodes, thus
+ * simplifying code that must process JSOP_GETTER/JSOP_SETTER
+ * prefixes.
+ */
+ pc += cs->length;
+ if (pc >= endpc)
+ break;
+ op = (JSOp) *pc;
+ cs = &js_CodeSpec[op];
+ }
+ saveop = op;
+ len = oplen = cs->length;
+
+ if (nb < 0 && -(nb + 1) == (intN)ss->top - cs->nuses + cs->ndefs)
+ return pc;
+
+ /*
+ * Save source literal associated with JS now before the following
+ * rewrite changes op. See bug 380197.
+ */
+ token = CodeToken[op];
+
+ if (pc + oplen == jp->dvgfence) {
+ JSStackFrame *fp;
+ uint32 format, mode, type;
+
+ /*
+ * Rewrite non-get ops to their "get" format if the error is in
+ * the bytecode at pc, so we don't decompile more than the error
+ * expression.
+ */
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
+ format = cs->format;
+ if (((fp && fp->regs && pc == fp->regs->pc) ||
+ (pc == startpc && cs->nuses != 0)) &&
+ format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_FOR|JOF_VARPROP)) {
+ mode = JOF_MODE(format);
+ if (mode == JOF_NAME) {
+ /*
+ * JOF_NAME does not imply JOF_ATOM, so we must check for
+ * the QARG and QVAR format types, and translate those to
+ * JSOP_GETARG or JSOP_GETLOCAL appropriately, instead of
+ * to JSOP_NAME.
+ */
+ type = JOF_TYPE(format);
+ op = (type == JOF_QARG)
+ ? JSOP_GETARG
+ : (type == JOF_LOCAL)
+ ? JSOP_GETLOCAL
+ : JSOP_NAME;
+
+ i = cs->nuses - js_CodeSpec[op].nuses;
+ while (--i >= 0)
+ PopOff(ss, JSOP_NOP);
+ } else {
+ /*
+ * We must replace the faulting pc's bytecode with a
+ * corresponding JSOP_GET* code. For JSOP_SET{PROP,ELEM},
+ * we must use the "2nd" form of JSOP_GET{PROP,ELEM}, to
+ * throw away the assignment op's right-hand operand and
+ * decompile it as if it were a GET of its left-hand
+ * operand.
+ */
+ if (mode == JOF_PROP) {
+ op = (JSOp) ((format & JOF_SET)
+ ? JSOP_GETPROP2
+ : JSOP_GETPROP);
+ } else if (mode == JOF_ELEM) {
+ op = (JSOp) ((format & JOF_SET)
+ ? JSOP_GETELEM2
+ : JSOP_GETELEM);
+ } else {
+ /*
+ * Unknown mode (including mode 0) means that op is
+ * uncategorized for our purposes, so we must write
+ * per-op special case code here.
+ */
+ switch (op) {
+ case JSOP_ENUMELEM:
+ case JSOP_ENUMCONSTELEM:
+ op = JSOP_GETELEM;
+ break;
+#if JS_HAS_LVALUE_RETURN
+ case JSOP_SETCALL:
+ op = JSOP_CALL;
+ break;
+#endif
+ case JSOP_GETTHISPROP:
+ /*
+ * NB: JSOP_GETTHISPROP can't fail due to |this|
+ * being null or undefined at runtime (beware that
+ * this may change for ES4). Therefore any error
+ * resulting from this op must be due to the value
+ * of the property accessed via |this|, so do not
+ * rewrite op to JSOP_THIS.
+ *
+ * The next two cases should not change op if
+ * js_DecompileValueGenerator was called from the
+ * the property getter. They should rewrite only
+ * if the base object in the arg/var/local is null
+ * or undefined. FIXME: bug 431569.
+ */
+ break;
+ case JSOP_GETARGPROP:
+ op = JSOP_GETARG;
+ break;
+ case JSOP_GETLOCALPROP:
+ op = JSOP_GETLOCAL;
+ break;
+ default:
+ LOCAL_ASSERT(0);
+ }
+ }
+ }
+ }
+
+ saveop = op;
+ if (op >= JSOP_LIMIT) {
+ switch (op) {
+ case JSOP_GETPROP2:
+ saveop = JSOP_GETPROP;
+ break;
+ case JSOP_GETELEM2:
+ saveop = JSOP_GETELEM;
+ break;
+ default:;
+ }
+ }
+ LOCAL_ASSERT(js_CodeSpec[saveop].length == oplen ||
+ JOF_TYPE(format) == JOF_SLOTATOM);
+
+ jp->dvgfence = NULL;
+ }
+
+ if (token) {
+ switch (cs->nuses) {
+ case 2:
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
+ /*
+ * Avoid over-parenthesizing y in x op= y based on its
+ * expansion: x = x op y (replace y by z = w to see the
+ * problem).
+ */
+ op = (JSOp) pc[oplen];
+ rval = POP_STR();
+ lval = POP_STR();
+ /* Print only the right operand of the assignment-op. */
+ todo = SprintCString(&ss->sprinter, rval);
+ op = saveop;
+ } else if (!inXML) {
+ rval = POP_STR_PREC(cs->prec + !!(cs->format & JOF_LEFTASSOC));
+ lval = POP_STR_PREC(cs->prec + !(cs->format & JOF_LEFTASSOC));
+ todo = Sprint(&ss->sprinter, "%s %s %s",
+ lval, token, rval);
+ } else {
+ /* In XML, just concatenate the two operands. */
+ LOCAL_ASSERT(op == JSOP_ADD);
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, ss_format, lval, rval);
+ }
+ break;
+
+ case 1:
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, ss_format, token, rval);
+ break;
+
+ case 0:
+ todo = SprintCString(&ss->sprinter, token);
+ break;
+
+ default:
+ todo = -2;
+ break;
+ }
+ } else {
+ switch (op) {
+ case JSOP_NOP:
+ /*
+ * Check for a do-while loop, a for-loop with an empty
+ * initializer part, a labeled statement, a function
+ * definition, or try/finally.
+ */
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_WHILE:
+ ++pc;
+ tail = js_GetSrcNoteOffset(sn, 0) - 1;
+ LOCAL_ASSERT(pc[tail] == JSOP_IFNE ||
+ pc[tail] == JSOP_IFNEX);
+ js_printf(jp, "\tdo {\n");
+ jp->indent += 4;
+ DECOMPILE_CODE(pc, tail);
+ jp->indent -= 4;
+ js_printf(jp, "\t} while (%s);\n", POP_COND_STR());
+ pc += tail;
+ len = js_CodeSpec[*pc].length;
+ todo = -2;
+ break;
+
+ case SRC_FOR:
+ rval = "";
+
+ do_forloop:
+ JS_ASSERT(SN_TYPE(sn) == SRC_FOR);
+
+ /* Skip the JSOP_NOP or JSOP_POP bytecode. */
+ pc += JSOP_NOP_LENGTH;
+
+ /* Get the cond, next, and loop-closing tail offsets. */
+ cond = js_GetSrcNoteOffset(sn, 0);
+ next = js_GetSrcNoteOffset(sn, 1);
+ tail = js_GetSrcNoteOffset(sn, 2);
+
+ /*
+ * If this loop has a condition, then pc points at a goto
+ * targeting the condition.
+ */
+ pc2 = pc;
+ if (cond != tail) {
+ LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
+ pc2 += (*pc == JSOP_GOTO) ? JSOP_GOTO_LENGTH : JSOP_GOTOX_LENGTH;
+ }
+ LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == pc2 - pc);
+
+ /* Print the keyword and the possibly empty init-part. */
+ js_printf(jp, "\tfor (%s;", rval);
+
+ if (cond != tail) {
+ /* Decompile the loop condition. */
+ DECOMPILE_CODE(pc + cond, tail - cond);
+ js_printf(jp, " %s", POP_STR());
+ }
+
+ /* Need a semicolon whether or not there was a cond. */
+ js_puts(jp, ";");
+
+ if (next != cond) {
+ /*
+ * Decompile the loop updater. It may end in a JSOP_POP
+ * that we skip; or in a JSOP_POPN that we do not skip,
+ * followed by a JSOP_NOP (skipped as if it's a POP).
+ * We cope with the difference between these two cases
+ * by checking for stack imbalance and popping if there
+ * is an rval.
+ */
+ uintN saveTop = ss->top;
+
+ DECOMPILE_CODE(pc + next, cond - next - JSOP_POP_LENGTH);
+ LOCAL_ASSERT(ss->top - saveTop <= 1U);
+ rval = (ss->top == saveTop)
+ ? ss->sprinter.base + ss->sprinter.offset
+ : POP_STR();
+ js_printf(jp, " %s", rval);
+ }
+
+ /* Do the loop body. */
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ next -= pc2 - pc;
+ DECOMPILE_CODE(pc2, next);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+
+ /* Set len so pc skips over the entire loop. */
+ len = tail + js_CodeSpec[pc[tail]].length;
+ break;
+
+ case SRC_LABEL:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ jp->indent -= 4;
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\t%s:\n", rval);
+ jp->indent += 4;
+ break;
+
+ case SRC_LABELBRACE:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\t%s: {\n", rval);
+ jp->indent += 4;
+ break;
+
+ case SRC_ENDBRACE:
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+
+ case SRC_FUNCDEF:
+ JS_GET_SCRIPT_FUNCTION(jp->script,
+ js_GetSrcNoteOffset(sn, 0),
+ fun);
+ do_function:
+ js_puts(jp, "\n");
+ jp2 = JS_NEW_PRINTER(cx, "nested_function", fun,
+ jp->indent, jp->pretty);
+ if (!jp2)
+ return NULL;
+ ok = js_DecompileFunction(jp2);
+ if (ok && jp2->sprinter.base)
+ js_puts(jp, jp2->sprinter.base);
+ js_DestroyPrinter(jp2);
+ if (!ok)
+ return NULL;
+ js_puts(jp, "\n\n");
+ break;
+
+ case SRC_BRACE:
+ js_printf(jp, "\t{\n");
+ jp->indent += 4;
+ len = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+
+ default:;
+ }
+ break;
+
+ case JSOP_PUSH:
+#if JS_HAS_DESTRUCTURING
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+ pc = DecompileGroupAssignment(ss, pc, endpc, sn, &todo);
+ if (!pc)
+ return NULL;
+ LOCAL_ASSERT(*pc == JSOP_POPN);
+ len = oplen = JSOP_POPN_LENGTH;
+ goto end_groupassignment;
+ }
+#endif
+ /* FALL THROUGH */
+
+ case JSOP_BINDNAME:
+ todo = Sprint(&ss->sprinter, "");
+ break;
+
+ case JSOP_TRY:
+ js_printf(jp, "\ttry {\n");
+ jp->indent += 4;
+ todo = -2;
+ break;
+
+ case JSOP_FINALLY:
+ jp->indent -= 4;
+ js_printf(jp, "\t} finally {\n");
+ jp->indent += 4;
+
+ /*
+ * We push push the pair of exception/restsub cookies to
+ * simulate the effects [gosub] or control transfer during
+ * exception capturing on the stack.
+ */
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 || !PushOff(ss, todo, op))
+ return NULL;
+ todo = Sprint(&ss->sprinter, retsub_pc_cookie);
+ break;
+
+ case JSOP_RETSUB:
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, retsub_pc_cookie) == 0);
+ lval = POP_STR();
+ LOCAL_ASSERT(strcmp(lval, exception_cookie) == 0);
+ todo = -2;
+ break;
+
+ case JSOP_GOSUB:
+ case JSOP_GOSUBX:
+ /*
+ * JSOP_GOSUB and GOSUBX have no effect on the decompiler's
+ * string stack because the next op in bytecode order finds
+ * the stack balanced by a JSOP_RETSUB executed elsewhere.
+ */
+ todo = -2;
+ break;
+
+ case JSOP_POPN:
+ {
+ uintN newtop, oldtop;
+
+ /*
+ * The compiler models operand stack depth and fixes the stack
+ * pointer on entry to a catch clause based on its depth model.
+ * The decompiler must match the code generator's model, which
+ * is why JSOP_FINALLY pushes a cookie that JSOP_RETSUB pops.
+ */
+ oldtop = ss->top;
+ newtop = oldtop - GET_UINT16(pc);
+ LOCAL_ASSERT(newtop <= oldtop);
+ todo = -2;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+#if JS_HAS_DESTRUCTURING
+ if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+ todo = Sprint(&ss->sprinter, "%s[] = [",
+ VarPrefix(sn));
+ if (todo < 0)
+ return NULL;
+ for (uintN i = newtop; i < oldtop; i++) {
+ rval = OFF2STR(&ss->sprinter, ss->offsets[i]);
+ if (Sprint(&ss->sprinter, ss_format,
+ (i == newtop) ? "" : ", ",
+ (i == oldtop - 1 && *rval == '\0')
+ ? ", " : rval) < 0) {
+ return NULL;
+ }
+ }
+ if (SprintPut(&ss->sprinter, "]", 1) < 0)
+ return NULL;
+
+ /*
+ * If this is an empty group assignment, we have no stack
+ * budget into which we can push our result string. Adjust
+ * ss->sprinter.offset so that our consumer can find the
+ * empty group assignment decompilation.
+ */
+ if (newtop == oldtop) {
+ ss->sprinter.offset = todo;
+ } else {
+ /*
+ * Kill newtop before the end_groupassignment: label by
+ * retracting/popping early. Control will either jump
+ * to do_forloop: or do_letheadbody: or else break from
+ * our case JSOP_POPN: after the switch (*pc2) below.
+ */
+ LOCAL_ASSERT(newtop < oldtop);
+ ss->sprinter.offset = GetOff(ss, newtop);
+ ss->top = newtop;
+ }
+
+ end_groupassignment:
+ LOCAL_ASSERT(*pc == JSOP_POPN);
+
+ /*
+ * Thread directly to the next opcode if we can, to handle
+ * the special cases of a group assignment in the first or
+ * last part of a for(;;) loop head, or in a let block or
+ * expression head.
+ *
+ * NB: todo at this point indexes space in ss->sprinter
+ * that is liable to be overwritten. The code below knows
+ * exactly how long rval lives, or else copies it down via
+ * SprintCString.
+ */
+ rval = OFF2STR(&ss->sprinter, todo);
+ todo = -2;
+ pc2 = pc + oplen;
+ if (*pc2 == JSOP_NOP) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ if (sn) {
+ if (SN_TYPE(sn) == SRC_FOR) {
+ op = JSOP_NOP;
+ pc = pc2;
+ goto do_forloop;
+ }
+
+ if (SN_TYPE(sn) == SRC_DECL) {
+ if (ss->top == StackDepth(jp->script)) {
+ /*
+ * This must be an empty destructuring
+ * in the head of a let whose body block
+ * is also empty.
+ */
+ pc = pc2 + JSOP_NOP_LENGTH;
+ len = js_GetSrcNoteOffset(sn, 0);
+ LOCAL_ASSERT(pc[len] == JSOP_LEAVEBLOCK);
+ js_printf(jp, "\tlet (%s) {\n", rval);
+ js_printf(jp, "\t}\n");
+ break;
+ }
+ todo = SprintCString(&ss->sprinter, rval);
+ if (todo < 0 || !PushOff(ss, todo, JSOP_NOP))
+ return NULL;
+ op = JSOP_POP;
+ pc = pc2 + JSOP_NOP_LENGTH;
+ goto do_letheadbody;
+ }
+ } else {
+ /*
+ * An unnannotated NOP following a POPN must be the
+ * third part of for(;;) loop head. If the POPN's
+ * immediate operand is 0, then we may have no slot
+ * on the sprint-stack in which to push our result
+ * string. In this case the result can be recovered
+ * at ss->sprinter.base + ss->sprinter.offset.
+ */
+ if (GET_UINT16(pc) == 0)
+ break;
+ todo = SprintCString(&ss->sprinter, rval);
+ saveop = JSOP_NOP;
+ }
+ }
+
+ /*
+ * If control flow reaches this point with todo still -2,
+ * just print rval as an expression statement.
+ */
+ if (todo == -2)
+ js_printf(jp, "\t%s;\n", rval);
+ break;
+ }
+#endif
+ if (newtop < oldtop) {
+ ss->sprinter.offset = GetOff(ss, newtop);
+ ss->top = newtop;
+ }
+ break;
+ }
+
+ case JSOP_EXCEPTION:
+ /* The catch decompiler handles this op itself. */
+ LOCAL_ASSERT(JS_FALSE);
+ break;
+
+ case JSOP_POP:
+ /*
+ * By default, do not automatically parenthesize when popping
+ * a stacked expression decompilation. We auto-parenthesize
+ * only when JSOP_POP is annotated with SRC_PCDELTA, meaning
+ * comma operator.
+ */
+ op = JSOP_POPV;
+ /* FALL THROUGH */
+
+ case JSOP_POPV:
+ sn = js_GetSrcNote(jp->script, pc);
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_FOR:
+ /* Force parens around 'in' expression at 'for' front. */
+ if (ss->opcodes[ss->top-1] == JSOP_IN)
+ op = JSOP_LSH;
+ rval = POP_STR();
+ todo = -2;
+ goto do_forloop;
+
+ case SRC_PCDELTA:
+ /* Comma operator: use JSOP_POP for correct precedence. */
+ op = JSOP_POP;
+
+ /* Pop and save to avoid blowing stack depth budget. */
+ lval = JS_strdup(cx, POP_STR());
+ if (!lval)
+ return NULL;
+
+ /*
+ * The offset tells distance to the end of the right-hand
+ * operand of the comma operator.
+ */
+ done = pc + len;
+ pc += js_GetSrcNoteOffset(sn, 0);
+ len = 0;
+
+ if (!Decompile(ss, done, pc - done, JSOP_POP)) {
+ JS_free(cx, (char *)lval);
+ return NULL;
+ }
+
+ /* Pop Decompile result and print comma expression. */
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s, %s", lval, rval);
+ JS_free(cx, (char *)lval);
+ break;
+
+ case SRC_HIDDEN:
+ /* Hide this pop, it's from a goto in a with or for/in. */
+ todo = -2;
+ break;
+
+ case SRC_DECL:
+ /* This pop is at the end of the let block/expr head. */
+ pc += JSOP_POP_LENGTH;
+#if JS_HAS_DESTRUCTURING
+ do_letheadbody:
+#endif
+ len = js_GetSrcNoteOffset(sn, 0);
+ if (pc[len] == JSOP_LEAVEBLOCK) {
+ js_printf(jp, "\tlet (%s) {\n", POP_STR());
+ jp->indent += 4;
+ DECOMPILE_CODE(pc, len);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ todo = -2;
+ } else {
+ LOCAL_ASSERT(pc[len] == JSOP_LEAVEBLOCKEXPR);
+
+ lval = JS_strdup(cx, PopStr(ss, JSOP_NOP));
+ if (!lval)
+ return NULL;
+
+ /* Set saveop to reflect what we will push. */
+ saveop = JSOP_LEAVEBLOCKEXPR;
+ if (!Decompile(ss, pc, len, saveop)) {
+ JS_free(cx, (char *)lval);
+ return NULL;
+ }
+ rval = PopStr(ss, JSOP_SETNAME);
+ todo = Sprint(&ss->sprinter,
+ (*rval == '{')
+ ? "let (%s) (%s)"
+ : "let (%s) %s",
+ lval, rval);
+ JS_free(cx, (char *)lval);
+ }
+ break;
+
+ default:
+ /* Turn off parens around a yield statement. */
+ if (ss->opcodes[ss->top-1] == JSOP_YIELD)
+ op = JSOP_NOP;
+
+ rval = POP_STR();
+
+ /*
+ * Don't emit decompiler-pushed strings that are not
+ * handled by other opcodes. They are pushed onto the
+ * stack to help model the interpreter stack and should
+ * not appear in the decompiler's output.
+ */
+ if (*rval != '\0' && (rval[0] != '/' || rval[1] != '*')) {
+ js_printf(jp,
+ (*rval == '{' ||
+ (strncmp(rval, js_function_str, 8) == 0 &&
+ rval[8] == ' '))
+ ? "\t(%s);\n"
+ : "\t%s;\n",
+ rval);
+ } else {
+ LOCAL_ASSERT(*rval == '\0' ||
+ strcmp(rval, exception_cookie) == 0);
+ }
+ todo = -2;
+ break;
+ }
+ sn = NULL;
+ break;
+
+ case JSOP_ENTERWITH:
+ LOCAL_ASSERT(!js_GetSrcNote(jp->script, pc));
+ rval = POP_STR();
+ js_printf(jp, "\twith (%s) {\n", rval);
+ jp->indent += 4;
+ todo = Sprint(&ss->sprinter, with_cookie);
+ break;
+
+ case JSOP_LEAVEWITH:
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, with_cookie) == 0);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+
+ case JSOP_ENTERBLOCK:
+ {
+ JSAtom **atomv, *smallv[5];
+ JSScopeProperty *sprop;
+
+ LOAD_OBJECT(0);
+ argc = OBJ_BLOCK_COUNT(cx, obj);
+ if ((size_t)argc <= JS_ARRAY_LENGTH(smallv)) {
+ atomv = smallv;
+ } else {
+ atomv = (JSAtom **) JS_malloc(cx, argc * sizeof(JSAtom *));
+ if (!atomv)
+ return NULL;
+ }
+
+ MUST_FLOW_THROUGH("enterblock_out");
+#define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
+ goto enterblock_out)
+ for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
+ sprop = sprop->parent) {
+ if (!(sprop->flags & SPROP_HAS_SHORTID))
+ continue;
+ LOCAL_ASSERT_OUT(sprop->shortid < argc);
+ atomv[sprop->shortid] = JSID_TO_ATOM(sprop->id);
+ }
+ ok = JS_TRUE;
+ for (i = 0; i < argc; i++) {
+ atom = atomv[i];
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval ||
+ !PushOff(ss, STR2OFF(&ss->sprinter, rval), op)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+ }
+
+ sn = js_GetSrcNote(jp->script, pc);
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+#if JS_HAS_BLOCK_SCOPE
+ case SRC_BRACE:
+ js_printf(jp, "\t{\n");
+ jp->indent += 4;
+ len = js_GetSrcNoteOffset(sn, 0);
+ ok = Decompile(ss, pc + oplen, len - oplen, JSOP_NOP)
+ != NULL;
+ if (!ok)
+ goto enterblock_out;
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ break;
+#endif
+
+ case SRC_CATCH:
+ jp->indent -= 4;
+ js_printf(jp, "\t} catch (");
+
+ pc2 = pc;
+ pc += oplen;
+ LOCAL_ASSERT_OUT(*pc == JSOP_EXCEPTION);
+ pc += JSOP_EXCEPTION_LENGTH;
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 || !PushOff(ss, todo, JSOP_EXCEPTION)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+
+ if (*pc == JSOP_DUP) {
+ sn2 = js_GetSrcNote(jp->script, pc);
+ if (!sn2 || SN_TYPE(sn2) != SRC_DESTRUCT) {
+ /*
+ * This is a dup to save the exception for later.
+ * It is emitted only when the catch head contains
+ * an exception guard.
+ */
+ LOCAL_ASSERT_OUT(js_GetSrcNoteOffset(sn, 0) != 0);
+ pc += JSOP_DUP_LENGTH;
+ todo = Sprint(&ss->sprinter, exception_cookie);
+ if (todo < 0 ||
+ !PushOff(ss, todo, JSOP_EXCEPTION)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+ }
+ }
+
+#if JS_HAS_DESTRUCTURING
+ if (*pc == JSOP_DUP) {
+ pc = DecompileDestructuring(ss, pc, endpc);
+ if (!pc) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+ LOCAL_ASSERT_OUT(*pc == JSOP_POP);
+ pc += JSOP_POP_LENGTH;
+ lval = PopStr(ss, JSOP_NOP);
+ js_puts(jp, lval);
+ } else {
+#endif
+ LOCAL_ASSERT_OUT(*pc == JSOP_SETLOCALPOP);
+ i = GET_SLOTNO(pc) - jp->script->nfixed;
+ pc += JSOP_SETLOCALPOP_LENGTH;
+ atom = atomv[i - OBJ_BLOCK_DEPTH(cx, obj)];
+ str = ATOM_TO_STRING(atom);
+ if (!QuoteString(&jp->sprinter, str, 0)) {
+ ok = JS_FALSE;
+ goto enterblock_out;
+ }
+#if JS_HAS_DESTRUCTURING
+ }
+#endif
+
+ /*
+ * Pop the exception_cookie (or its dup in the case of a
+ * guarded catch head) off the stack now.
+ */
+ rval = PopStr(ss, JSOP_NOP);
+ LOCAL_ASSERT_OUT(strcmp(rval, exception_cookie) == 0);
+
+ len = js_GetSrcNoteOffset(sn, 0);
+ if (len) {
+ len -= PTRDIFF(pc, pc2, jsbytecode);
+ LOCAL_ASSERT_OUT(len > 0);
+ js_printf(jp, " if ");
+ ok = Decompile(ss, pc, len, JSOP_NOP) != NULL;
+ if (!ok)
+ goto enterblock_out;
+ js_printf(jp, "%s", POP_STR());
+ pc += len;
+ LOCAL_ASSERT_OUT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
+ pc += js_CodeSpec[*pc].length;
+ }
+
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ len = 0;
+ break;
+ default:
+ break;
+ }
+
+ todo = -2;
+
+#undef LOCAL_ASSERT_OUT
+ enterblock_out:
+ if (atomv != smallv)
+ JS_free(cx, atomv);
+ if (!ok)
+ return NULL;
+ }
+ break;
+
+ case JSOP_LEAVEBLOCK:
+ case JSOP_LEAVEBLOCKEXPR:
+ {
+ uintN top, depth;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (op == JSOP_LEAVEBLOCKEXPR) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_PCBASE);
+ rval = POP_STR();
+ } else if (sn) {
+ LOCAL_ASSERT(op == JSOP_LEAVEBLOCK);
+ if (SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+
+ /*
+ * This JSOP_LEAVEBLOCK must be for a catch block. If sn's
+ * offset does not equal the model stack depth, there must
+ * be a copy of the exception value on the stack due to a
+ * catch guard (see above, the JSOP_ENTERBLOCK + SRC_CATCH
+ * case code).
+ */
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_CATCH);
+ if ((uintN)js_GetSrcNoteOffset(sn, 0) != ss->top) {
+ LOCAL_ASSERT((uintN)js_GetSrcNoteOffset(sn, 0)
+ == ss->top - 1);
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, exception_cookie) == 0);
+ }
+ }
+ top = ss->top;
+ depth = GET_UINT16(pc);
+ LOCAL_ASSERT(top >= depth);
+ top -= depth;
+ ss->top = top;
+ ss->sprinter.offset = GetOff(ss, top);
+ if (op == JSOP_LEAVEBLOCKEXPR)
+ todo = SprintCString(&ss->sprinter, rval);
+ break;
+ }
+
+ case JSOP_CALLUPVAR:
+ case JSOP_GETUPVAR:
+
+ if (!jp->fun)
+ JS_GET_SCRIPT_FUNCTION(jp->script, 0, jp->fun);
+
+ if (!jp->localNames)
+ jp->localNames = js_GetLocalNameArray(cx, jp->fun, &jp->pool);
+
+ i = JS_UPVAR_LOCAL_NAME_START(jp->fun) + GET_UINT16(pc);
+ if (i >= JS_GET_LOCAL_NAME_COUNT(jp->fun)) {
+ JSUpvarArray *uva;
+#ifdef DEBUG
+ /*
+ * We must be in an eval called from jp->fun, where
+ * jp->script is the eval-compiled script.
+ *
+ * However, it's possible that a js_Invoke already
+ * pushed a frame trying to call js_Construct on an
+ * object that's not a constructor, causing us to be
+ * called with an intervening frame on the stack.
+ */
+ JSStackFrame *fp = cx->fp;
+ if (fp) {
+ while (!(fp->flags & JSFRAME_EVAL))
+ fp = fp->down;
+ JS_ASSERT(fp->script == jp->script);
+ JS_ASSERT(fp->down->fun == jp->fun);
+ JS_ASSERT(FUN_INTERPRETED(jp->fun));
+ JS_ASSERT(jp->script != jp->fun->u.i.script);
+ JS_ASSERT(jp->script->upvarsOffset != 0);
+ }
+#endif
+ uva = JS_SCRIPT_UPVARS(jp->script);
+ i = GET_UINT16(pc);
+ i = UPVAR_FRAME_SLOT(uva->vector[i]);
+ }
+ atom = GetArgOrVarAtom(jp, i);
+ goto do_name;
+
+ case JSOP_CALLLOCAL:
+ case JSOP_GETLOCAL:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_name;
+ }
+ LOCAL_ASSERT((uintN)i < ss->top);
+ sn = js_GetSrcNote(jp->script, pc);
+
+#if JS_HAS_DESTRUCTURING
+ if (sn && SN_TYPE(sn) == SRC_GROUPASSIGN) {
+ pc = DecompileGroupAssignment(ss, pc, endpc, sn, &todo);
+ if (!pc)
+ return NULL;
+ LOCAL_ASSERT(*pc == JSOP_POPN);
+ len = oplen = JSOP_POPN_LENGTH;
+ goto end_groupassignment;
+ }
+#endif
+
+ rval = GetLocal(ss, i);
+ todo = Sprint(&ss->sprinter, ss_format, VarPrefix(sn), rval);
+ break;
+
+ case JSOP_SETLOCAL:
+ case JSOP_SETLOCALPOP:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_setname;
+ }
+ lval = GetLocal(ss, i);
+ rval = POP_STR();
+ goto do_setlval;
+
+ case JSOP_INCLOCAL:
+ case JSOP_DECLOCAL:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_incatom;
+ }
+ lval = GetLocal(ss, i);
+ goto do_inclval;
+
+ case JSOP_LOCALINC:
+ case JSOP_LOCALDEC:
+ if (IsVarSlot(jp, pc, &i)) {
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ goto do_atominc;
+ }
+ lval = GetLocal(ss, i);
+ goto do_lvalinc;
+
+ case JSOP_RETRVAL:
+ todo = -2;
+ break;
+
+ case JSOP_RETURN:
+ LOCAL_ASSERT(jp->fun);
+ fun = jp->fun;
+ if (fun->flags & JSFUN_EXPR_CLOSURE) {
+ /* Turn on parens around comma-expression here. */
+ op = JSOP_SETNAME;
+ rval = POP_STR();
+ js_printf(jp, (*rval == '{') ? "(%s)%s" : ss_format,
+ rval,
+ ((fun->flags & JSFUN_LAMBDA) || !fun->atom)
+ ? ""
+ : ";");
+ todo = -2;
+ break;
+ }
+ /* FALL THROUGH */
+
+ case JSOP_SETRVAL:
+ rval = POP_STR();
+ if (*rval != '\0')
+ js_printf(jp, "\t%s %s;\n", js_return_str, rval);
+ else
+ js_printf(jp, "\t%s;\n", js_return_str);
+ todo = -2;
+ break;
+
+#if JS_HAS_GENERATORS
+ case JSOP_YIELD:
+#if JS_HAS_GENERATOR_EXPRS
+ if (!ss->inGenExp || !(sn = js_GetSrcNote(jp->script, pc)))
+#endif
+ {
+ /* Turn off most parens. */
+ op = JSOP_SETNAME;
+ rval = POP_STR();
+ todo = (*rval != '\0')
+ ? Sprint(&ss->sprinter,
+ (strncmp(rval, js_yield_str, 5) == 0 &&
+ (rval[5] == ' ' || rval[5] == '\0'))
+ ? "%s (%s)"
+ : "%s %s",
+ js_yield_str, rval)
+ : SprintCString(&ss->sprinter, js_yield_str);
+ break;
+ }
+#if JS_HAS_GENERATOR_EXPRS
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_HIDDEN);
+ /* FALL THROUGH */
+#endif
+
+ case JSOP_ARRAYPUSH:
+ {
+ uintN pos, forpos;
+ ptrdiff_t start;
+
+ /* Turn off most parens. */
+ op = JSOP_SETNAME;
+
+ /* Pop the expression being pushed or yielded. */
+ rval = POP_STR();
+
+ /*
+ * Skip the for loop head stacked by JSOP_FORLOCAL until we hit
+ * a block local slot (note empty destructuring patterns result
+ * in unit-count blocks).
+ */
+ pos = ss->top;
+ while (pos != 0) {
+ op = (JSOp) ss->opcodes[--pos];
+ if (op == JSOP_ENTERBLOCK)
+ break;
+ }
+ JS_ASSERT(op == JSOP_ENTERBLOCK);
+
+ /*
+ * Here, forpos must index the space before the left-most |for|
+ * in the single string of accumulated |for| heads and optional
+ * final |if (condition)|.
+ */
+ forpos = pos + 2;
+ LOCAL_ASSERT(forpos < ss->top);
+
+ /*
+ * Now move pos downward over the block's local slots. Even an
+ * empty destructuring pattern has one (dummy) local.
+ */
+ while (ss->opcodes[pos] == JSOP_ENTERBLOCK) {
+ if (pos == 0)
+ break;
+ --pos;
+ }
+ JS_ASSERT_IF(saveop == JSOP_ARRAYPUSH,
+ jp->script->nfixed + pos == GET_UINT16(pc));
+
+#if JS_HAS_GENERATOR_EXPRS
+ if (saveop == JSOP_YIELD) {
+ /*
+ * Generator expression: decompile just rval followed by
+ * the string starting at forpos. Leave the result string
+ * in ss->offsets[0] so it can be recovered by our caller
+ * (the JSOP_ANONFUNOBJ with SRC_GENEXP case). Bump the
+ * top of stack to balance yield, which is an expression
+ * (so has neutral stack balance).
+ */
+ LOCAL_ASSERT(pos == 0);
+ xval = OFF2STR(&ss->sprinter, ss->offsets[forpos]);
+ ss->sprinter.offset = PAREN_SLOP;
+ todo = Sprint(&ss->sprinter, ss_format, rval, xval);
+ if (todo < 0)
+ return NULL;
+ ss->offsets[0] = todo;
+ ++ss->top;
+ return pc;
+ }
+#endif /* JS_HAS_GENERATOR_EXPRS */
+
+ /*
+ * Array comprehension: retract the sprinter to the beginning
+ * of the array initialiser and decompile "[<rval> for ...]".
+ */
+ LOCAL_ASSERT(ss->opcodes[pos] == JSOP_NEWINIT);
+ start = ss->offsets[pos];
+ LOCAL_ASSERT(ss->sprinter.base[start] == '[' ||
+ ss->sprinter.base[start] == '#');
+ LOCAL_ASSERT(forpos < ss->top);
+ xval = OFF2STR(&ss->sprinter, ss->offsets[forpos]);
+ lval = OFF2STR(&ss->sprinter, start);
+ RETRACT(&ss->sprinter, lval);
+
+ todo = Sprint(&ss->sprinter, sss_format, lval, rval, xval);
+ if (todo < 0)
+ return NULL;
+ ss->offsets[pos] = todo;
+ todo = -2;
+ break;
+ }
+#endif
+
+ case JSOP_THROWING:
+ todo = -2;
+ break;
+
+ case JSOP_THROW:
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+ rval = POP_STR();
+ js_printf(jp, "\t%s %s;\n", js_throw_str, rval);
+ break;
+
+ case JSOP_ITER:
+ foreach = (pc[1] & (JSITER_FOREACH | JSITER_KEYVALUE)) ==
+ JSITER_FOREACH;
+ todo = SprintCString(&ss->sprinter, iter_cookie);
+ break;
+
+ case JSOP_NEXTITER:
+ JS_NOT_REACHED("JSOP_NEXTITER");
+ break;
+
+ case JSOP_ENDITER:
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = -2;
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ break;
+ (void) PopOff(ss, op);
+ (void) PopOff(ss, op);
+ break;
+
+ case JSOP_GOTO:
+ case JSOP_GOTOX:
+ sn = js_GetSrcNote(jp->script, pc);
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_FOR_IN:
+ /*
+ * The loop back-edge carries +1 stack balance, for the
+ * flag processed by JSOP_IFNE. We do not decompile the
+ * JSOP_IFNE, and instead push the left-hand side of 'in'
+ * after the loop edge in this stack slot (the JSOP_FOR*
+ * opcodes' decompilers do this pushing).
+ */
+ cond = GetJumpOffset(pc, pc);
+ next = js_GetSrcNoteOffset(sn, 0);
+ tail = js_GetSrcNoteOffset(sn, 1);
+ JS_ASSERT(pc[cond] == JSOP_NEXTITER);
+ DECOMPILE_CODE(pc + oplen, next - oplen);
+ lval = POP_STR();
+ if (ss->inArrayInit || ss->inGenExp) {
+ (void) PopOff(ss, JSOP_NOP);
+ rval = TOP_STR();
+ LOCAL_ASSERT(ss->top >= 2);
+ if (ss->opcodes[ss->top - 2] == JSOP_FORLOCAL) {
+ ss->sprinter.offset = ss->offsets[ss->top - 1] - PAREN_SLOP;
+ if (Sprint(&ss->sprinter, " %s (%s in %s)",
+ foreach ? js_for_each_str : js_for_str,
+ lval, rval) < 0) {
+ return NULL;
+ }
+
+ /*
+ * Do not AddParentSlop here, as we will push the
+ * top-most offset again, which will add paren slop
+ * for us. We must push to balance the stack budget
+ * when nesting for heads in a comprehension.
+ */
+ todo = ss->offsets[ss->top - 1];
+ } else {
+ LOCAL_ASSERT(ss->opcodes[ss->top - 2] == JSOP_ENTERBLOCK);
+ todo = Sprint(&ss->sprinter, " %s (%s in %s)",
+ foreach ? js_for_each_str : js_for_str,
+ lval, rval);
+ }
+ if (todo < 0 || !PushOff(ss, todo, JSOP_FORLOCAL))
+ return NULL;
+ DECOMPILE_CODE(pc + next, cond - next);
+ } else {
+ /*
+ * As above, rval or an extension of it must remain
+ * stacked during loop body decompilation.
+ */
+ rval = GetStr(ss, ss->top - 2);
+ js_printf(jp, "\t%s (%s in %s) {\n",
+ foreach ? js_for_each_str : js_for_str,
+ lval, rval);
+ jp->indent += 4;
+ DECOMPILE_CODE(pc + next, cond - next);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ }
+ pc += tail;
+ LOCAL_ASSERT(*pc == JSOP_IFNE || *pc == JSOP_IFNEX);
+ len = js_CodeSpec[*pc].length;
+ break;
+
+ case SRC_WHILE:
+ cond = GetJumpOffset(pc, pc);
+ tail = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + cond, tail - cond);
+ js_printf(jp, "\twhile (%s) {\n", POP_COND_STR());
+ jp->indent += 4;
+ DECOMPILE_CODE(pc + oplen, cond - oplen);
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ pc += tail;
+ LOCAL_ASSERT(*pc == JSOP_IFNE || *pc == JSOP_IFNEX);
+ len = js_CodeSpec[*pc].length;
+ todo = -2;
+ break;
+
+ case SRC_CONT2LABEL:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\tcontinue %s;\n", rval);
+ break;
+
+ case SRC_CONTINUE:
+ js_printf(jp, "\tcontinue;\n");
+ break;
+
+ case SRC_BREAK2LABEL:
+ GET_SOURCE_NOTE_ATOM(sn, atom);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ js_printf(jp, "\tbreak %s;\n", rval);
+ break;
+
+ case SRC_HIDDEN:
+ break;
+
+ default:
+ js_printf(jp, "\tbreak;\n");
+ break;
+ }
+ todo = -2;
+ break;
+
+ case JSOP_IFEQ:
+ case JSOP_IFEQX:
+ {
+ JSBool elseif = JS_FALSE;
+
+ if_again:
+ len = GetJumpOffset(pc, pc);
+ sn = js_GetSrcNote(jp->script, pc);
+
+ switch (sn ? SN_TYPE(sn) : SRC_NULL) {
+ case SRC_IF:
+ case SRC_IF_ELSE:
+ rval = POP_COND_STR();
+ if (ss->inArrayInit || ss->inGenExp) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_IF);
+ ss->sprinter.offset -= PAREN_SLOP;
+ if (Sprint(&ss->sprinter, " if (%s)", rval) < 0)
+ return NULL;
+ AddParenSlop(ss);
+ } else {
+ js_printf(jp,
+ elseif ? " if (%s) {\n" : "\tif (%s) {\n",
+ rval);
+ jp->indent += 4;
+ }
+
+ if (SN_TYPE(sn) == SRC_IF) {
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ } else {
+ LOCAL_ASSERT(!ss->inArrayInit && !ss->inGenExp);
+ tail = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + oplen, tail - oplen);
+ jp->indent -= 4;
+ pc += tail;
+ LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
+ oplen = js_CodeSpec[*pc].length;
+ len = GetJumpOffset(pc, pc);
+ js_printf(jp, "\t} else");
+
+ /*
+ * If the second offset for sn is non-zero, it tells
+ * the distance from the goto around the else, to the
+ * ifeq for the if inside the else that forms an "if
+ * else if" chain. Thus cond spans the condition of
+ * the second if, so we simply decompile it and start
+ * over at label if_again.
+ */
+ cond = js_GetSrcNoteOffset(sn, 1);
+ if (cond != 0) {
+ DECOMPILE_CODE(pc + oplen, cond - oplen);
+ pc += cond;
+ elseif = JS_TRUE;
+ goto if_again;
+ }
+
+ js_printf(jp, " {\n");
+ jp->indent += 4;
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ }
+
+ if (!ss->inArrayInit && !ss->inGenExp) {
+ jp->indent -= 4;
+ js_printf(jp, "\t}\n");
+ }
+ todo = -2;
+ break;
+
+ case SRC_COND:
+ xval = JS_strdup(cx, POP_STR());
+ if (!xval)
+ return NULL;
+ len = js_GetSrcNoteOffset(sn, 0);
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ lval = JS_strdup(cx, POP_STR());
+ if (!lval) {
+ JS_free(cx, (void *)xval);
+ return NULL;
+ }
+ pc += len;
+ LOCAL_ASSERT(*pc == JSOP_GOTO || *pc == JSOP_GOTOX);
+ oplen = js_CodeSpec[*pc].length;
+ len = GetJumpOffset(pc, pc);
+ DECOMPILE_CODE(pc + oplen, len - oplen);
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s ? %s : %s",
+ xval, lval, rval);
+ JS_free(cx, (void *)xval);
+ JS_free(cx, (void *)lval);
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ case JSOP_IFNE:
+ case JSOP_IFNEX:
+ LOCAL_ASSERT(0);
+ break;
+
+ case JSOP_OR:
+ case JSOP_ORX:
+ xval = "||";
+
+ do_logical_connective:
+ /* Top of stack is the first clause in a disjunction (||). */
+ lval = JS_strdup(cx, POP_STR());
+ if (!lval)
+ return NULL;
+ done = pc + GetJumpOffset(pc, pc);
+ pc += len;
+ len = PTRDIFF(done, pc, jsbytecode);
+ if (!Decompile(ss, pc, len, op)) {
+ JS_free(cx, (char *)lval);
+ return NULL;
+ }
+ rval = POP_STR();
+ if (jp->pretty &&
+ jp->indent + 4 + strlen(lval) + 4 + strlen(rval) > 75) {
+ rval = JS_strdup(cx, rval);
+ if (!rval) {
+ tail = -1;
+ } else {
+ todo = Sprint(&ss->sprinter, "%s %s\n", lval, xval);
+ tail = Sprint(&ss->sprinter, "%*s%s",
+ jp->indent + 4, "", rval);
+ JS_free(cx, (char *)rval);
+ }
+ if (tail < 0)
+ todo = -1;
+ } else {
+ todo = Sprint(&ss->sprinter, "%s %s %s", lval, xval, rval);
+ }
+ JS_free(cx, (char *)lval);
+ break;
+
+ case JSOP_AND:
+ case JSOP_ANDX:
+ xval = "&&";
+ goto do_logical_connective;
+
+ case JSOP_FORARG:
+ sn = NULL;
+ i = GET_ARGNO(pc);
+ goto do_forvarslot;
+
+ case JSOP_FORLOCAL:
+ sn = js_GetSrcNote(jp->script, pc);
+ if (!IsVarSlot(jp, pc, &i)) {
+ JS_ASSERT(op == JSOP_FORLOCAL);
+ todo = Sprint(&ss->sprinter, ss_format, VarPrefix(sn), GetStr(ss, i));
+ break;
+ }
+
+ do_forvarslot:
+ atom = GetArgOrVarAtom(jp, i);
+ LOCAL_ASSERT(atom);
+ todo = SprintCString(&ss->sprinter, VarPrefix(sn));
+ if (todo < 0 || !QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return NULL;
+ break;
+
+ case JSOP_FORNAME:
+ LOAD_ATOM(0);
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = SprintCString(&ss->sprinter, VarPrefix(sn));
+ if (todo < 0 || !QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return NULL;
+ break;
+
+ case JSOP_FORPROP:
+ xval = NULL;
+ LOAD_ATOM(0);
+ if (!ATOM_IS_IDENTIFIER(atom)) {
+ xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ (jschar)'\'');
+ if (!xval)
+ return NULL;
+ }
+ lval = POP_STR();
+ if (xval) {
+ JS_ASSERT(*lval);
+ todo = Sprint(&ss->sprinter, index_format, lval, xval);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format, lval, *lval ? "." : "");
+ if (todo < 0)
+ return NULL;
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0))
+ return NULL;
+ }
+ break;
+
+ case JSOP_FORELEM:
+ todo = SprintCString(&ss->sprinter, forelem_cookie);
+ break;
+
+ case JSOP_ENUMELEM:
+ case JSOP_ENUMCONSTELEM:
+ /*
+ * The stack has the object under the (top) index expression.
+ * The "rval" property id is underneath those two on the stack.
+ * The for loop body net and gross lengths can now be adjusted
+ * to account for the length of the indexing expression that
+ * came after JSOP_FORELEM and before JSOP_ENUMELEM.
+ */
+ atom = NULL;
+ op = JSOP_NOP; /* turn off parens around xval */
+ xval = POP_STR();
+ op = JSOP_GETELEM; /* lval must have high precedence */
+ lval = POP_STR();
+ op = saveop;
+ rval = POP_STR();
+ LOCAL_ASSERT(strcmp(rval, forelem_cookie) == 0);
+ if (*xval == '\0') {
+ todo = SprintCString(&ss->sprinter, lval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? dot_format
+ : index_format,
+ lval, xval);
+ }
+ break;
+
+#if JS_HAS_GETTER_SETTER
+ case JSOP_GETTER:
+ case JSOP_SETTER:
+ todo = -2;
+ break;
+#endif
+
+ case JSOP_DUP2:
+ rval = GetStr(ss, ss->top-2);
+ todo = SprintCString(&ss->sprinter, rval);
+ if (todo < 0 || !PushOff(ss, todo,
+ (JSOp) ss->opcodes[ss->top-2])) {
+ return NULL;
+ }
+ /* FALL THROUGH */
+
+ case JSOP_DUP:
+#if JS_HAS_DESTRUCTURING
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_DESTRUCT);
+ pc = DecompileDestructuring(ss, pc, endpc);
+ if (!pc)
+ return NULL;
+ len = 0;
+ lval = POP_STR();
+ op = saveop = JSOP_ENUMELEM;
+ rval = POP_STR();
+
+ if (strcmp(rval, forelem_cookie) == 0) {
+ todo = Sprint(&ss->sprinter, ss_format,
+ VarPrefix(sn), lval);
+
+ // Skip POP so the SRC_FOR_IN code can pop for itself.
+ if (*pc == JSOP_POP)
+ len = JSOP_POP_LENGTH;
+ } else {
+ todo = Sprint(&ss->sprinter, "%s%s = %s",
+ VarPrefix(sn), lval, rval);
+ }
+ break;
+ }
+#endif
+
+ rval = GetStr(ss, ss->top-1);
+ saveop = (JSOp) ss->opcodes[ss->top-1];
+ todo = SprintCString(&ss->sprinter, rval);
+ break;
+
+ case JSOP_SETARG:
+ atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
+ LOCAL_ASSERT(atom);
+ goto do_setname;
+
+ case JSOP_SETCONST:
+ case JSOP_SETNAME:
+ case JSOP_SETGVAR:
+ LOAD_ATOM(0);
+
+ do_setname:
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ rval = POP_STR();
+ if (op == JSOP_SETNAME)
+ (void) PopOff(ss, op);
+
+ do_setlval:
+ sn = js_GetSrcNote(jp->script, pc - 1);
+ if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
+ todo = Sprint(&ss->sprinter, "%s %s= %s",
+ lval,
+ (lastop == JSOP_GETTER)
+ ? js_getter_str
+ : (lastop == JSOP_SETTER)
+ ? js_setter_str
+ : CodeToken[lastop],
+ rval);
+ } else {
+ sn = js_GetSrcNote(jp->script, pc);
+ todo = Sprint(&ss->sprinter, "%s%s = %s",
+ VarPrefix(sn), lval, rval);
+ }
+ if (op == JSOP_SETLOCALPOP) {
+ if (!PushOff(ss, todo, saveop))
+ return NULL;
+ rval = POP_STR();
+ LOCAL_ASSERT(*rval != '\0');
+ js_printf(jp, "\t%s;\n", rval);
+ todo = -2;
+ }
+ break;
+
+ case JSOP_NEW:
+ case JSOP_CALL:
+ case JSOP_EVAL:
+ case JSOP_APPLY:
+#if JS_HAS_LVALUE_RETURN
+ case JSOP_SETCALL:
+#endif
+ /* Turn off most parens (all if there's only one argument). */
+ argc = GET_ARGC(pc);
+ op = (argc == 1) ? JSOP_NOP : JSOP_SETNAME;
+ argv = (char **)
+ JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv);
+ if (!argv)
+ return NULL;
+
+ ok = JS_TRUE;
+ for (i = argc; i > 0; i--) {
+ argv[i] = JS_strdup(cx, POP_STR());
+ if (!argv[i])
+ ok = JS_FALSE;
+ }
+
+ /* Skip the JSOP_PUSHOBJ-created empty string. */
+ LOCAL_ASSERT(ss->top >= 2);
+ (void) PopOff(ss, op);
+
+ /*
+ * Special case: new (x(y)(z)) must be parenthesized like so.
+ * Same for new (x(y).z) -- contrast with new x(y).z.
+ * See PROPAGATE_CALLNESS.
+ */
+ op = (JSOp) ss->opcodes[ss->top-1];
+ lval = PopStr(ss,
+ (saveop == JSOP_NEW &&
+ (op == JSOP_CALL ||
+ op == JSOP_EVAL ||
+ op == JSOP_APPLY ||
+ (js_CodeSpec[op].format & JOF_CALLOP)))
+ ? JSOP_NAME
+ : saveop);
+ op = saveop;
+
+ argv[0] = JS_strdup(cx, lval);
+ if (!argv[i])
+ ok = JS_FALSE;
+
+ lval = "(", rval = ")";
+ if (op == JSOP_NEW) {
+ if (argc == 0)
+ lval = rval = "";
+ todo = Sprint(&ss->sprinter, "%s %s%s",
+ js_new_str, argv[0], lval);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format,
+ argv[0], lval);
+ }
+ if (todo < 0)
+ ok = JS_FALSE;
+
+ for (i = 1; i <= argc; i++) {
+ if (!argv[i] ||
+ Sprint(&ss->sprinter, ss_format,
+ argv[i], (i < argc) ? ", " : "") < 0) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+ if (Sprint(&ss->sprinter, rval) < 0)
+ ok = JS_FALSE;
+
+ for (i = 0; i <= argc; i++) {
+ if (argv[i])
+ JS_free(cx, argv[i]);
+ }
+ JS_free(cx, argv);
+ if (!ok)
+ return NULL;
+#if JS_HAS_LVALUE_RETURN
+ if (op == JSOP_SETCALL) {
+ if (!PushOff(ss, todo, op))
+ return NULL;
+ todo = Sprint(&ss->sprinter, "");
+ }
+#endif
+ break;
+
+ case JSOP_DELNAME:
+ LOAD_ATOM(0);
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ RETRACT(&ss->sprinter, lval);
+ do_delete_lval:
+ todo = Sprint(&ss->sprinter, "%s %s", js_delete_str, lval);
+ break;
+
+ case JSOP_DELPROP:
+ GET_ATOM_QUOTE_AND_FMT("%s %s[%s]", "%s %s.%s", rval);
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt, js_delete_str, lval, rval);
+ break;
+
+ case JSOP_DELELEM:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ if (*xval == '\0')
+ goto do_delete_lval;
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? "%s %s.%s"
+ : "%s %s[%s]",
+ js_delete_str, lval, xval);
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case JSOP_DELDESC:
+ xval = POP_STR();
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s..%s",
+ js_delete_str, lval, xval);
+ break;
+#endif
+
+ case JSOP_TYPEOFEXPR:
+ case JSOP_TYPEOF:
+ case JSOP_VOID:
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s",
+ (op == JSOP_VOID) ? js_void_str : js_typeof_str,
+ rval);
+ break;
+
+ case JSOP_INCARG:
+ case JSOP_DECARG:
+ atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
+ LOCAL_ASSERT(atom);
+ goto do_incatom;
+
+ case JSOP_INCNAME:
+ case JSOP_DECNAME:
+ case JSOP_INCGVAR:
+ case JSOP_DECGVAR:
+ LOAD_ATOM(0);
+ do_incatom:
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ RETRACT(&ss->sprinter, lval);
+ do_inclval:
+ todo = Sprint(&ss->sprinter, ss_format,
+ js_incop_strs[!(cs->format & JOF_INC)], lval);
+ break;
+
+ case JSOP_INCPROP:
+ case JSOP_DECPROP:
+ GET_ATOM_QUOTE_AND_FMT(preindex_format, predot_format, rval);
+
+ /*
+ * Force precedence below the numeric literal opcodes, so that
+ * 42..foo or 10000..toString(16), e.g., decompile with parens
+ * around the left-hand side of dot.
+ */
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt,
+ js_incop_strs[!(cs->format & JOF_INC)],
+ lval, rval);
+ break;
+
+ case JSOP_INCELEM:
+ case JSOP_DECELEM:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = JSOP_GETELEM;
+ lval = POP_STR();
+ if (*xval != '\0') {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? predot_format
+ : preindex_format,
+ js_incop_strs[!(cs->format & JOF_INC)],
+ lval, xval);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format,
+ js_incop_strs[!(cs->format & JOF_INC)], lval);
+ }
+ break;
+
+ case JSOP_ARGINC:
+ case JSOP_ARGDEC:
+ atom = GetArgOrVarAtom(jp, GET_ARGNO(pc));
+ LOCAL_ASSERT(atom);
+ goto do_atominc;
+
+ case JSOP_NAMEINC:
+ case JSOP_NAMEDEC:
+ case JSOP_GVARINC:
+ case JSOP_GVARDEC:
+ LOAD_ATOM(0);
+ do_atominc:
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval)
+ return NULL;
+ RETRACT(&ss->sprinter, lval);
+ do_lvalinc:
+ todo = Sprint(&ss->sprinter, ss_format,
+ lval, js_incop_strs[!(cs->format & JOF_INC)]);
+ break;
+
+ case JSOP_PROPINC:
+ case JSOP_PROPDEC:
+ GET_ATOM_QUOTE_AND_FMT(postindex_format, postdot_format, rval);
+
+ /*
+ * Force precedence below the numeric literal opcodes, so that
+ * 42..foo or 10000..toString(16), e.g., decompile with parens
+ * around the left-hand side of dot.
+ */
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt, lval, rval,
+ js_incop_strs[!(cs->format & JOF_INC)]);
+ break;
+
+ case JSOP_ELEMINC:
+ case JSOP_ELEMDEC:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = JSOP_GETELEM;
+ lval = POP_STR();
+ if (*xval != '\0') {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? postdot_format
+ : postindex_format,
+ lval, xval,
+ js_incop_strs[!(cs->format & JOF_INC)]);
+ } else {
+ todo = Sprint(&ss->sprinter, ss_format,
+ lval, js_incop_strs[!(cs->format & JOF_INC)]);
+ }
+ break;
+
+ case JSOP_LENGTH:
+ fmt = dot_format;
+ rval = js_length_str;
+ goto do_getprop_lval;
+
+ case JSOP_GETPROP2:
+ op = JSOP_GETPROP;
+ (void) PopOff(ss, lastop);
+ /* FALL THROUGH */
+
+ case JSOP_CALLPROP:
+ case JSOP_GETPROP:
+ case JSOP_GETXPROP:
+ LOAD_ATOM(0);
+
+ do_getprop:
+ GET_QUOTE_AND_FMT(index_format, dot_format, rval);
+ do_getprop_lval:
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, fmt, lval, rval);
+ break;
+
+ case JSOP_GETTHISPROP:
+ LOAD_ATOM(0);
+ GET_QUOTE_AND_FMT(index_format, dot_format, rval);
+ todo = Sprint(&ss->sprinter, fmt, js_this_str, rval);
+ break;
+
+ case JSOP_GETARGPROP:
+ /* Get the name of the argument or variable. */
+ i = GET_ARGNO(pc);
+
+ do_getarg_prop:
+ atom = GetArgOrVarAtom(ss->printer, i);
+ LOCAL_ASSERT(atom);
+ LOCAL_ASSERT(ATOM_IS_STRING(atom));
+ lval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!lval || !PushOff(ss, STR2OFF(&ss->sprinter, lval), op))
+ return NULL;
+
+ /* Get the name of the property. */
+ LOAD_ATOM(ARGNO_LEN);
+ goto do_getprop;
+
+ case JSOP_GETLOCALPROP:
+ if (IsVarSlot(jp, pc, &i))
+ goto do_getarg_prop;
+ LOCAL_ASSERT((uintN)i < ss->top);
+ lval = GetLocal(ss, i);
+ if (!lval)
+ return NULL;
+ todo = SprintCString(&ss->sprinter, lval);
+ if (todo < 0 || !PushOff(ss, todo, op))
+ return NULL;
+ LOAD_ATOM(2);
+ goto do_getprop;
+
+ case JSOP_SETPROP:
+ LOAD_ATOM(0);
+ GET_QUOTE_AND_FMT("%s[%s] %s= %s", "%s.%s %s= %s", xval);
+ rval = POP_STR();
+
+ /*
+ * Force precedence below the numeric literal opcodes, so that
+ * 42..foo or 10000..toString(16), e.g., decompile with parens
+ * around the left-hand side of dot.
+ */
+ op = JSOP_GETPROP;
+ lval = POP_STR();
+ sn = js_GetSrcNote(jp->script, pc - 1);
+ todo = Sprint(&ss->sprinter, fmt, lval, xval,
+ (sn && SN_TYPE(sn) == SRC_ASSIGNOP)
+ ? (lastop == JSOP_GETTER)
+ ? js_getter_str
+ : (lastop == JSOP_SETTER)
+ ? js_setter_str
+ : CodeToken[lastop]
+ : "",
+ rval);
+ break;
+
+ case JSOP_GETELEM2:
+ op = JSOP_GETELEM;
+ (void) PopOff(ss, lastop);
+ /* FALL THROUGH */
+
+ case JSOP_CALLELEM:
+ case JSOP_GETELEM:
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ op = saveop;
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ if (*xval == '\0') {
+ todo = Sprint(&ss->sprinter, "%s", lval);
+ } else {
+ todo = Sprint(&ss->sprinter,
+ (JOF_OPMODE(lastop) == JOF_XMLNAME)
+ ? dot_format
+ : index_format,
+ lval, xval);
+ }
+ break;
+
+ case JSOP_SETELEM:
+ rval = POP_STR();
+ op = JSOP_NOP; /* turn off parens */
+ xval = POP_STR();
+ cs = &js_CodeSpec[ss->opcodes[ss->top]];
+ op = JSOP_GETELEM; /* lval must have high precedence */
+ lval = POP_STR();
+ op = saveop;
+ if (*xval == '\0')
+ goto do_setlval;
+ sn = js_GetSrcNote(jp->script, pc - 1);
+ todo = Sprint(&ss->sprinter,
+ (JOF_MODE(cs->format) == JOF_XMLNAME)
+ ? "%s.%s %s= %s"
+ : "%s[%s] %s= %s",
+ lval, xval,
+ (sn && SN_TYPE(sn) == SRC_ASSIGNOP)
+ ? (lastop == JSOP_GETTER)
+ ? js_getter_str
+ : (lastop == JSOP_SETTER)
+ ? js_setter_str
+ : CodeToken[lastop]
+ : "",
+ rval);
+ break;
+
+ case JSOP_ARGSUB:
+ i = (jsint) GET_ARGNO(pc);
+ todo = Sprint(&ss->sprinter, "%s[%d]",
+ js_arguments_str, (int) i);
+ break;
+
+ case JSOP_ARGCNT:
+ todo = Sprint(&ss->sprinter, dot_format,
+ js_arguments_str, js_length_str);
+ break;
+
+ case JSOP_CALLARG:
+ case JSOP_GETARG:
+ i = GET_ARGNO(pc);
+ atom = GetArgOrVarAtom(jp, i);
+#if JS_HAS_DESTRUCTURING
+ if (!atom) {
+ todo = Sprint(&ss->sprinter, "%s[%d]", js_arguments_str, i);
+ break;
+ }
+#else
+ LOCAL_ASSERT(atom);
+#endif
+ goto do_name;
+
+ case JSOP_CALLNAME:
+ case JSOP_NAME:
+ case JSOP_GETGVAR:
+ case JSOP_CALLGVAR:
+ LOAD_ATOM(0);
+ do_name:
+ lval = "";
+#if JS_HAS_XML_SUPPORT
+ do_qname:
+#endif
+ sn = js_GetSrcNote(jp->script, pc);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ inXML ? DONT_ESCAPE : 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ todo = Sprint(&ss->sprinter, sss_format,
+ VarPrefix(sn), lval, rval);
+ break;
+
+ case JSOP_UINT16:
+ i = (jsint) GET_UINT16(pc);
+ goto do_sprint_int;
+
+ case JSOP_UINT24:
+ i = (jsint) GET_UINT24(pc);
+ goto do_sprint_int;
+
+ case JSOP_INT8:
+ i = GET_INT8(pc);
+ goto do_sprint_int;
+
+ case JSOP_INT32:
+ i = GET_INT32(pc);
+ do_sprint_int:
+ todo = Sprint(&ss->sprinter, "%d", i);
+ break;
+
+ case JSOP_DOUBLE:
+ LOAD_ATOM(0);
+ val = ATOM_KEY(atom);
+ LOCAL_ASSERT(JSVAL_IS_DOUBLE(val));
+ todo = SprintDoubleValue(&ss->sprinter, val, &saveop);
+ break;
+
+ case JSOP_STRING:
+ LOAD_ATOM(0);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ inXML ? DONT_ESCAPE : '"');
+ if (!rval)
+ return NULL;
+ todo = STR2OFF(&ss->sprinter, rval);
+ break;
+
+ case JSOP_ANONFUNOBJ:
+#if JS_HAS_GENERATOR_EXPRS
+ sn = js_GetSrcNote(jp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_GENEXP) {
+ JSScript *inner, *outer;
+ void *mark;
+ SprintStack ss2;
+
+ LOAD_FUNCTION(0);
+ inner = fun->u.i.script;
+
+ /*
+ * All allocation when decompiling is LIFO, using malloc
+ * or, more commonly, arena-alloocating from cx->tempPool.
+ * After InitSprintStack succeeds, we must release to mark
+ * before returning.
+ */
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner)))
+ return NULL;
+ ss2.inGenExp = JS_TRUE;
+
+ /*
+ * Recursively decompile this generator function as an
+ * un-parenthesized generator expression. The ss->inGenExp
+ * special case of JSOP_YIELD shares array comprehension
+ * decompilation code that leaves the result as the single
+ * string pushed on ss2.
+ */
+ outer = jp->script;
+ LOCAL_ASSERT(JS_UPTRDIFF(pc, outer->code) <= outer->length);
+ jp->script = inner;
+ if (!Decompile(&ss2, inner->code, inner->length, JSOP_NOP)) {
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return NULL;
+ }
+ jp->script = outer;
+
+ /*
+ * Advance over this op and its global |this| push, and
+ * arrange to advance over the call to this lambda.
+ */
+ pc += len;
+ LOCAL_ASSERT(*pc == JSOP_NULL || *pc == JSOP_NULLTHIS);
+ pc += JSOP_NULL_LENGTH;
+ LOCAL_ASSERT(*pc == JSOP_CALL);
+ LOCAL_ASSERT(GET_ARGC(pc) == 0);
+ len = JSOP_CALL_LENGTH;
+
+ /*
+ * Arrange to parenthesize this genexp unless:
+ *
+ * 1. It is the complete expression consumed by a control
+ * flow bytecode such as JSOP_TABLESWITCH whose syntax
+ * always parenthesizes the controlling expression.
+ * 2. It is the condition of a loop other than a for (;;).
+ * 3. It is the sole argument to a function call.
+ * 4. It is the condition of an if statement and not of a
+ * ?: expression.
+ *
+ * But (first, before anything else) always parenthesize
+ * if this genexp runs up against endpc and the next op is
+ * not a loop condition (JSOP_IFNE*) opcode. In such cases,
+ * this Decompile activation has been recursively called by
+ * a comma operator, &&, or || bytecode.
+ */
+ pc2 = pc + len;
+ LOCAL_ASSERT(pc2 < endpc ||
+ endpc < outer->code + outer->length);
+ LOCAL_ASSERT(ss2.top == 1);
+ ss2.opcodes[0] = JSOP_POP;
+ if (pc2 == endpc &&
+ (JSOp) *endpc != JSOP_IFNE &&
+ (JSOp) *endpc != JSOP_IFNEX) {
+ op = JSOP_SETNAME;
+ } else {
+ op = (JSOp) *pc2;
+ op = ((js_CodeSpec[op].format & JOF_PARENHEAD) ||
+ ((js_CodeSpec[op].format & JOF_INVOKE) &&
+ GET_ARGC(pc2) == 1) ||
+ ((op == JSOP_IFEQ || op == JSOP_IFEQX) &&
+ (sn2 = js_GetSrcNote(outer, pc2)) &&
+ SN_TYPE(sn2) != SRC_COND))
+ ? JSOP_POP
+ : JSOP_SETNAME;
+
+ /*
+ * Stack this result as if it's a name and not an
+ * anonymous function, so it doesn't get decompiled as
+ * a generator function in a getter or setter context.
+ * The precedence level is the same for JSOP_NAME and
+ * JSOP_ANONFUNOBJ.
+ */
+ LOCAL_ASSERT(js_CodeSpec[JSOP_NAME].prec ==
+ js_CodeSpec[saveop].prec);
+ saveop = JSOP_NAME;
+ }
+
+ /*
+ * Alas, we have to malloc a copy of the result left on
+ * the top of ss2 because both ss and ss2 arena-allocate
+ * from cx's tempPool.
+ */
+ rval = JS_strdup(cx, PopStr(&ss2, op));
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ if (!rval)
+ return NULL;
+ todo = SprintCString(&ss->sprinter, rval);
+ JS_free(cx, (void *)rval);
+ break;
+ }
+#endif /* JS_HAS_GENERATOR_EXPRS */
+ /* FALL THROUGH */
+
+ case JSOP_NAMEDFUNOBJ:
+ LOAD_FUNCTION(0);
+ {
+ uintN indent = JS_DONT_PRETTY_PRINT;
+
+ /*
+ * Always parenthesize expression closures. We can't force
+ * saveop to a low-precedence op to arrange for auto-magic
+ * parenthesization without confusing getter/setter code
+ * that checks for JSOP_ANONFUNOBJ and JSOP_NAMEDFUNOBJ.
+ */
+ if (!(fun->flags & JSFUN_EXPR_CLOSURE))
+ indent |= JS_IN_GROUP_CONTEXT;
+ str = JS_DecompileFunction(cx, fun, indent);
+ if (!str)
+ return NULL;
+ }
+ sprint_string:
+ todo = SprintString(&ss->sprinter, str);
+ break;
+
+ case JSOP_OBJECT:
+ LOAD_OBJECT(0);
+ LOCAL_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
+ goto do_regexp;
+
+ case JSOP_REGEXP:
+ GET_REGEXP_FROM_BYTECODE(jp->script, pc, 0, obj);
+ do_regexp:
+ if (!js_regexp_toString(cx, obj, &val))
+ return NULL;
+ str = JSVAL_TO_STRING(val);
+ goto sprint_string;
+
+ case JSOP_TABLESWITCH:
+ case JSOP_TABLESWITCHX:
+ {
+ ptrdiff_t jmplen, off, off2;
+ jsint j, n, low, high;
+ TableEntry *table, *tmp;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
+ len = js_GetSrcNoteOffset(sn, 0);
+ jmplen = (op == JSOP_TABLESWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ low = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+ high = GET_JUMP_OFFSET(pc2);
+ pc2 += JUMP_OFFSET_LEN;
+
+ n = high - low + 1;
+ if (n == 0) {
+ table = NULL;
+ j = 0;
+ ok = JS_TRUE;
+ } else {
+ table = (TableEntry *)
+ JS_malloc(cx, (size_t)n * sizeof *table);
+ if (!table)
+ return NULL;
+ for (i = j = 0; i < n; i++) {
+ table[j].label = NULL;
+ off2 = GetJumpOffset(pc, pc2);
+ if (off2) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ if (sn) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_LABEL);
+ GET_SOURCE_NOTE_ATOM(sn, table[j].label);
+ }
+ table[j].key = INT_TO_JSVAL(low + i);
+ table[j].offset = off2;
+ table[j].order = j;
+ j++;
+ }
+ pc2 += jmplen;
+ }
+ tmp = (TableEntry *)
+ JS_malloc(cx, (size_t)j * sizeof *table);
+ if (tmp) {
+ ok = js_MergeSort(table, (size_t)j, sizeof(TableEntry),
+ CompareOffsets, NULL, tmp);
+ JS_free(cx, tmp);
+ } else {
+ ok = JS_FALSE;
+ }
+ }
+
+ if (ok) {
+ ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off,
+ JS_FALSE);
+ }
+ JS_free(cx, table);
+ if (!ok)
+ return NULL;
+ todo = -2;
+ break;
+ }
+
+ case JSOP_LOOKUPSWITCH:
+ case JSOP_LOOKUPSWITCHX:
+ {
+ ptrdiff_t jmplen, off, off2;
+ jsatomid npairs, k;
+ TableEntry *table;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
+ len = js_GetSrcNoteOffset(sn, 0);
+ jmplen = (op == JSOP_LOOKUPSWITCH) ? JUMP_OFFSET_LEN
+ : JUMPX_OFFSET_LEN;
+ pc2 = pc;
+ off = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ npairs = GET_UINT16(pc2);
+ pc2 += UINT16_LEN;
+
+ table = (TableEntry *)
+ JS_malloc(cx, (size_t)npairs * sizeof *table);
+ if (!table)
+ return NULL;
+ for (k = 0; k < npairs; k++) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ if (sn) {
+ LOCAL_ASSERT(SN_TYPE(sn) == SRC_LABEL);
+ GET_SOURCE_NOTE_ATOM(sn, table[k].label);
+ } else {
+ table[k].label = NULL;
+ }
+ JS_GET_SCRIPT_ATOM(jp->script, GET_INDEX(pc2), atom);
+ pc2 += INDEX_LEN;
+ off2 = GetJumpOffset(pc, pc2);
+ pc2 += jmplen;
+ table[k].key = ATOM_KEY(atom);
+ table[k].offset = off2;
+ }
+
+ ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off,
+ JS_FALSE);
+ JS_free(cx, table);
+ if (!ok)
+ return NULL;
+ todo = -2;
+ break;
+ }
+
+ case JSOP_CONDSWITCH:
+ {
+ ptrdiff_t off, off2, caseOff;
+ jsint ncases;
+ TableEntry *table;
+
+ sn = js_GetSrcNote(jp->script, pc);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);
+ len = js_GetSrcNoteOffset(sn, 0);
+ off = js_GetSrcNoteOffset(sn, 1);
+
+ /*
+ * Count the cases using offsets from switch to first case,
+ * and case to case, stored in srcnote immediates.
+ */
+ pc2 = pc;
+ off2 = off;
+ for (ncases = 0; off2 != 0; ncases++) {
+ pc2 += off2;
+ LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
+ *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
+ if (*pc2 == JSOP_DEFAULT || *pc2 == JSOP_DEFAULTX) {
+ /* End of cases, but count default as a case. */
+ off2 = 0;
+ } else {
+ sn = js_GetSrcNote(jp->script, pc2);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
+ off2 = js_GetSrcNoteOffset(sn, 0);
+ }
+ }
+
+ /*
+ * Allocate table and rescan the cases using their srcnotes,
+ * stashing each case's delta from switch top in table[i].key,
+ * and the distance to its statements in table[i].offset.
+ */
+ table = (TableEntry *)
+ JS_malloc(cx, (size_t)ncases * sizeof *table);
+ if (!table)
+ return NULL;
+ pc2 = pc;
+ off2 = off;
+ for (i = 0; i < ncases; i++) {
+ pc2 += off2;
+ LOCAL_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT ||
+ *pc2 == JSOP_CASEX || *pc2 == JSOP_DEFAULTX);
+ caseOff = pc2 - pc;
+ table[i].key = INT_TO_JSVAL((jsint) caseOff);
+ table[i].offset = caseOff + GetJumpOffset(pc2, pc2);
+ if (*pc2 == JSOP_CASE || *pc2 == JSOP_CASEX) {
+ sn = js_GetSrcNote(jp->script, pc2);
+ LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);
+ off2 = js_GetSrcNoteOffset(sn, 0);
+ }
+ }
+
+ /*
+ * Find offset of default code by fetching the default offset
+ * from the end of table. JSOP_CONDSWITCH always has a default
+ * case at the end.
+ */
+ off = JSVAL_TO_INT(table[ncases-1].key);
+ pc2 = pc + off;
+ off += GetJumpOffset(pc2, pc2);
+
+ ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,
+ JS_TRUE);
+ JS_free(cx, table);
+ if (!ok)
+ return NULL;
+ todo = -2;
+ break;
+ }
+
+ case JSOP_CASE:
+ case JSOP_CASEX:
+ {
+ lval = POP_STR();
+ if (!lval)
+ return NULL;
+ js_printf(jp, "\tcase %s:\n", lval);
+ todo = -2;
+ break;
+ }
+
+ case JSOP_DEFFUN:
+ LOAD_FUNCTION(0);
+ todo = -2;
+ goto do_function;
+ break;
+
+ case JSOP_TRAP:
+ saveop = op = JS_GetTrapOpcode(cx, jp->script, pc);
+ *pc = op;
+ cs = &js_CodeSpec[op];
+ len = cs->length;
+ DECOMPILE_CODE(pc, len);
+ *pc = JSOP_TRAP;
+ todo = -2;
+ break;
+
+ case JSOP_HOLE:
+ todo = SprintPut(&ss->sprinter, "", 0);
+ break;
+
+ case JSOP_NEWARRAY:
+ {
+ ptrdiff_t off;
+ char *base, *from, *to;
+
+ /*
+ * All operands are stacked and ready for in-place formatting.
+ * We know that PAREN_SLOP is 3 here, and take advantage of it
+ * to avoid strdup'ing.
+ */
+ argc = GET_UINT24(pc);
+ LOCAL_ASSERT(ss->top >= (uintN) argc);
+ sn = js_GetSrcNote(jp->script, pc);
+ if (argc == 0) {
+ todo = Sprint(&ss->sprinter, "[%s]",
+ (sn && SN_TYPE(sn) == SRC_CONTINUE)
+ ? ", "
+ : "");
+ } else {
+ ss->top -= argc;
+ off = GetOff(ss, ss->top);
+ LOCAL_ASSERT(off >= PAREN_SLOP);
+ base = OFF2STR(&ss->sprinter, off);
+ to = base + 1;
+ i = 0;
+ for (;;) {
+ /* Move to the next string that had been stacked. */
+ from = OFF2STR(&ss->sprinter, off);
+ todo = strlen(from);
+ memmove(to, from, todo);
+ to += todo;
+ if (++i == argc &&
+ !(sn && SN_TYPE(sn) == SRC_CONTINUE)) {
+ break;
+ }
+ *to++ = ',';
+ *to++ = ' ';
+ off = GetOff(ss, ss->top + i);
+ }
+ LOCAL_ASSERT(to - base < ss->sprinter.offset - PAREN_SLOP);
+ *base = '[';
+ *to++ = ']';
+ *to = '\0';
+ ss->sprinter.offset = STR2OFF(&ss->sprinter, to);
+ todo = STR2OFF(&ss->sprinter, base);
+ }
+ break;
+ }
+
+ case JSOP_NEWINIT:
+ {
+ i = GET_INT8(pc);
+ LOCAL_ASSERT(i == JSProto_Array || i == JSProto_Object);
+
+ todo = ss->sprinter.offset;
+#if JS_HAS_SHARP_VARS
+ op = (JSOp)pc[len];
+ if (op == JSOP_DEFSHARP) {
+ pc += len;
+ cs = &js_CodeSpec[op];
+ len = cs->length;
+ if (Sprint(&ss->sprinter, "#%u=",
+ (unsigned) (jsint) GET_UINT16(pc)) < 0)
+ return NULL;
+ }
+#endif /* JS_HAS_SHARP_VARS */
+ if (i == JSProto_Array) {
+ ++ss->inArrayInit;
+ if (SprintCString(&ss->sprinter, "[") < 0)
+ return NULL;
+ } else {
+ if (SprintCString(&ss->sprinter, "{") < 0)
+ return NULL;
+ }
+ break;
+ }
+
+ case JSOP_ENDINIT:
+ {
+ JSBool inArray;
+
+ op = JSOP_NOP; /* turn off parens */
+ rval = POP_STR();
+ sn = js_GetSrcNote(jp->script, pc);
+
+ /* Skip any #n= prefix to find the opening bracket. */
+ for (xval = rval; *xval != '[' && *xval != '{'; xval++)
+ continue;
+ inArray = (*xval == '[');
+ if (inArray)
+ --ss->inArrayInit;
+ todo = Sprint(&ss->sprinter, "%s%s%c",
+ rval,
+ (sn && SN_TYPE(sn) == SRC_CONTINUE) ? ", " : "",
+ inArray ? ']' : '}');
+ break;
+ }
+
+ {
+ JSBool isFirst;
+ const char *maybeComma;
+
+ case JSOP_INITELEM:
+ isFirst = (ss->opcodes[ss->top - 3] == JSOP_NEWINIT);
+
+ /* Turn off most parens. */
+ op = JSOP_SETNAME;
+ rval = POP_STR();
+
+ /* Turn off all parens for xval and lval, which we control. */
+ op = JSOP_NOP;
+ xval = POP_STR();
+ lval = POP_STR();
+ sn = js_GetSrcNote(jp->script, pc);
+
+ if (sn && SN_TYPE(sn) == SRC_INITPROP) {
+ atom = NULL;
+ goto do_initprop;
+ }
+ maybeComma = isFirst ? "" : ", ";
+ todo = Sprint(&ss->sprinter, sss_format,
+ lval,
+ maybeComma,
+ rval);
+ break;
+
+ case JSOP_INITPROP:
+ LOAD_ATOM(0);
+ xval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ (jschar)
+ (ATOM_IS_IDENTIFIER(atom) ? 0 : '\''));
+ if (!xval)
+ return NULL;
+ isFirst = (ss->opcodes[ss->top - 2] == JSOP_NEWINIT);
+ rval = POP_STR();
+ lval = POP_STR();
+ /* fall through */
+
+ do_initprop:
+ maybeComma = isFirst ? "" : ", ";
+#ifdef OLD_GETTER_SETTER
+ todo = Sprint(&ss->sprinter, "%s%s%s%s%s%s%s:%s",
+ lval,
+ maybeComma,
+ xval,
+ (lastop == JSOP_GETTER || lastop == JSOP_SETTER)
+ ? " " : "",
+ (lastop == JSOP_GETTER) ? js_getter_str :
+ (lastop == JSOP_SETTER) ? js_setter_str :
+ "",
+ rval);
+#else
+ if (lastop == JSOP_GETTER || lastop == JSOP_SETTER) {
+ if (!atom ||
+ !ATOM_IS_STRING(atom) ||
+ !ATOM_IS_IDENTIFIER(atom) ||
+ ATOM_IS_KEYWORD(atom) ||
+ (ss->opcodes[ss->top+1] != JSOP_ANONFUNOBJ &&
+ ss->opcodes[ss->top+1] != JSOP_NAMEDFUNOBJ)) {
+ todo = Sprint(&ss->sprinter, "%s%s%s %s: %s",
+ lval,
+ maybeComma,
+ xval,
+ (lastop == JSOP_GETTER) ? js_getter_str :
+ (lastop == JSOP_SETTER) ? js_setter_str :
+ "",
+ rval);
+ } else {
+ const char *end = rval + strlen(rval);
+
+ if (*rval == '(')
+ ++rval, --end;
+ LOCAL_ASSERT(strncmp(rval, js_function_str, 8) == 0);
+ LOCAL_ASSERT(rval[8] == ' ');
+ rval += 8 + 1;
+ LOCAL_ASSERT(*end ? *end == ')' : end[-1] == '}');
+ todo = Sprint(&ss->sprinter, "%s%s%s %s%s%.*s",
+ lval,
+ maybeComma,
+ (lastop == JSOP_GETTER)
+ ? js_get_str : js_set_str,
+ xval,
+ (rval[0] != '(') ? " " : "",
+ end - rval, rval);
+ }
+ } else {
+ todo = Sprint(&ss->sprinter, "%s%s%s: %s",
+ lval, maybeComma, xval, rval);
+ }
+#endif
+ break;
+ }
+
+#if JS_HAS_SHARP_VARS
+ case JSOP_DEFSHARP:
+ i = (jsint) GET_UINT16(pc);
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "#%u=%s", (unsigned) i, rval);
+ break;
+
+ case JSOP_USESHARP:
+ i = (jsint) GET_UINT16(pc);
+ todo = Sprint(&ss->sprinter, "#%u#", (unsigned) i);
+ break;
+#endif /* JS_HAS_SHARP_VARS */
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ case JSOP_DEBUGGER:
+ js_printf(jp, "\tdebugger;\n");
+ todo = -2;
+ break;
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ case JSOP_STARTXML:
+ case JSOP_STARTXMLEXPR:
+ inXML = op == JSOP_STARTXML;
+ todo = -2;
+ break;
+
+ case JSOP_DEFXMLNS:
+ rval = POP_STR();
+ js_printf(jp, "\t%s %s %s = %s;\n",
+ js_default_str, js_xml_str, js_namespace_str, rval);
+ todo = -2;
+ break;
+
+ case JSOP_ANYNAME:
+ if (pc[JSOP_ANYNAME_LENGTH] == JSOP_TOATTRNAME) {
+ len += JSOP_TOATTRNAME_LENGTH;
+ todo = SprintPut(&ss->sprinter, "@*", 2);
+ } else {
+ todo = SprintPut(&ss->sprinter, "*", 1);
+ }
+ break;
+
+ case JSOP_QNAMEPART:
+ LOAD_ATOM(0);
+ if (pc[JSOP_QNAMEPART_LENGTH] == JSOP_TOATTRNAME) {
+ saveop = JSOP_TOATTRNAME;
+ len += JSOP_TOATTRNAME_LENGTH;
+ lval = "@";
+ goto do_qname;
+ }
+ goto do_name;
+
+ case JSOP_QNAMECONST:
+ LOAD_ATOM(0);
+ rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
+ if (!rval)
+ return NULL;
+ RETRACT(&ss->sprinter, rval);
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s::%s", lval, rval);
+ break;
+
+ case JSOP_QNAME:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s::[%s]", lval, rval);
+ break;
+
+ case JSOP_TOATTRNAME:
+ op = JSOP_NOP; /* turn off parens */
+ rval = POP_STR();
+ todo = Sprint(&ss->sprinter, "@[%s]", rval);
+ break;
+
+ case JSOP_TOATTRVAL:
+ todo = -2;
+ break;
+
+ case JSOP_ADDATTRNAME:
+ rval = POP_STR();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s %s", lval, rval);
+ /* This gets reset by all XML tag expressions. */
+ quoteAttr = JS_TRUE;
+ break;
+
+ case JSOP_ADDATTRVAL:
+ rval = POP_STR();
+ lval = POP_STR();
+ if (quoteAttr)
+ todo = Sprint(&ss->sprinter, "%s=\"%s\"", lval, rval);
+ else
+ todo = Sprint(&ss->sprinter, "%s=%s", lval, rval);
+ break;
+
+ case JSOP_BINDXMLNAME:
+ /* Leave the name stacked and push a dummy string. */
+ todo = Sprint(&ss->sprinter, "");
+ break;
+
+ case JSOP_SETXMLNAME:
+ /* Pop the r.h.s., the dummy string, and the name. */
+ rval = POP_STR();
+ (void) PopOff(ss, op);
+ lval = POP_STR();
+ goto do_setlval;
+
+ case JSOP_XMLELTEXPR:
+ case JSOP_XMLTAGEXPR:
+ todo = Sprint(&ss->sprinter, "{%s}", POP_STR());
+ inXML = JS_TRUE;
+ /* If we're an attribute value, we shouldn't quote this. */
+ quoteAttr = JS_FALSE;
+ break;
+
+ case JSOP_TOXMLLIST:
+ op = JSOP_NOP; /* turn off parens */
+ todo = Sprint(&ss->sprinter, "<>%s</>", POP_STR());
+ inXML = JS_FALSE;
+ break;
+
+ case JSOP_TOXML:
+ case JSOP_CALLXMLNAME:
+ case JSOP_XMLNAME:
+ case JSOP_FILTER:
+ /* These ops indicate the end of XML expressions. */
+ inXML = JS_FALSE;
+ todo = -2;
+ break;
+
+ case JSOP_ENDFILTER:
+ rval = POP_STR();
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s.(%s)", lval, rval);
+ break;
+
+ case JSOP_DESCENDANTS:
+ rval = POP_STR();
+ PROPAGATE_CALLNESS();
+ lval = POP_STR();
+ todo = Sprint(&ss->sprinter, "%s..%s", lval, rval);
+ break;
+
+ case JSOP_XMLOBJECT:
+ LOAD_OBJECT(0);
+ todo = Sprint(&ss->sprinter, "<xml address='%p'>", obj);
+ break;
+
+ case JSOP_XMLCDATA:
+ LOAD_ATOM(0);
+ todo = SprintPut(&ss->sprinter, "<![CDATA[", 9);
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ DONT_ESCAPE))
+ return NULL;
+ SprintPut(&ss->sprinter, "]]>", 3);
+ break;
+
+ case JSOP_XMLCOMMENT:
+ LOAD_ATOM(0);
+ todo = SprintPut(&ss->sprinter, "<!--", 4);
+ if (!QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
+ DONT_ESCAPE))
+ return NULL;
+ SprintPut(&ss->sprinter, "-->", 3);
+ break;
+
+ case JSOP_XMLPI:
+ LOAD_ATOM(0);
+ rval = JS_strdup(cx, POP_STR());
+ if (!rval)
+ return NULL;
+ todo = SprintPut(&ss->sprinter, "<?", 2);
+ ok = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0) &&
+ (*rval == '\0' ||
+ (SprintPut(&ss->sprinter, " ", 1) >= 0 &&
+ SprintCString(&ss->sprinter, rval)));
+ JS_free(cx, (char *)rval);
+ if (!ok)
+ return NULL;
+ SprintPut(&ss->sprinter, "?>", 2);
+ break;
+
+ case JSOP_GETFUNNS:
+ todo = SprintPut(&ss->sprinter, js_function_str, 8);
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ default:
+ todo = -2;
+ break;
+ }
+ }
+
+ if (todo < 0) {
+ /* -2 means "don't push", -1 means reported error. */
+ if (todo == -1)
+ return NULL;
+ } else {
+ if (!PushOff(ss, todo, saveop))
+ return NULL;
+ }
+
+ if (cs->format & JOF_CALLOP) {
+ todo = Sprint(&ss->sprinter, "");
+ if (todo < 0 || !PushOff(ss, todo, saveop))
+ return NULL;
+ }
+
+ pc += len;
+ }
+
+/*
+ * Undefine local macros.
+ */
+#undef inXML
+#undef DECOMPILE_CODE
+#undef NEXT_OP
+#undef TOP_STR
+#undef POP_STR
+#undef POP_STR_PREC
+#undef LOCAL_ASSERT
+#undef ATOM_IS_IDENTIFIER
+#undef GET_QUOTE_AND_FMT
+#undef GET_ATOM_QUOTE_AND_FMT
+
+ return pc;
+}
+
+static JSBool
+DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
+ uintN pcdepth)
+{
+ uintN depth, i;
+ SprintStack ss;
+ JSContext *cx;
+ void *mark;
+ JSBool ok;
+ JSScript *oldscript;
+ jsbytecode *oldcode, *oldmain, *code;
+ char *last;
+
+ depth = StackDepth(script);
+ JS_ASSERT(pcdepth <= depth);
+
+ /* Initialize a sprinter for use with the offset stack. */
+ cx = jp->sprinter.context;
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ ok = InitSprintStack(cx, &ss, jp, depth);
+ if (!ok)
+ goto out;
+
+ /*
+ * If we are called from js_DecompileValueGenerator with a portion of
+ * script's bytecode that starts with a non-zero model stack depth given
+ * by pcdepth, attempt to initialize the missing string offsets in ss to
+ * |spindex| negative indexes from fp->sp for the activation fp in which
+ * the error arose.
+ *
+ * See js_DecompileValueGenerator for how its |spindex| parameter is used,
+ * and see also GetOff, which makes use of the ss.offsets[i] < -1 that are
+ * potentially stored below.
+ */
+ ss.top = pcdepth;
+ if (pcdepth != 0) {
+ for (i = 0; i < pcdepth; i++) {
+ ss.offsets[i] = -2 - (ptrdiff_t)i;
+ ss.opcodes[i] = *jp->pcstack[i];
+ }
+ }
+
+ /* Call recursive subroutine to do the hard work. */
+ oldscript = jp->script;
+ jp->script = script;
+ oldcode = jp->script->code;
+ oldmain = jp->script->main;
+ code = js_UntrapScriptCode(cx, jp->script);
+ if (code != oldcode) {
+ jp->script->code = code;
+ jp->script->main = code + (oldmain - oldcode);
+ pc = code + (pc - oldcode);
+ }
+
+ ok = Decompile(&ss, pc, len, JSOP_NOP) != NULL;
+ if (code != oldcode) {
+ JS_free(cx, jp->script->code);
+ jp->script->code = oldcode;
+ jp->script->main = oldmain;
+ }
+ jp->script = oldscript;
+
+ /* If the given code didn't empty the stack, do it now. */
+ if (ok && ss.top) {
+ do {
+ last = OFF2STR(&ss.sprinter, PopOff(&ss, JSOP_POP));
+ } while (ss.top > pcdepth);
+ js_printf(jp, "%s", last);
+ }
+
+out:
+ /* Free all temporary stuff allocated under this call. */
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return ok;
+}
+
+JSBool
+js_DecompileScript(JSPrinter *jp, JSScript *script)
+{
+ return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
+}
+
+static const char native_code_str[] = "\t[native code]\n";
+
+JSBool
+js_DecompileFunctionBody(JSPrinter *jp)
+{
+ JSScript *script;
+
+ JS_ASSERT(jp->fun);
+ JS_ASSERT(!jp->script);
+ if (!FUN_INTERPRETED(jp->fun)) {
+ js_printf(jp, native_code_str);
+ return JS_TRUE;
+ }
+
+ script = jp->fun->u.i.script;
+ return DecompileCode(jp, script, script->code, (uintN)script->length, 0);
+}
+
+JSBool
+js_DecompileFunction(JSPrinter *jp)
+{
+ JSFunction *fun;
+ uintN i;
+ JSAtom *param;
+ jsbytecode *pc, *endpc;
+ ptrdiff_t len;
+ JSBool ok;
+
+ fun = jp->fun;
+ JS_ASSERT(fun);
+ JS_ASSERT(!jp->script);
+
+ /*
+ * If pretty, conform to ECMA-262 Edition 3, 15.3.4.2, by decompiling a
+ * FunctionDeclaration. Otherwise, check the JSFUN_LAMBDA flag and force
+ * an expression by parenthesizing.
+ */
+ if (jp->pretty) {
+ js_printf(jp, "\t");
+ } else {
+ if (!jp->grouped && (fun->flags & JSFUN_LAMBDA))
+ js_puts(jp, "(");
+ }
+ if (JSFUN_GETTER_TEST(fun->flags))
+ js_printf(jp, "%s ", js_getter_str);
+ else if (JSFUN_SETTER_TEST(fun->flags))
+ js_printf(jp, "%s ", js_setter_str);
+
+ js_printf(jp, "%s ", js_function_str);
+ if (fun->atom && !QuoteString(&jp->sprinter, ATOM_TO_STRING(fun->atom), 0))
+ return JS_FALSE;
+ js_puts(jp, "(");
+
+ if (!FUN_INTERPRETED(fun)) {
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ js_printf(jp, native_code_str);
+ jp->indent -= 4;
+ js_printf(jp, "\t}");
+ } else {
+#ifdef JS_HAS_DESTRUCTURING
+ SprintStack ss;
+ void *mark;
+#endif
+
+ /* Print the parameters. */
+ pc = fun->u.i.script->main;
+ endpc = pc + fun->u.i.script->length;
+ ok = JS_TRUE;
+
+#ifdef JS_HAS_DESTRUCTURING
+ /* Skip JSOP_GENERATOR in case of destructuring parameters. */
+ if (*pc == JSOP_GENERATOR)
+ pc += JSOP_GENERATOR_LENGTH;
+
+ ss.printer = NULL;
+ jp->script = fun->u.i.script;
+ mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
+#endif
+
+ for (i = 0; i < fun->nargs; i++) {
+ if (i > 0)
+ js_puts(jp, ", ");
+
+ param = GetArgOrVarAtom(jp, i);
+
+#if JS_HAS_DESTRUCTURING
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, JS_FALSE)
+
+ if (!param) {
+ ptrdiff_t todo;
+ const char *lval;
+
+ LOCAL_ASSERT(*pc == JSOP_GETARG);
+ pc += JSOP_GETARG_LENGTH;
+ LOCAL_ASSERT(*pc == JSOP_DUP);
+ if (!ss.printer) {
+ ok = InitSprintStack(jp->sprinter.context, &ss, jp,
+ StackDepth(fun->u.i.script));
+ if (!ok)
+ break;
+ }
+ pc = DecompileDestructuring(&ss, pc, endpc);
+ if (!pc) {
+ ok = JS_FALSE;
+ break;
+ }
+ LOCAL_ASSERT(*pc == JSOP_POP);
+ pc += JSOP_POP_LENGTH;
+ lval = PopStr(&ss, JSOP_NOP);
+ todo = SprintCString(&jp->sprinter, lval);
+ if (todo < 0) {
+ ok = JS_FALSE;
+ break;
+ }
+ continue;
+ }
+
+#undef LOCAL_ASSERT
+#endif
+
+ if (!QuoteString(&jp->sprinter, ATOM_TO_STRING(param), 0)) {
+ ok = JS_FALSE;
+ break;
+ }
+ }
+
+#ifdef JS_HAS_DESTRUCTURING
+ jp->script = NULL;
+ JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
+#endif
+ if (!ok)
+ return JS_FALSE;
+ if (fun->flags & JSFUN_EXPR_CLOSURE) {
+ js_printf(jp, ") ");
+ } else {
+ js_printf(jp, ") {\n");
+ jp->indent += 4;
+ }
+
+ len = fun->u.i.script->code + fun->u.i.script->length - pc;
+ ok = DecompileCode(jp, fun->u.i.script, pc, (uintN)len, 0);
+ if (!ok)
+ return JS_FALSE;
+
+ if (!(fun->flags & JSFUN_EXPR_CLOSURE)) {
+ jp->indent -= 4;
+ js_printf(jp, "\t}");
+ }
+ }
+
+ if (!jp->pretty && !jp->grouped && (fun->flags & JSFUN_LAMBDA))
+ js_puts(jp, ")");
+
+ return JS_TRUE;
+}
+
+char *
+js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback)
+{
+ JSStackFrame *fp;
+ jsbytecode *pc;
+ JSScript *script;
+ JSFrameRegs *regs;
+ intN pcdepth;
+ jsval *sp, *stackBase;
+ char *name;
+
+ JS_ASSERT(spindex < 0 ||
+ spindex == JSDVG_IGNORE_STACK ||
+ spindex == JSDVG_SEARCH_STACK);
+
+ for (fp = cx->fp; fp && !fp->script; fp = fp->down)
+ continue;
+ if (!fp || !fp->regs)
+ goto do_fallback;
+
+ script = fp->script;
+ regs = fp->regs;
+ pc = fp->imacpc ? fp->imacpc : regs->pc;
+ if (pc < script->main || script->code + script->length <= pc) {
+ JS_NOT_REACHED("bug");
+ goto do_fallback;
+ }
+
+ if (spindex != JSDVG_IGNORE_STACK) {
+ jsbytecode **pcstack;
+
+ /*
+ * Prepare computing pcstack containing pointers to opcodes that
+ * populated interpreter's stack with its current content.
+ */
+ pcstack = (jsbytecode **)
+ JS_malloc(cx, StackDepth(script) * sizeof *pcstack);
+ if (!pcstack)
+ return NULL;
+ pcdepth = ReconstructPCStack(cx, script, pc, pcstack);
+ if (pcdepth < 0)
+ goto release_pcstack;
+
+ if (spindex != JSDVG_SEARCH_STACK) {
+ JS_ASSERT(spindex < 0);
+ pcdepth += spindex;
+ if (pcdepth < 0)
+ goto release_pcstack;
+ pc = pcstack[pcdepth];
+ } else {
+ /*
+ * We search from fp->sp to base to find the most recently
+ * calculated value matching v under assumption that it is
+ * it that caused exception, see bug 328664.
+ */
+ stackBase = StackBase(fp);
+ sp = regs->sp;
+ do {
+ if (sp == stackBase) {
+ pcdepth = -1;
+ goto release_pcstack;
+ }
+ } while (*--sp != v);
+
+ if (sp >= stackBase + pcdepth) {
+ /*
+ * The value comes from a temporary slot that the interpreter
+ * uses for GC roots or when JSOP_APPLY extended the stack to
+ * fit the argument array elements. Assume that it is the
+ * current PC that caused the exception.
+ */
+ pc = fp->imacpc ? fp->imacpc : regs->pc;
+ } else {
+ pc = pcstack[sp - stackBase];
+ }
+ }
+
+ release_pcstack:
+ JS_free(cx, pcstack);
+ if (pcdepth < 0)
+ goto do_fallback;
+ }
+
+ {
+ jsbytecode* savepc = regs->pc;
+ jsbytecode* imacpc = fp->imacpc;
+ if (imacpc) {
+ regs->pc = imacpc;
+ fp->imacpc = NULL;
+ }
+ name = DecompileExpression(cx, script, fp->fun, pc);
+ if (imacpc) {
+ regs->pc = savepc;
+ fp->imacpc = imacpc;
+ }
+ }
+ if (name != FAILED_EXPRESSION_DECOMPILER)
+ return name;
+
+ do_fallback:
+ if (!fallback) {
+ fallback = js_ValueToSource(cx, v);
+ if (!fallback)
+ return NULL;
+ }
+ return js_DeflateString(cx, JSSTRING_CHARS(fallback),
+ JSSTRING_LENGTH(fallback));
+}
+
+static char *
+DecompileExpression(JSContext *cx, JSScript *script, JSFunction *fun,
+ jsbytecode *pc)
+{
+ jsbytecode *code, *oldcode, *oldmain;
+ JSOp op;
+ const JSCodeSpec *cs;
+ jsbytecode *begin, *end;
+ jssrcnote *sn;
+ ptrdiff_t len;
+ jsbytecode **pcstack;
+ intN pcdepth;
+ JSPrinter *jp;
+ char *name;
+
+ JS_ASSERT(script->main <= pc && pc < script->code + script->length);
+
+ pcstack = NULL;
+ oldcode = script->code;
+ oldmain = script->main;
+
+ MUST_FLOW_THROUGH("out");
+ code = js_UntrapScriptCode(cx, script);
+ if (code != oldcode) {
+ script->code = code;
+ script->main = code + (oldmain - oldcode);
+ pc = code + (pc - oldcode);
+ }
+
+ op = (JSOp) *pc;
+
+ /* None of these stack-writing ops generates novel values. */
+ JS_ASSERT(op != JSOP_CASE && op != JSOP_CASEX &&
+ op != JSOP_DUP && op != JSOP_DUP2);
+
+ /*
+ * |this| could convert to a very long object initialiser, so cite it by
+ * its keyword name instead.
+ */
+ if (op == JSOP_THIS) {
+ name = JS_strdup(cx, js_this_str);
+ goto out;
+ }
+
+ /*
+ * JSOP_BINDNAME is special: it generates a value, the base object of a
+ * reference. But if it is the generating op for a diagnostic produced by
+ * js_DecompileValueGenerator, the name being bound is irrelevant. Just
+ * fall back to the base object.
+ */
+ if (op == JSOP_BINDNAME) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+
+ /* NAME ops are self-contained, others require left or right context. */
+ cs = &js_CodeSpec[op];
+ begin = pc;
+ end = pc + cs->length;
+ switch (JOF_MODE(cs->format)) {
+ case JOF_PROP:
+ case JOF_ELEM:
+ case JOF_XMLNAME:
+ case 0:
+ sn = js_GetSrcNote(script, pc);
+ if (!sn) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+ switch (SN_TYPE(sn)) {
+ case SRC_PCBASE:
+ begin -= js_GetSrcNoteOffset(sn, 0);
+ break;
+ case SRC_PCDELTA:
+ end = begin + js_GetSrcNoteOffset(sn, 0);
+ begin += cs->length;
+ break;
+ default:
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+ break;
+ default:;
+ }
+ len = PTRDIFF(end, begin, jsbytecode);
+ if (len <= 0) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+
+ pcstack = (jsbytecode **)
+ JS_malloc(cx, StackDepth(script) * sizeof *pcstack);
+ if (!pcstack) {
+ name = NULL;
+ goto out;
+ }
+
+ MUST_FLOW_THROUGH("out");
+ pcdepth = ReconstructPCStack(cx, script, begin, pcstack);
+ if (pcdepth < 0) {
+ name = FAILED_EXPRESSION_DECOMPILER;
+ goto out;
+ }
+
+ name = NULL;
+ jp = JS_NEW_PRINTER(cx, "js_DecompileValueGenerator", fun, 0, JS_FALSE);
+ if (jp) {
+ jp->dvgfence = end;
+ jp->pcstack = pcstack;
+ if (DecompileCode(jp, script, begin, (uintN) len, (uintN) pcdepth)) {
+ name = (jp->sprinter.base) ? jp->sprinter.base : (char *) "";
+ name = JS_strdup(cx, name);
+ }
+ js_DestroyPrinter(jp);
+ }
+
+ out:
+ if (code != oldcode) {
+ JS_free(cx, script->code);
+ script->code = oldcode;
+ script->main = oldmain;
+ }
+
+ JS_free(cx, pcstack);
+ return name;
+}
+
+uintN
+js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ return ReconstructPCStack(cx, script, pc, NULL);
+}
+
+static intN
+ReconstructPCStack(JSContext *cx, JSScript *script, jsbytecode *target,
+ jsbytecode **pcstack)
+{
+ intN pcdepth, nuses, ndefs;
+ jsbytecode *pc;
+ JSOp op;
+ const JSCodeSpec *cs;
+ ptrdiff_t oplen;
+ jssrcnote *sn;
+ intN i;
+
+#define LOCAL_ASSERT(expr) LOCAL_ASSERT_RV(expr, -1);
+
+ /*
+ * Walk forward from script->main and compute the stack depth and stack of
+ * operand-generating opcode PCs in pcstack.
+ *
+ * FIXME: Code to compute oplen copied from js_Disassemble1 and reduced.
+ * FIXME: Optimize to use last empty-stack sequence point.
+ */
+ LOCAL_ASSERT(script->main <= target && target < script->code + script->length);
+ pcdepth = 0;
+ for (pc = script->main; pc < target; pc += oplen) {
+ op = (JSOp) *pc;
+ if (op == JSOP_TRAP)
+ op = JS_GetTrapOpcode(cx, script, pc);
+ cs = &js_CodeSpec[op];
+ oplen = cs->length;
+ if (oplen < 0)
+ oplen = js_GetVariableBytecodeLength(pc);
+
+ /*
+ * A (C ? T : E) expression requires skipping either T (if target is in
+ * E) or both T and E (if target is after the whole expression) before
+ * adjusting pcdepth based on the JSOP_IFEQ or JSOP_IFEQX at pc that
+ * tests condition C. We know that the stack depth can't change from
+ * what it was with C on top of stack.
+ */
+ sn = js_GetSrcNote(script, pc);
+ if (sn && SN_TYPE(sn) == SRC_COND) {
+ ptrdiff_t jmpoff, jmplen;
+
+ jmpoff = js_GetSrcNoteOffset(sn, 0);
+ if (pc + jmpoff < target) {
+ pc += jmpoff;
+ op = (JSOp) *pc;
+ JS_ASSERT(op == JSOP_GOTO || op == JSOP_GOTOX);
+ cs = &js_CodeSpec[op];
+ oplen = cs->length;
+ JS_ASSERT(oplen > 0);
+ jmplen = GetJumpOffset(pc, pc);
+ if (pc + jmplen < target) {
+ oplen = (uintN) jmplen;
+ continue;
+ }
+
+ /*
+ * Ok, target lies in E. Manually pop C off the model stack,
+ * since we have moved beyond the IFEQ now.
+ */
+ --pcdepth;
+ LOCAL_ASSERT(pcdepth >= 0);
+ }
+ }
+
+ if (sn && SN_TYPE(sn) == SRC_HIDDEN)
+ continue;
+
+ nuses = cs->nuses;
+ if (nuses < 0)
+ nuses = js_GetVariableStackUseLength(op, pc);
+
+ ndefs = cs->ndefs;
+ if (ndefs < 0) {
+ JSObject *obj;
+
+ JS_ASSERT(op == JSOP_ENTERBLOCK);
+ GET_OBJECT_FROM_BYTECODE(script, pc, 0, obj);
+ JS_ASSERT(OBJ_BLOCK_DEPTH(cx, obj) == pcdepth);
+ ndefs = OBJ_BLOCK_COUNT(cx, obj);
+ }
+
+ pcdepth -= nuses;
+ LOCAL_ASSERT(pcdepth >= 0);
+ LOCAL_ASSERT((uintN)(pcdepth + ndefs) <= StackDepth(script));
+
+ /*
+ * Fill the slots that the opcode defines withs its pc unless it just
+ * reshuffle the stack. In the latter case we want to preserve the
+ * opcode that generated the original value.
+ */
+ switch (op) {
+ default:
+ if (pcstack) {
+ for (i = 0; i != ndefs; ++i)
+ pcstack[pcdepth + i] = pc;
+ }
+ break;
+
+ case JSOP_CASE:
+ case JSOP_CASEX:
+ /* Keep the switch value. */
+ JS_ASSERT(ndefs == 1);
+ break;
+
+ case JSOP_DUP:
+ JS_ASSERT(ndefs == 2);
+ if (pcstack)
+ pcstack[pcdepth + 1] = pcstack[pcdepth];
+ break;
+
+ case JSOP_DUP2:
+ JS_ASSERT(ndefs == 4);
+ if (pcstack) {
+ pcstack[pcdepth + 2] = pcstack[pcdepth];
+ pcstack[pcdepth + 3] = pcstack[pcdepth + 1];
+ }
+ break;
+ }
+ pcdepth += ndefs;
+ }
+ LOCAL_ASSERT(pc == target);
+ return pcdepth;
+
+#undef LOCAL_ASSERT
+}
+
+#undef LOCAL_ASSERT_RV
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h
new file mode 100644
index 0000000..6ce8a40
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.h
@@ -0,0 +1,404 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsopcode_h___
+#define jsopcode_h___
+/*
+ * JS bytecode definitions.
+ */
+#include <stddef.h>
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsutil.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * JS operation bytecodes.
+ */
+typedef enum JSOp {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ op = val,
+#include "jsopcode.tbl"
+#undef OPDEF
+ JSOP_LIMIT
+} JSOp;
+
+/*
+ * JS bytecode formats.
+ */
+#define JOF_BYTE 0 /* single bytecode, no immediates */
+#define JOF_JUMP 1 /* signed 16-bit jump offset immediate */
+#define JOF_ATOM 2 /* unsigned 16-bit constant pool index */
+#define JOF_UINT16 3 /* unsigned 16-bit immediate operand */
+#define JOF_TABLESWITCH 4 /* table switch */
+#define JOF_LOOKUPSWITCH 5 /* lookup switch */
+#define JOF_QARG 6 /* quickened get/set function argument ops */
+#define JOF_LOCAL 7 /* var or block-local variable */
+#define JOF_SLOTATOM 8 /* uint16 slot index + constant pool index */
+#define JOF_JUMPX 9 /* signed 32-bit jump offset immediate */
+#define JOF_TABLESWITCHX 10 /* extended (32-bit offset) table switch */
+#define JOF_LOOKUPSWITCHX 11 /* extended (32-bit offset) lookup switch */
+#define JOF_UINT24 12 /* extended unsigned 24-bit literal (index) */
+#define JOF_UINT8 13 /* uint8 immediate, e.g. top 8 bits of 24-bit
+ atom index */
+#define JOF_INT32 14 /* int32 immediate operand */
+#define JOF_OBJECT 15 /* unsigned 16-bit object pool index */
+#define JOF_SLOTOBJECT 16 /* uint16 slot index + object pool index */
+#define JOF_REGEXP 17 /* unsigned 16-bit regexp pool index */
+#define JOF_INT8 18 /* int8 immediate operand */
+#define JOF_TYPEMASK 0x001f /* mask for above immediate types */
+
+#define JOF_NAME (1U<<5) /* name operation */
+#define JOF_PROP (2U<<5) /* obj.prop operation */
+#define JOF_ELEM (3U<<5) /* obj[index] operation */
+#define JOF_XMLNAME (4U<<5) /* XML name: *, a::b, @a, @a::b, etc. */
+#define JOF_VARPROP (5U<<5) /* x.prop for this, arg, var, or local x */
+#define JOF_MODEMASK (7U<<5) /* mask for above addressing modes */
+#define JOF_SET (1U<<8) /* set (i.e., assignment) operation */
+#define JOF_DEL (1U<<9) /* delete operation */
+#define JOF_DEC (1U<<10) /* decrement (--, not ++) opcode */
+#define JOF_INC (2U<<10) /* increment (++, not --) opcode */
+#define JOF_INCDEC (3U<<10) /* increment or decrement opcode */
+#define JOF_POST (1U<<12) /* postorder increment or decrement */
+#define JOF_FOR (1U<<13) /* for-in property op (akin to JOF_SET) */
+#define JOF_ASSIGNING JOF_SET /* hint for JSClass.resolve, used for ops
+ that do simplex assignment */
+#define JOF_DETECTING (1U<<14) /* object detection for JSNewResolveOp */
+#define JOF_BACKPATCH (1U<<15) /* backpatch placeholder during codegen */
+#define JOF_LEFTASSOC (1U<<16) /* left-associative operator */
+#define JOF_DECLARING (1U<<17) /* var, const, or function declaration op */
+#define JOF_INDEXBASE (1U<<18) /* atom segment base setting prefix op */
+#define JOF_CALLOP (1U<<19) /* call operation that pushes function and
+ this */
+#define JOF_PARENHEAD (1U<<20) /* opcode consumes value of expression in
+ parenthesized statement head */
+#define JOF_INVOKE (1U<<21) /* JSOP_CALL, JSOP_NEW, JSOP_EVAL */
+#define JOF_TMPSLOT (1U<<22) /* interpreter uses extra temporary slot
+ to root intermediate objects besides
+ the slots opcode uses */
+#define JOF_TMPSLOT2 (2U<<22) /* interpreter uses extra 2 temporary slot
+ besides the slots opcode uses */
+#define JOF_TMPSLOT_SHIFT 22
+#define JOF_TMPSLOT_MASK (JS_BITMASK(2) << JOF_TMPSLOT_SHIFT)
+
+/* Shorthands for type from format and type from opcode. */
+#define JOF_TYPE(fmt) ((fmt) & JOF_TYPEMASK)
+#define JOF_OPTYPE(op) JOF_TYPE(js_CodeSpec[op].format)
+
+/* Shorthands for mode from format and mode from opcode. */
+#define JOF_MODE(fmt) ((fmt) & JOF_MODEMASK)
+#define JOF_OPMODE(op) JOF_MODE(js_CodeSpec[op].format)
+
+#define JOF_TYPE_IS_EXTENDED_JUMP(t) \
+ ((unsigned)((t) - JOF_JUMPX) <= (unsigned)(JOF_LOOKUPSWITCHX - JOF_JUMPX))
+
+/*
+ * Immediate operand getters, setters, and bounds.
+ */
+
+/* Common uint16 immediate format helpers. */
+#define UINT16_LEN 2
+#define UINT16_HI(i) ((jsbytecode)((i) >> 8))
+#define UINT16_LO(i) ((jsbytecode)(i))
+#define GET_UINT16(pc) ((uintN)(((pc)[1] << 8) | (pc)[2]))
+#define SET_UINT16(pc,i) ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
+#define UINT16_LIMIT ((uintN)1 << 16)
+
+/* Short (2-byte signed offset) relative jump macros. */
+#define JUMP_OFFSET_LEN 2
+#define JUMP_OFFSET_HI(off) ((jsbytecode)((off) >> 8))
+#define JUMP_OFFSET_LO(off) ((jsbytecode)(off))
+#define GET_JUMP_OFFSET(pc) ((int16)GET_UINT16(pc))
+#define SET_JUMP_OFFSET(pc,off) ((pc)[1] = JUMP_OFFSET_HI(off), \
+ (pc)[2] = JUMP_OFFSET_LO(off))
+#define JUMP_OFFSET_MIN ((int16)0x8000)
+#define JUMP_OFFSET_MAX ((int16)0x7fff)
+
+/*
+ * When a short jump won't hold a relative offset, its 2-byte immediate offset
+ * operand is an unsigned index of a span-dependency record, maintained until
+ * code generation finishes -- after which some (but we hope not nearly all)
+ * span-dependent jumps must be extended (see OptimizeSpanDeps in jsemit.c).
+ *
+ * If the span-dependency record index overflows SPANDEP_INDEX_MAX, the jump
+ * offset will contain SPANDEP_INDEX_HUGE, indicating that the record must be
+ * found (via binary search) by its "before span-dependency optimization" pc
+ * offset (from script main entry point).
+ */
+#define GET_SPANDEP_INDEX(pc) ((uint16)GET_UINT16(pc))
+#define SET_SPANDEP_INDEX(pc,i) ((pc)[1] = JUMP_OFFSET_HI(i), \
+ (pc)[2] = JUMP_OFFSET_LO(i))
+#define SPANDEP_INDEX_MAX ((uint16)0xfffe)
+#define SPANDEP_INDEX_HUGE ((uint16)0xffff)
+
+/* Ultimately, if short jumps won't do, emit long (4-byte signed) offsets. */
+#define JUMPX_OFFSET_LEN 4
+#define JUMPX_OFFSET_B3(off) ((jsbytecode)((off) >> 24))
+#define JUMPX_OFFSET_B2(off) ((jsbytecode)((off) >> 16))
+#define JUMPX_OFFSET_B1(off) ((jsbytecode)((off) >> 8))
+#define JUMPX_OFFSET_B0(off) ((jsbytecode)(off))
+#define GET_JUMPX_OFFSET(pc) ((int32)(((pc)[1] << 24) | ((pc)[2] << 16) \
+ | ((pc)[3] << 8) | (pc)[4]))
+#define SET_JUMPX_OFFSET(pc,off)((pc)[1] = JUMPX_OFFSET_B3(off), \
+ (pc)[2] = JUMPX_OFFSET_B2(off), \
+ (pc)[3] = JUMPX_OFFSET_B1(off), \
+ (pc)[4] = JUMPX_OFFSET_B0(off))
+#define JUMPX_OFFSET_MIN ((int32)0x80000000)
+#define JUMPX_OFFSET_MAX ((int32)0x7fffffff)
+
+/*
+ * A literal is indexed by a per-script atom or object maps. Most scripts
+ * have relatively few literals, so the standard JOF_ATOM, JOF_OBJECT and
+ * JOF_REGEXP formats specifies a fixed 16 bits of immediate operand index.
+ * A script with more than 64K literals must wrap the bytecode into
+ * JSOP_INDEXBASE and JSOP_RESETBASE pair.
+ */
+#define INDEX_LEN 2
+#define INDEX_HI(i) ((jsbytecode)((i) >> 8))
+#define INDEX_LO(i) ((jsbytecode)(i))
+#define GET_INDEX(pc) GET_UINT16(pc)
+#define SET_INDEX(pc,i) ((pc)[1] = INDEX_HI(i), (pc)[2] = INDEX_LO(i))
+
+#define GET_INDEXBASE(pc) (JS_ASSERT(*(pc) == JSOP_INDEXBASE), \
+ ((uintN)((pc)[1])) << 16)
+#define INDEXBASE_LEN 1
+
+#define UINT24_HI(i) ((jsbytecode)((i) >> 16))
+#define UINT24_MID(i) ((jsbytecode)((i) >> 8))
+#define UINT24_LO(i) ((jsbytecode)(i))
+#define GET_UINT24(pc) ((jsatomid)(((pc)[1] << 16) | \
+ ((pc)[2] << 8) | \
+ (pc)[3]))
+#define SET_UINT24(pc,i) ((pc)[1] = UINT24_HI(i), \
+ (pc)[2] = UINT24_MID(i), \
+ (pc)[3] = UINT24_LO(i))
+
+#define GET_INT8(pc) ((jsint)(int8)(pc)[1])
+
+#define GET_INT32(pc) ((jsint)(((uint32)((pc)[1]) << 24) | \
+ ((uint32)((pc)[2]) << 16) | \
+ ((uint32)((pc)[3]) << 8) | \
+ (uint32)(pc)[4]))
+#define SET_INT32(pc,i) ((pc)[1] = (jsbytecode)((uint32)(i) >> 24), \
+ (pc)[2] = (jsbytecode)((uint32)(i) >> 16), \
+ (pc)[3] = (jsbytecode)((uint32)(i) >> 8), \
+ (pc)[4] = (jsbytecode)(uint32)(i))
+
+/* Index limit is determined by SN_3BYTE_OFFSET_FLAG, see jsemit.h. */
+#define INDEX_LIMIT_LOG2 23
+#define INDEX_LIMIT ((uint32)1 << INDEX_LIMIT_LOG2)
+
+JS_STATIC_ASSERT(sizeof(uint32) * JS_BITS_PER_BYTE >= INDEX_LIMIT_LOG2 + 1);
+
+/* Actual argument count operand format helpers. */
+#define ARGC_HI(argc) UINT16_HI(argc)
+#define ARGC_LO(argc) UINT16_LO(argc)
+#define GET_ARGC(pc) GET_UINT16(pc)
+#define ARGC_LIMIT UINT16_LIMIT
+
+/* Synonyms for quick JOF_QARG and JOF_LOCAL bytecodes. */
+#define GET_ARGNO(pc) GET_UINT16(pc)
+#define SET_ARGNO(pc,argno) SET_UINT16(pc,argno)
+#define ARGNO_LEN 2
+#define ARGNO_LIMIT UINT16_LIMIT
+
+#define GET_SLOTNO(pc) GET_UINT16(pc)
+#define SET_SLOTNO(pc,varno) SET_UINT16(pc,varno)
+#define SLOTNO_LEN 2
+#define SLOTNO_LIMIT UINT16_LIMIT
+
+struct JSCodeSpec {
+ int8 length; /* length including opcode byte */
+ int8 nuses; /* arity, -1 if variadic */
+ int8 ndefs; /* number of stack results */
+ uint8 prec; /* operator precedence */
+ uint32 format; /* immediate operand format */
+};
+
+extern const JSCodeSpec js_CodeSpec[];
+extern uintN js_NumCodeSpecs;
+extern const char *js_CodeName[];
+extern const char js_EscapeMap[];
+
+/*
+ * Return a GC'ed string containing the chars in str, with any non-printing
+ * chars or quotes (' or " as specified by the quote argument) escaped, and
+ * with the quote character at the beginning and end of the result string.
+ */
+extern JSString *
+js_QuoteString(JSContext *cx, JSString *str, jschar quote);
+
+/*
+ * JSPrinter operations, for printf style message formatting. The return
+ * value from js_GetPrinterOutput() is the printer's cumulative output, in
+ * a GC'ed string.
+ */
+
+#ifdef JS_ARENAMETER
+# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
+ js_NewPrinter(cx, name, fun, indent, pretty)
+#else
+# define JS_NEW_PRINTER(cx, name, fun, indent, pretty) \
+ js_NewPrinter(cx, fun, indent, pretty)
+#endif
+
+extern JSPrinter *
+JS_NEW_PRINTER(JSContext *cx, const char *name, JSFunction *fun,
+ uintN indent, JSBool pretty);
+
+extern void
+js_DestroyPrinter(JSPrinter *jp);
+
+extern JSString *
+js_GetPrinterOutput(JSPrinter *jp);
+
+extern int
+js_printf(JSPrinter *jp, const char *format, ...);
+
+extern JSBool
+js_puts(JSPrinter *jp, const char *s);
+
+/*
+ * Get index operand from the bytecode using a bytecode analysis to deduce the
+ * the index register. This function is infallible, in spite of taking cx as
+ * its first parameter; it uses only cx->runtime when calling JS_GetTrapOpcode.
+ * The GET_*_FROM_BYTECODE macros that call it pick up cx from their caller's
+ * lexical environments.
+ */
+uintN
+js_GetIndexFromBytecode(JSContext *cx, JSScript *script, jsbytecode *pc,
+ ptrdiff_t pcoff);
+
+/*
+ * A slower version of GET_ATOM when the caller does not want to maintain
+ * the index segment register itself.
+ */
+#define GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_ATOM((script), index_, atom); \
+ JS_END_MACRO
+
+#define GET_OBJECT_FROM_BYTECODE(script, pc, pcoff, obj) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_OBJECT((script), index_, obj); \
+ JS_END_MACRO
+
+#define GET_FUNCTION_FROM_BYTECODE(script, pc, pcoff, fun) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_FUNCTION((script), index_, fun); \
+ JS_END_MACRO
+
+#define GET_REGEXP_FROM_BYTECODE(script, pc, pcoff, obj) \
+ JS_BEGIN_MACRO \
+ uintN index_ = js_GetIndexFromBytecode(cx, (script), (pc), (pcoff)); \
+ JS_GET_SCRIPT_REGEXP((script), index_, obj); \
+ JS_END_MACRO
+
+/*
+ * Get the length of variable-length bytecode like JSOP_TABLESWITCH.
+ */
+extern uintN
+js_GetVariableBytecodeLength(jsbytecode *pc);
+
+/*
+ * Find the number of stack slots used by a variadic opcode such as JSOP_CALL
+ * or JSOP_NEWARRAY (for such ops, JSCodeSpec.nuses is -1).
+ */
+extern uintN
+js_GetVariableStackUseLength(JSOp op, jsbytecode *pc);
+
+#ifdef DEBUG
+/*
+ * Disassemblers, for debugging only.
+ */
+#include <stdio.h>
+
+extern JS_FRIEND_API(JSBool)
+js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, FILE *fp);
+
+extern JS_FRIEND_API(uintN)
+js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, uintN loc,
+ JSBool lines, FILE *fp);
+#endif /* DEBUG */
+
+/*
+ * Decompilers, for script, function, and expression pretty-printing.
+ */
+extern JSBool
+js_DecompileScript(JSPrinter *jp, JSScript *script);
+
+extern JSBool
+js_DecompileFunctionBody(JSPrinter *jp);
+
+extern JSBool
+js_DecompileFunction(JSPrinter *jp);
+
+/*
+ * Find the source expression that resulted in v, and return a newly allocated
+ * C-string containing it. Fall back on v's string conversion (fallback) if we
+ * can't find the bytecode that generated and pushed v on the operand stack.
+ *
+ * Search the current stack frame if spindex is JSDVG_SEARCH_STACK. Don't
+ * look for v on the stack if spindex is JSDVG_IGNORE_STACK. Otherwise,
+ * spindex is the negative index of v, measured from cx->fp->sp, or from a
+ * lower frame's sp if cx->fp is native.
+ *
+ * The caller must call JS_free on the result after a succsesful call.
+ */
+extern char *
+js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
+ JSString *fallback);
+
+#define JSDVG_IGNORE_STACK 0
+#define JSDVG_SEARCH_STACK 1
+
+/*
+ * Given bytecode address pc in script's main program code, return the operand
+ * stack depth just before (JSOp) *pc executes.
+ */
+extern uintN
+js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+JS_END_EXTERN_C
+
+#endif /* jsopcode_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl
new file mode 100644
index 0000000..6392209
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsopcode.tbl
@@ -0,0 +1,557 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JavaScript operation bytecodes. If you need to allocate a bytecode, look
+ * for a name of the form JSOP_UNUSED* and claim it. Otherwise, always add at
+ * the end of the table.
+ *
+ * Includers must define an OPDEF macro of the following form:
+ *
+ * #define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) ...
+ *
+ * Selected arguments can be expanded in initializers. The op argument is
+ * expanded followed by comma in the JSOp enum (jsopcode.h), e.g. The value
+ * field must be dense for now, because jsopcode.c uses an OPDEF() expansion
+ * inside the js_CodeSpec[] initializer.
+ *
+ * Field Description
+ * op Bytecode name, which is the JSOp enumerator name
+ * value Bytecode value, which is the JSOp enumerator value
+ * name C string containing name for disassembler
+ * image C string containing "image" for pretty-printer, null if ugly
+ * length Number of bytes including any immediate operands
+ * nuses Number of stack slots consumed by bytecode, -1 if variadic
+ * ndefs Number of stack slots produced by bytecode, -1 if variadic
+ * prec Operator precedence, zero if not an operator
+ * format Bytecode plus immediate operand encoding format
+ *
+ * Precedence Operators Opcodes
+ * 1 yield w JSOP_YIELD
+ * 2 , JSOP_POP with SRC_PCDELTA, JSOP_RETURN
+ * 3 =, +=, etc. JSOP_SETNAME, etc. (all JOF_SET);
+ * let (...) ... and JSOP_LEAVEBLOCKEXPR
+ * 4 ?: JSOP_IFEQ, JSOP_IFEQX
+ * 5 || JSOP_OR, JSOP_ORX
+ * 6 && JSOP_AND, JSOP_ANDX
+ * 7 | JSOP_BITOR
+ * 8 ^ JSOP_BITXOR
+ * 9 & JSOP_BITAND
+ * 10 ==, !=, etc. JSOP_EQ, JSOP_NE, etc.
+ * 11 <, in, etc. JSOP_LT, JSOP_IN, etc.
+ * 12 <<, >>, >>> JSOP_LSH, JSOP_RSH, JSOP_URSH
+ * 13 +, -, etc. JSOP_ADD, JSOP_SUB, etc.
+ * 14 *, /, % JSOP_MUL, JSOP_DIV, JSOP_MOD
+ * 15 !, ~, delete, etc. JSOP_NOT, JSOP_BITNOT, JSOP_DEL*, etc.
+ * 16 3.14, 0, etc. JSOP_DOUBLE, JSOP_ZERO, etc.
+ * 17 new JSOP_NEW
+ * 18 x.y, f(), etc. JSOP_GETPROP, JSOP_CALL, etc.
+ * 19 x, null, JSOP_NAME, JSOP_NULL, etc.;
+ * function (...) ... and JSOP_ANONFUNOBJ, JSOP_NAMEDFUNOBJ
+ *
+ * The push-numeric-constant operators, JSOP_ZERO, JSOP_DOUBLE, etc., have
+ * lower precedence than the member operators emitted for the . operator, to
+ * cause the decompiler to parenthesize the . left operand, e.g. (0).foo.
+ * Otherwise the . could be taken as a decimal point.
+ *
+ * Let expressions are "primary" when viewed from the left, but they eat up ops
+ * to the right as if assignment expressions and therefore have precedence 3.
+ * This makes the decompiler retain the parentheses in (let (a=0) x) ? a : 0
+ * but omit the superfluous ones in (let (a=0) x), a.
+ *
+ * Yield expressions must be parenthesized even in comma-expressions and
+ * argument lists, so they have the lowest precedence.
+ *
+ * This file is best viewed with 128 columns:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
+ */
+
+/* legend: op val name image len use def prec format */
+
+/* Longstanding JavaScript bytecodes. */
+OPDEF(JSOP_INTERRUPT, 0, "interrupt", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_PUSH, 1, "push", NULL, 1, 0, 1, 0, JOF_BYTE)
+OPDEF(JSOP_POPV, 2, "popv", NULL, 1, 1, 0, 2, JOF_BYTE)
+OPDEF(JSOP_ENTERWITH, 3, "enterwith", NULL, 1, 1, 1, 0, JOF_BYTE|JOF_PARENHEAD)
+OPDEF(JSOP_LEAVEWITH, 4, "leavewith", NULL, 1, 1, 0, 0, JOF_BYTE)
+OPDEF(JSOP_RETURN, 5, "return", NULL, 1, 1, 0, 2, JOF_BYTE)
+OPDEF(JSOP_GOTO, 6, "goto", NULL, 3, 0, 0, 0, JOF_JUMP)
+OPDEF(JSOP_IFEQ, 7, "ifeq", NULL, 3, 1, 0, 4, JOF_JUMP|JOF_DETECTING)
+OPDEF(JSOP_IFNE, 8, "ifne", NULL, 3, 1, 0, 0, JOF_JUMP|JOF_PARENHEAD)
+
+/* Get the arguments object for the current, lightweight function activation. */
+OPDEF(JSOP_ARGUMENTS, 9, js_arguments_str, js_arguments_str, 1, 0, 1, 18, JOF_BYTE)
+
+/* ECMA-compliant for-in loop with argument or local loop control. */
+OPDEF(JSOP_FORARG, 10, "forarg", NULL, 3, 2, 2, 19, JOF_QARG|JOF_NAME|JOF_FOR)
+OPDEF(JSOP_FORLOCAL, 11, "forlocal", NULL, 3, 2, 2, 19, JOF_LOCAL|JOF_NAME|JOF_FOR)
+
+/* More longstanding bytecodes. */
+OPDEF(JSOP_DUP, 12, "dup", NULL, 1, 1, 2, 0, JOF_BYTE)
+OPDEF(JSOP_DUP2, 13, "dup2", NULL, 1, 2, 4, 0, JOF_BYTE)
+OPDEF(JSOP_SETCONST, 14, "setconst", NULL, 3, 1, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET)
+OPDEF(JSOP_BITOR, 15, "bitor", "|", 1, 2, 1, 7, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_BITXOR, 16, "bitxor", "^", 1, 2, 1, 8, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_BITAND, 17, "bitand", "&", 1, 2, 1, 9, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_EQ, 18, "eq", "==", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
+OPDEF(JSOP_NE, 19, "ne", "!=", 1, 2, 1, 10, JOF_BYTE|JOF_LEFTASSOC|JOF_DETECTING)
+OPDEF(JSOP_LT, 20, "lt", "<", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_LE, 21, "le", "<=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_GT, 22, "gt", ">", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_GE, 23, "ge", ">=", 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_LSH, 24, "lsh", "<<", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_RSH, 25, "rsh", ">>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_URSH, 26, "ursh", ">>>", 1, 2, 1, 12, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_ADD, 27, "add", "+", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_SUB, 28, "sub", "-", 1, 2, 1, 13, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_MUL, 29, "mul", "*", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_DIV, 30, "div", "/", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_MOD, 31, "mod", "%", 1, 2, 1, 14, JOF_BYTE|JOF_LEFTASSOC|JOF_TMPSLOT2)
+OPDEF(JSOP_NOT, 32, "not", "!", 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
+OPDEF(JSOP_BITNOT, 33, "bitnot", "~", 1, 1, 1, 15, JOF_BYTE)
+OPDEF(JSOP_NEG, 34, "neg", "- ", 1, 1, 1, 15, JOF_BYTE)
+OPDEF(JSOP_NEW, 35, js_new_str, NULL, 3, -1, 1, 17, JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_DELNAME, 36, "delname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEL)
+OPDEF(JSOP_DELPROP, 37, "delprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEL)
+OPDEF(JSOP_DELELEM, 38, "delelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEL)
+OPDEF(JSOP_TYPEOF, 39, js_typeof_str,NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
+OPDEF(JSOP_VOID, 40, js_void_str, NULL, 1, 1, 1, 15, JOF_BYTE)
+
+OPDEF(JSOP_INCNAME, 41, "incname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_INCPROP, 42, "incprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_INCELEM, 43, "incelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECNAME, 44, "decname", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECPROP, 45, "decprop", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECELEM, 46, "decelem", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_NAMEINC, 47, "nameinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_PROPINC, 48, "propinc", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_ELEMINC, 49, "eleminc", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_NAMEDEC, 50, "namedec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_PROPDEC, 51, "propdec", NULL, 3, 1, 1, 15, JOF_ATOM|JOF_PROP|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_ELEMDEC, 52, "elemdec", NULL, 1, 2, 1, 15, JOF_BYTE |JOF_ELEM|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+
+OPDEF(JSOP_GETPROP, 53, "getprop", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP)
+OPDEF(JSOP_SETPROP, 54, "setprop", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_GETELEM, 55, "getelem", NULL, 1, 2, 1, 18, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC)
+OPDEF(JSOP_SETELEM, 56, "setelem", NULL, 1, 3, 1, 3, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_CALLNAME, 57, "callname", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALL, 58, "call", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_NAME, 59, "name", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME)
+OPDEF(JSOP_DOUBLE, 60, "double", NULL, 3, 0, 1, 16, JOF_ATOM)
+OPDEF(JSOP_STRING, 61, "string", NULL, 3, 0, 1, 19, JOF_ATOM)
+OPDEF(JSOP_ZERO, 62, "zero", "0", 1, 0, 1, 16, JOF_BYTE)
+OPDEF(JSOP_ONE, 63, "one", "1", 1, 0, 1, 16, JOF_BYTE)
+OPDEF(JSOP_NULL, 64, js_null_str, js_null_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_THIS, 65, js_this_str, js_this_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_FALSE, 66, js_false_str, js_false_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_TRUE, 67, js_true_str, js_true_str, 1, 0, 1, 19, JOF_BYTE)
+OPDEF(JSOP_OR, 68, "or", NULL, 3, 1, 0, 5, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
+OPDEF(JSOP_AND, 69, "and", NULL, 3, 1, 0, 6, JOF_JUMP|JOF_DETECTING|JOF_LEFTASSOC)
+
+/* The switch bytecodes have variable length. */
+OPDEF(JSOP_TABLESWITCH, 70, "tableswitch", NULL, -1, 1, 0, 0, JOF_TABLESWITCH|JOF_DETECTING|JOF_PARENHEAD)
+OPDEF(JSOP_LOOKUPSWITCH, 71, "lookupswitch", NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCH|JOF_DETECTING|JOF_PARENHEAD)
+
+/* New, infallible/transitive identity ops. */
+OPDEF(JSOP_STRICTEQ, 72, "stricteq", "===", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC)
+OPDEF(JSOP_STRICTNE, 73, "strictne", "!==", 1, 2, 1, 10, JOF_BYTE|JOF_DETECTING|JOF_LEFTASSOC)
+
+/* Variant of JSOP_NULL for default (global) |this| parameter pushing. */
+OPDEF(JSOP_NULLTHIS, 74, js_null_str, js_null_str, 1, 0, 1, 19, JOF_BYTE)
+
+/*
+ * JSOP_ITER sets up a for-in or for-each-in loop using the JSITER_* flag bits
+ * in this op's uint8 immediate operand. It replaces the top of stack object
+ * with an iterator for that object, and pushes a slot used by JSOP_NEXTITER.
+ *
+ * JSOP_NEXTITER stores the next iterated value in the top of stack slot which
+ * was allocated by JSOP_ITER and pushes true, or stores JSVAL_HOLE and pushes
+ * false. It is followed immediately by JSOP_IFNE{,X}.
+ *
+ * JSOP_ENDITER cleans up after the loop. It uses the slot above the iterator
+ * for temporary GC rooting.
+ */
+OPDEF(JSOP_ITER, 75, "iter", NULL, 2, 1, 2, 0, JOF_UINT8)
+OPDEF(JSOP_NEXTITER, 76, "nextiter", NULL, 1, 2, 3, 0, JOF_BYTE)
+OPDEF(JSOP_ENDITER, 77, "enditer", NULL, 1, 2, 0, 0, JOF_BYTE)
+
+OPDEF(JSOP_APPLY, 78, "apply", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE)
+OPDEF(JSOP_SWAP, 79, "swap", NULL, 1, 2, 2, 0, JOF_BYTE)
+
+/* Push object literal. */
+OPDEF(JSOP_OBJECT, 80, "object", NULL, 3, 0, 1, 19, JOF_OBJECT)
+
+/* Pop value and discard it. */
+OPDEF(JSOP_POP, 81, "pop", NULL, 1, 1, 0, 2, JOF_BYTE)
+
+/* Convert value to number, for unary +. */
+OPDEF(JSOP_POS, 82, "pos", "+ ", 1, 1, 1, 15, JOF_BYTE)
+
+/* Trap into debugger for breakpoint, etc. */
+OPDEF(JSOP_TRAP, 83, "trap", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* Fast get/set ops for function arguments and local variables. */
+OPDEF(JSOP_GETARG, 84, "getarg", NULL, 3, 0, 1, 19, JOF_QARG |JOF_NAME)
+OPDEF(JSOP_SETARG, 85, "setarg", NULL, 3, 1, 1, 3, JOF_QARG |JOF_NAME|JOF_SET)
+OPDEF(JSOP_GETLOCAL, 86,"getlocal", NULL, 3, 0, 1, 19, JOF_LOCAL|JOF_NAME)
+OPDEF(JSOP_SETLOCAL, 87,"setlocal", NULL, 3, 1, 1, 3, JOF_LOCAL|JOF_NAME|JOF_SET|JOF_DETECTING)
+
+/* Push unsigned 16-bit int constant. */
+OPDEF(JSOP_UINT16, 88, "uint16", NULL, 3, 0, 1, 16, JOF_UINT16)
+
+/* Object and array literal support. */
+OPDEF(JSOP_NEWINIT, 89, "newinit", NULL, 2, 0, 1, 19, JOF_INT8)
+OPDEF(JSOP_ENDINIT, 90, "endinit", NULL, 1, 0, 0, 19, JOF_BYTE)
+OPDEF(JSOP_INITPROP, 91, "initprop", NULL, 3, 1, 0, 3, JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_INITELEM, 92, "initelem", NULL, 1, 2, 0, 3, JOF_BYTE |JOF_ELEM|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_DEFSHARP, 93, "defsharp", NULL, 3, 0, 0, 0, JOF_UINT16)
+OPDEF(JSOP_USESHARP, 94, "usesharp", NULL, 3, 0, 1, 0, JOF_UINT16)
+
+/* Fast inc/dec ops for args and locals. */
+OPDEF(JSOP_INCARG, 95, "incarg", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_INC)
+OPDEF(JSOP_DECARG, 96, "decarg", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_DEC)
+OPDEF(JSOP_ARGINC, 97, "arginc", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_INC|JOF_POST)
+OPDEF(JSOP_ARGDEC, 98, "argdec", NULL, 3, 0, 1, 15, JOF_QARG |JOF_NAME|JOF_DEC|JOF_POST)
+
+OPDEF(JSOP_INCLOCAL, 99, "inclocal", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_INC)
+OPDEF(JSOP_DECLOCAL, 100,"declocal", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_DEC)
+OPDEF(JSOP_LOCALINC, 101,"localinc", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_INC|JOF_POST)
+OPDEF(JSOP_LOCALDEC, 102,"localdec", NULL, 3, 0, 1, 15, JOF_LOCAL|JOF_NAME|JOF_DEC|JOF_POST)
+
+OPDEF(JSOP_IMACOP, 103,"imacop", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* ECMA-compliant for/in ops. */
+OPDEF(JSOP_FORNAME, 104,"forname", NULL, 3, 2, 2, 19, JOF_ATOM|JOF_NAME|JOF_FOR)
+OPDEF(JSOP_FORPROP, 105,"forprop", NULL, 3, 3, 2, 18, JOF_ATOM|JOF_PROP|JOF_FOR)
+OPDEF(JSOP_FORELEM, 106,"forelem", NULL, 1, 2, 3, 18, JOF_BYTE |JOF_ELEM|JOF_FOR)
+OPDEF(JSOP_POPN, 107,"popn", NULL, 3, -1, 0, 0, JOF_UINT16)
+
+/* ECMA-compliant assignment ops. */
+OPDEF(JSOP_BINDNAME, 108,"bindname", NULL, 3, 0, 1, 0, JOF_ATOM|JOF_NAME|JOF_SET)
+OPDEF(JSOP_SETNAME, 109,"setname", NULL, 3, 2, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING)
+
+/* Exception handling ops. */
+OPDEF(JSOP_THROW, 110,js_throw_str, NULL, 1, 1, 0, 0, JOF_BYTE)
+
+/* 'in' and 'instanceof' ops. */
+OPDEF(JSOP_IN, 111,js_in_str, js_in_str, 1, 2, 1, 11, JOF_BYTE|JOF_LEFTASSOC)
+OPDEF(JSOP_INSTANCEOF,112,js_instanceof_str,js_instanceof_str,1,2,1,11,JOF_BYTE|JOF_LEFTASSOC)
+
+/* debugger op */
+OPDEF(JSOP_DEBUGGER, 113,"debugger", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* gosub/retsub for finally handling */
+OPDEF(JSOP_GOSUB, 114,"gosub", NULL, 3, 0, 0, 0, JOF_JUMP)
+OPDEF(JSOP_RETSUB, 115,"retsub", NULL, 1, 2, 0, 0, JOF_BYTE)
+
+/* More exception handling ops. */
+OPDEF(JSOP_EXCEPTION, 116,"exception", NULL, 1, 0, 1, 0, JOF_BYTE)
+
+/* Embedded lineno to speedup pc->line mapping. */
+OPDEF(JSOP_LINENO, 117,"lineno", NULL, 3, 0, 0, 0, JOF_UINT16)
+
+/*
+ * ECMA-compliant switch statement ops.
+ * CONDSWITCH is a decompilable NOP; CASE is ===, POP, jump if true, re-push
+ * lval if false; and DEFAULT is POP lval and GOTO.
+ */
+OPDEF(JSOP_CONDSWITCH,118,"condswitch", NULL, 1, 0, 0, 0, JOF_BYTE|JOF_PARENHEAD)
+OPDEF(JSOP_CASE, 119,"case", NULL, 3, 2, 1, 0, JOF_JUMP)
+OPDEF(JSOP_DEFAULT, 120,"default", NULL, 3, 1, 0, 0, JOF_JUMP)
+
+/*
+ * ECMA-compliant call to eval op
+ */
+OPDEF(JSOP_EVAL, 121,"eval", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE)
+
+/*
+ * ECMA-compliant helper for 'for (x[i] in o)' loops.
+ */
+OPDEF(JSOP_ENUMELEM, 122,"enumelem", NULL, 1, 3, 0, 3, JOF_BYTE |JOF_SET)
+
+/*
+ * Getter and setter prefix bytecodes. These modify the next bytecode, either
+ * an assignment or a property initializer code, which then defines a property
+ * getter or setter.
+ */
+OPDEF(JSOP_GETTER, 123,js_getter_str,NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_SETTER, 124,js_setter_str,NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Prolog bytecodes for defining function, var, and const names.
+ */
+OPDEF(JSOP_DEFFUN, 125,"deffun", NULL, 3, 0, 0, 0, JOF_OBJECT|JOF_DECLARING)
+OPDEF(JSOP_DEFCONST, 126,"defconst", NULL, 3, 0, 0, 0, JOF_ATOM|JOF_DECLARING)
+OPDEF(JSOP_DEFVAR, 127,"defvar", NULL, 3, 0, 0, 0, JOF_ATOM|JOF_DECLARING)
+
+/* Auto-clone (if needed due to re-parenting) and push an anonymous function. */
+OPDEF(JSOP_ANONFUNOBJ, 128, "anonfunobj", NULL, 3, 0, 1, 19, JOF_OBJECT)
+
+/* ECMA ed. 3 named function expression. */
+OPDEF(JSOP_NAMEDFUNOBJ, 129, "namedfunobj", NULL, 3, 0, 1, 19, JOF_OBJECT)
+
+/*
+ * Like JSOP_SETLOCAL, but specialized to avoid requiring JSOP_POP immediately
+ * after to throw away the exception value.
+ */
+OPDEF(JSOP_SETLOCALPOP, 130, "setlocalpop", NULL, 3, 1, 0, 3, JOF_LOCAL|JOF_NAME|JOF_SET)
+
+/* Parenthesization opcode to help the decompiler. */
+OPDEF(JSOP_UNUSED131, 131, "unused131", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Host object extension: given 'o.item(i) = j', the left-hand side compiles
+ * JSOP_SETCALL, rather than JSOP_CALL.
+ */
+OPDEF(JSOP_SETCALL, 132, "setcall", NULL, 3, -1, 2, 18, JOF_UINT16|JOF_SET)
+
+/*
+ * Exception handling no-op, for more economical byte-coding than SRC_TRYFIN
+ * srcnote-annotated JSOP_NOPs and to simply stack balance handling.
+ */
+OPDEF(JSOP_TRY, 133,"try", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_FINALLY, 134,"finally", NULL, 1, 0, 2, 0, JOF_BYTE)
+
+/*
+ * Generic nop for the decompiler.
+ */
+OPDEF(JSOP_NOP, 135,"nop", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Bytecodes that avoid making an arguments object in most cases:
+ * JSOP_ARGSUB gets arguments[i] from fp->argv, iff i is in [0, fp->argc-1].
+ * JSOP_ARGCNT returns fp->argc.
+ */
+OPDEF(JSOP_ARGSUB, 136,"argsub", NULL, 3, 0, 1, 18, JOF_QARG |JOF_NAME)
+OPDEF(JSOP_ARGCNT, 137,"argcnt", NULL, 1, 0, 1, 18, JOF_BYTE)
+
+/*
+ * Define a local function object as a local variable.
+ * The local variable's slot number is the first immediate two-byte operand.
+ * The function object's atom index is the second immediate operand.
+ */
+OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL, 5, 0, 0, 0, JOF_SLOTOBJECT|JOF_DECLARING)
+
+/* Extended jumps. */
+OPDEF(JSOP_GOTOX, 139,"gotox", NULL, 5, 0, 0, 0, JOF_JUMPX)
+OPDEF(JSOP_IFEQX, 140,"ifeqx", NULL, 5, 1, 0, 4, JOF_JUMPX|JOF_DETECTING)
+OPDEF(JSOP_IFNEX, 141,"ifnex", NULL, 5, 1, 0, 0, JOF_JUMPX|JOF_PARENHEAD)
+OPDEF(JSOP_ORX, 142,"orx", NULL, 5, 1, 0, 5, JOF_JUMPX|JOF_DETECTING)
+OPDEF(JSOP_ANDX, 143,"andx", NULL, 5, 1, 0, 6, JOF_JUMPX|JOF_DETECTING)
+OPDEF(JSOP_GOSUBX, 144,"gosubx", NULL, 5, 0, 0, 0, JOF_JUMPX)
+OPDEF(JSOP_CASEX, 145,"casex", NULL, 5, 2, 1, 0, JOF_JUMPX)
+OPDEF(JSOP_DEFAULTX, 146,"defaultx", NULL, 5, 1, 0, 0, JOF_JUMPX)
+OPDEF(JSOP_TABLESWITCHX, 147,"tableswitchx",NULL, -1, 1, 0, 0, JOF_TABLESWITCHX|JOF_DETECTING|JOF_PARENHEAD)
+OPDEF(JSOP_LOOKUPSWITCHX, 148,"lookupswitchx",NULL, -1, 1, 0, 0, JOF_LOOKUPSWITCHX|JOF_DETECTING|JOF_PARENHEAD)
+
+/* Placeholders for a real jump opcode set during backpatch chain fixup. */
+OPDEF(JSOP_BACKPATCH, 149,"backpatch",NULL, 3, 0, 0, 0, JOF_JUMP|JOF_BACKPATCH)
+OPDEF(JSOP_BACKPATCH_POP, 150,"backpatch_pop",NULL, 3, 1, 0, 0, JOF_JUMP|JOF_BACKPATCH)
+
+/* Set pending exception from the stack, to trigger rethrow. */
+OPDEF(JSOP_THROWING, 151,"throwing", NULL, 1, 1, 0, 0, JOF_BYTE)
+
+/* Set and get return value pseudo-register in stack frame. */
+OPDEF(JSOP_SETRVAL, 152,"setrval", NULL, 1, 1, 0, 2, JOF_BYTE)
+OPDEF(JSOP_RETRVAL, 153,"retrval", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/* Optimized global variable ops (we don't bother doing a JSOP_FORGVAR op). */
+OPDEF(JSOP_GETGVAR, 154,"getgvar", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_NAME)
+OPDEF(JSOP_SETGVAR, 155,"setgvar", NULL, 3, 1, 1, 3, JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_INCGVAR, 156,"incgvar", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_TMPSLOT2)
+OPDEF(JSOP_DECGVAR, 157,"decgvar", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_TMPSLOT2)
+OPDEF(JSOP_GVARINC, 158,"gvarinc", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT2)
+OPDEF(JSOP_GVARDEC, 159,"gvardec", NULL, 3, 0, 1, 15, JOF_ATOM|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT2)
+
+/* Regular expression literal requiring special "fork on exec" handling. */
+OPDEF(JSOP_REGEXP, 160,"regexp", NULL, 3, 0, 1, 19, JOF_REGEXP)
+
+/* XML (ECMA-357, a.k.a. "E4X") support. */
+OPDEF(JSOP_DEFXMLNS, 161,"defxmlns", NULL, 1, 1, 0, 0, JOF_BYTE)
+OPDEF(JSOP_ANYNAME, 162,"anyname", NULL, 1, 0, 1, 19, JOF_BYTE|JOF_XMLNAME)
+OPDEF(JSOP_QNAMEPART, 163,"qnamepart", NULL, 3, 0, 1, 19, JOF_ATOM|JOF_XMLNAME)
+OPDEF(JSOP_QNAMECONST, 164,"qnameconst", NULL, 3, 1, 1, 19, JOF_ATOM|JOF_XMLNAME)
+OPDEF(JSOP_QNAME, 165,"qname", NULL, 1, 2, 1, 0, JOF_BYTE|JOF_XMLNAME)
+OPDEF(JSOP_TOATTRNAME, 166,"toattrname", NULL, 1, 1, 1, 19, JOF_BYTE|JOF_XMLNAME)
+OPDEF(JSOP_TOATTRVAL, 167,"toattrval", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_ADDATTRNAME, 168,"addattrname",NULL, 1, 2, 1, 13, JOF_BYTE)
+OPDEF(JSOP_ADDATTRVAL, 169,"addattrval", NULL, 1, 2, 1, 13, JOF_BYTE)
+OPDEF(JSOP_BINDXMLNAME, 170,"bindxmlname",NULL, 1, 1, 2, 3, JOF_BYTE|JOF_SET)
+OPDEF(JSOP_SETXMLNAME, 171,"setxmlname", NULL, 1, 3, 1, 3, JOF_BYTE|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_XMLNAME, 172,"xmlname", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_DESCENDANTS, 173,"descendants",NULL, 1, 2, 1, 18, JOF_BYTE)
+OPDEF(JSOP_FILTER, 174,"filter", NULL, 3, 1, 1, 0, JOF_JUMP)
+OPDEF(JSOP_ENDFILTER, 175,"endfilter", NULL, 3, 2, 1, 18, JOF_JUMP)
+OPDEF(JSOP_TOXML, 176,"toxml", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_TOXMLLIST, 177,"toxmllist", NULL, 1, 1, 1, 19, JOF_BYTE)
+OPDEF(JSOP_XMLTAGEXPR, 178,"xmltagexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
+OPDEF(JSOP_XMLELTEXPR, 179,"xmleltexpr", NULL, 1, 1, 1, 0, JOF_BYTE)
+OPDEF(JSOP_XMLOBJECT, 180,"xmlobject", NULL, 3, 0, 1, 19, JOF_OBJECT)
+OPDEF(JSOP_XMLCDATA, 181,"xmlcdata", NULL, 3, 0, 1, 19, JOF_ATOM)
+OPDEF(JSOP_XMLCOMMENT, 182,"xmlcomment", NULL, 3, 0, 1, 19, JOF_ATOM)
+OPDEF(JSOP_XMLPI, 183,"xmlpi", NULL, 3, 1, 1, 19, JOF_ATOM)
+OPDEF(JSOP_CALLPROP, 184,"callprop", NULL, 3, 1, 2, 18, JOF_ATOM|JOF_PROP|JOF_CALLOP)
+OPDEF(JSOP_GETFUNNS, 185,"getfunns", NULL, 1, 0, 1, 19, JOF_BYTE)
+
+/*
+ * Get a display (free) variable from the closure's reserved slots.
+ */
+OPDEF(JSOP_GETUPVAR, 186,"getupvar", NULL, 3, 0, 1, 19, JOF_UINT16|JOF_NAME)
+
+OPDEF(JSOP_DELDESC, 187,"deldesc", NULL, 1, 2, 1, 15, JOF_BYTE|JOF_ELEM|JOF_DEL)
+
+/*
+ * Opcode to hold 24-bit immediate integer operands.
+ */
+OPDEF(JSOP_UINT24, 188,"uint24", NULL, 4, 0, 1, 16, JOF_UINT24)
+
+/*
+ * Opcodes to allow 24-bit atom or object indexes. Whenever an index exceeds
+ * the 16-bit limit, the index-accessing bytecode must be bracketed by
+ * JSOP_INDEXBASE and JSOP_RESETBASE to provide the upper bits of the index.
+ * See jsemit.c, EmitIndexOp.
+ */
+OPDEF(JSOP_INDEXBASE, 189,"atombase", NULL, 2, 0, 0, 0, JOF_UINT8|JOF_INDEXBASE)
+OPDEF(JSOP_RESETBASE, 190,"resetbase", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_RESETBASE0, 191,"resetbase0", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Opcodes to help the decompiler deal with XML.
+ */
+OPDEF(JSOP_STARTXML, 192,"startxml", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_STARTXMLEXPR, 193,"startxmlexpr",NULL, 1, 0, 0, 0, JOF_BYTE)
+
+OPDEF(JSOP_CALLELEM, 194, "callelem", NULL, 1, 2, 2, 18, JOF_BYTE |JOF_ELEM|JOF_LEFTASSOC|JOF_CALLOP)
+
+/*
+ * Stop interpretation, emitted at end of script to save the threaded bytecode
+ * interpreter an extra branch test on every DO_NEXT_OP (see jsinterp.c).
+ */
+OPDEF(JSOP_STOP, 195,"stop", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Get an extant property value, throwing ReferenceError if the identified
+ * property does not exist.
+ */
+OPDEF(JSOP_GETXPROP, 196,"getxprop", NULL, 3, 1, 1, 18, JOF_ATOM|JOF_PROP)
+
+OPDEF(JSOP_CALLXMLNAME, 197, "callxmlname", NULL, 1, 1, 2, 19, JOF_BYTE|JOF_CALLOP)
+
+/*
+ * Specialized JSOP_TYPEOF to avoid reporting undefined for typeof(0, undef).
+ */
+OPDEF(JSOP_TYPEOFEXPR, 198,"typeofexpr", NULL, 1, 1, 1, 15, JOF_BYTE|JOF_DETECTING)
+
+/*
+ * Block-local scope support.
+ */
+OPDEF(JSOP_ENTERBLOCK, 199,"enterblock", NULL, 3, 0, -1, 0, JOF_OBJECT)
+OPDEF(JSOP_LEAVEBLOCK, 200,"leaveblock", NULL, 3, -1, 0, 0, JOF_UINT16)
+OPDEF(JSOP_UNUSED201, 201,"unused201", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED202, 202,"unused202", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED203, 203,"unused203", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED204, 204,"unused204", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED205, 205,"unused205", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED206, 206,"unused206", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED207, 207,"unused207", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED208, 208,"unused208", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_UNUSED209, 209,"unused209", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Generator and array comprehension support.
+ */
+OPDEF(JSOP_GENERATOR, 210,"generator", NULL, 1, 0, 0, 0, JOF_BYTE)
+OPDEF(JSOP_YIELD, 211,"yield", NULL, 1, 1, 1, 1, JOF_BYTE)
+OPDEF(JSOP_ARRAYPUSH, 212,"arraypush", NULL, 3, 1, 0, 3, JOF_LOCAL)
+
+/*
+ * In the forthcoming great opcode reorg, this should go next to JSOP_GETUPVAR.
+ */
+OPDEF(JSOP_CALLUPVAR, 213, "callupvar", NULL, 3, 0, 2, 19, JOF_UINT16|JOF_NAME|JOF_CALLOP)
+
+/*
+ * Variant of JSOP_ENUMELEM for destructuring const (const [a, b] = ...).
+ */
+OPDEF(JSOP_ENUMCONSTELEM, 214,"enumconstelem",NULL, 1, 3, 0, 3, JOF_BYTE|JOF_SET)
+
+/*
+ * Variant of JSOP_LEAVEBLOCK has a result on the stack above the locals,
+ * which must be moved down when the block pops.
+ */
+OPDEF(JSOP_LEAVEBLOCKEXPR,215,"leaveblockexpr",NULL, 3, -1, 1, 3, JOF_UINT16)
+
+/*
+ * Optimize common JSOP_{THIS,GET{ARG,LOCAL}} -> JSOP_GETPROP cliches.
+ */
+OPDEF(JSOP_GETTHISPROP, 216,"getthisprop", NULL, 3, 0, 1, 18, JOF_ATOM|JOF_VARPROP)
+OPDEF(JSOP_GETARGPROP, 217,"getargprop", NULL, 5, 0, 1, 18, JOF_SLOTATOM|JOF_VARPROP)
+OPDEF(JSOP_GETLOCALPROP, 218,"getlocalprop", NULL, 5, 0, 1, 18, JOF_SLOTATOM|JOF_VARPROP)
+OPDEF(JSOP_UNUSED219, 219,"unused219", NULL, 1, 0, 0, 0, JOF_BYTE)
+
+/*
+ * Optimize atom segments 1-3. These must be followed by JSOP_RESETBASE0 after
+ * the opcode that they prefix.
+ */
+OPDEF(JSOP_INDEXBASE1, 220,"atombase1", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE2, 221,"atombase2", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE3, 222,"atombase3", NULL, 1, 0, 0, 0, JOF_BYTE |JOF_INDEXBASE)
+
+OPDEF(JSOP_CALLGVAR, 223, "callgvar", NULL, 3, 0, 2, 19, JOF_ATOM|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALLLOCAL, 224, "calllocal", NULL, 3, 0, 2, 19, JOF_LOCAL|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALLARG, 225, "callarg", NULL, 3, 0, 2, 19, JOF_QARG |JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_UNUSED226, 226, "unused226", NULL, 1, 0, 1, 1, JOF_BYTE)
+
+/*
+ * Opcodes to hold 8-bit and 32-bit immediate integer operands.
+ */
+OPDEF(JSOP_INT8, 227, "int8", NULL, 2, 0, 1, 16, JOF_INT8)
+OPDEF(JSOP_INT32, 228, "int32", NULL, 5, 0, 1, 16, JOF_INT32)
+
+/*
+ * Get the value of the 'length' property from a stacked object.
+ */
+OPDEF(JSOP_LENGTH, 229, "length", NULL, 1, 1, 1, 18, JOF_BYTE|JOF_PROP)
+
+/*
+ * JSOP_NEWARRAY optimizes array literal evaluation using the interpreter stack.
+ * JSOP_HOLE pushes a JSVAL_HOLE (used with JSOP_NEWINIT and JSOP_NEWARRAY).
+ */
+OPDEF(JSOP_NEWARRAY, 230, "newarray", NULL, 4, -1, 1, 19, JOF_UINT24)
+OPDEF(JSOP_HOLE, 231, "hole", NULL, 1, 0, 1, 0, JOF_BYTE)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp
new file mode 100644
index 0000000..ecebc06
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsoplengen.cpp
@@ -0,0 +1,121 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is String Switch Generator for JavaScript Keywords,
+ * released 2005-12-09.
+ *
+ * The Initial Developer of the Original Code is
+ * Igor Bukanov.
+ * Portions created by the Initial Developer are Copyright (C) 2005-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const struct {
+ const char *name;
+ int length;
+} pairs[] = {
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ { #op, length } ,
+#include "jsopcode.tbl"
+#undef OPDEF
+};
+
+int
+main(int argc, char **argv)
+{
+ FILE *fp;
+ size_t maxNameWidth, i, nameWidth, tabStop;
+ int lengthGap;
+
+ static const char prefix[] = "#define ";
+ static const char suffix[] = "_LENGTH";
+ static const size_t tabWidth = 8;
+ static const size_t prefixWidth = sizeof(prefix) - 1;
+ static const size_t suffixWidth = sizeof(suffix) - 1;
+
+ if (argc != 2) {
+ fputs("Bad usage\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ fp = fopen(argv[1], "w");
+ if (!fp) {
+ perror("fopen");
+ return EXIT_FAILURE;
+ }
+ fputs("/*\n"
+ " * Automatically generated header with JS opcode length constants.\n"
+ " *\n"
+ " * Do not edit it, alter jsopcode.tbl instead.\n"
+ " */\n",
+ fp);
+
+ /*
+ * Print
+ *
+ * #define name_LENGTH length
+ *
+ * with all length values aligned on the same column. The column is at the
+ * second character position after a tab-stop with the first position
+ * reserved for the minus sign of variable-length opcodes.
+ */
+ maxNameWidth = 0;
+ for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) {
+ nameWidth = strlen(pairs[i].name);
+ if (maxNameWidth < nameWidth)
+ maxNameWidth = nameWidth;
+ }
+
+ tabStop = prefixWidth + maxNameWidth + suffixWidth + 1;
+ tabStop = (tabStop + tabWidth - 1) / tabWidth * tabWidth;
+ for (i = 0; i != sizeof pairs / sizeof pairs[0]; ++i) {
+ lengthGap = (int) (tabStop - prefixWidth - strlen(pairs[i].name) -
+ suffixWidth);
+ fprintf(fp, "%s%s%s%*c%2d\n",
+ prefix, pairs[i].name, suffix, lengthGap, ' ',
+ pairs[i].length);
+ if (ferror(fp)) {
+ perror("fclose");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (fclose(fp)) {
+ perror("fclose");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h b/tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h
new file mode 100644
index 0000000..ede1221
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsotypes.h
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * This section typedefs the old 'native' types to the new PR<type>s.
+ * These definitions are scheduled to be eliminated at the earliest
+ * possible time. The NSPR API is implemented and documented using
+ * the new definitions.
+ */
+
+/*
+ * Note that we test for PROTYPES_H, not JSOTYPES_H. This is to avoid
+ * double-definitions of scalar types such as uint32, if NSPR's
+ * protypes.h is also included.
+ */
+#ifndef PROTYPES_H
+#define PROTYPES_H
+
+#ifdef XP_BEOS
+/* BeOS defines most int types in SupportDefs.h (int8, uint8, int16,
+ * uint16, int32, uint32, int64, uint64), so in the interest of
+ * not conflicting with other definitions elsewhere we have to skip the
+ * #ifdef jungle below, duplicate some definitions, and do our stuff.
+ */
+#include <SupportDefs.h>
+
+typedef JSUintn uintn;
+#ifndef _XP_Core_
+typedef JSIntn intn;
+#endif
+
+#else
+
+/* SVR4 typedef of uint is commonly found on UNIX machines. */
+#ifdef XP_UNIX
+#include <sys/types.h>
+#else
+typedef JSUintn uint;
+#endif
+
+typedef JSUintn uintn;
+typedef JSUint64 uint64;
+#if !defined(_WIN32) && !defined(XP_OS2)
+typedef JSUint32 uint32;
+#else
+typedef unsigned long uint32;
+#endif
+typedef JSUint16 uint16;
+typedef JSUint8 uint8;
+
+#ifndef _XP_Core_
+typedef JSIntn intn;
+#endif
+
+/*
+ * On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very
+ * common header file) defines the types int8, int16, int32, and int64.
+ * So we don't define these four types here to avoid conflicts in case
+ * the code also includes sys/types.h.
+ */
+#if defined(AIX) && defined(HAVE_SYS_INTTYPES_H)
+#include <sys/inttypes.h>
+#else
+typedef JSInt64 int64;
+
+/* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
+#ifdef HPUX
+#include <model.h>
+#else
+#if !defined(_WIN32) && !defined(XP_OS2)
+typedef JSInt32 int32;
+#else
+typedef long int32;
+#endif
+typedef JSInt16 int16;
+typedef JSInt8 int8;
+#endif /* HPUX */
+#endif /* AIX && HAVE_SYS_INTTYPES_H */
+
+#endif /* XP_BEOS */
+
+typedef JSFloat64 float64;
+
+/* Re: jsbit.h */
+#define TEST_BIT JS_TEST_BIT
+#define SET_BIT JS_SET_BIT
+#define CLEAR_BIT JS_CLEAR_BIT
+
+/* Re: prarena.h->plarena.h */
+#define PRArena PLArena
+#define PRArenaPool PLArenaPool
+#define PRArenaStats PLArenaStats
+#define PR_ARENA_ALIGN PL_ARENA_ALIGN
+#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL
+#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE
+#define PR_ARENA_GROW PL_ARENA_GROW
+#define PR_ARENA_MARK PL_ARENA_MARK
+#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED
+#define PR_CLEAR_ARENA PL_CLEAR_ARENA
+#define PR_ARENA_RELEASE PL_ARENA_RELEASE
+#define PR_COUNT_ARENA PL_COUNT_ARENA
+#define PR_ARENA_DESTROY PL_ARENA_DESTROY
+#define PR_InitArenaPool PL_InitArenaPool
+#define PR_FreeArenaPool PL_FreeArenaPool
+#define PR_FinishArenaPool PL_FinishArenaPool
+#define PR_CompactArenaPool PL_CompactArenaPool
+#define PR_ArenaFinish PL_ArenaFinish
+#define PR_ArenaAllocate PL_ArenaAllocate
+#define PR_ArenaGrow PL_ArenaGrow
+#define PR_ArenaRelease PL_ArenaRelease
+#define PR_ArenaCountAllocation PL_ArenaCountAllocation
+#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth
+#define PR_ArenaCountGrowth PL_ArenaCountGrowth
+#define PR_ArenaCountRelease PL_ArenaCountRelease
+#define PR_ArenaCountRetract PL_ArenaCountRetract
+
+/* Re: prevent.h->plevent.h */
+#define PREvent PLEvent
+#define PREventQueue PLEventQueue
+#define PR_CreateEventQueue PL_CreateEventQueue
+#define PR_DestroyEventQueue PL_DestroyEventQueue
+#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
+#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
+#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
+#define PR_PostEvent PL_PostEvent
+#define PR_PostSynchronousEvent PL_PostSynchronousEvent
+#define PR_GetEvent PL_GetEvent
+#define PR_EventAvailable PL_EventAvailable
+#define PREventFunProc PLEventFunProc
+#define PR_MapEvents PL_MapEvents
+#define PR_RevokeEvents PL_RevokeEvents
+#define PR_ProcessPendingEvents PL_ProcessPendingEvents
+#define PR_WaitForEvent PL_WaitForEvent
+#define PR_EventLoop PL_EventLoop
+#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
+#define PRHandleEventProc PLHandleEventProc
+#define PRDestroyEventProc PLDestroyEventProc
+#define PR_InitEvent PL_InitEvent
+#define PR_GetEventOwner PL_GetEventOwner
+#define PR_HandleEvent PL_HandleEvent
+#define PR_DestroyEvent PL_DestroyEvent
+#define PR_DequeueEvent PL_DequeueEvent
+#define PR_GetMainEventQueue PL_GetMainEventQueue
+
+/* Re: prhash.h->plhash.h */
+#define PRHashEntry PLHashEntry
+#define PRHashTable PLHashTable
+#define PRHashNumber PLHashNumber
+#define PRHashFunction PLHashFunction
+#define PRHashComparator PLHashComparator
+#define PRHashEnumerator PLHashEnumerator
+#define PRHashAllocOps PLHashAllocOps
+#define PR_NewHashTable PL_NewHashTable
+#define PR_HashTableDestroy PL_HashTableDestroy
+#define PR_HashTableRawLookup PL_HashTableRawLookup
+#define PR_HashTableRawAdd PL_HashTableRawAdd
+#define PR_HashTableRawRemove PL_HashTableRawRemove
+#define PR_HashTableAdd PL_HashTableAdd
+#define PR_HashTableRemove PL_HashTableRemove
+#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries
+#define PR_HashTableLookup PL_HashTableLookup
+#define PR_HashTableDump PL_HashTableDump
+#define PR_HashString PL_HashString
+#define PR_CompareStrings PL_CompareStrings
+#define PR_CompareValues PL_CompareValues
+
+#endif /* !defined(PROTYPES_H) */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp
new file mode 100644
index 0000000..57da28a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.cpp
@@ -0,0 +1,6822 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS parser.
+ *
+ * This is a recursive-descent parser for the JavaScript language specified by
+ * "The JavaScript 1.5 Language Specification". It uses lexical and semantic
+ * feedback to disambiguate non-LL(1) structures. It generates trees of nodes
+ * induced by the recursive parsing (not precise syntax trees, see jsparse.h).
+ * After tree construction, it rewrites trees to fold constants and evaluate
+ * compile-time expressions. Finally, it calls js_EmitTree (see jsemit.h) to
+ * generate bytecode.
+ *
+ * This parser attempts no error recovery.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsstaticcheck.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#if JS_HAS_DESTRUCTURING
+#include "jsdhash.h"
+#endif
+
+/*
+ * Asserts to verify assumptions behind pn_ macros.
+ */
+JS_STATIC_ASSERT(offsetof(JSParseNode, pn_u.name.atom) ==
+ offsetof(JSParseNode, pn_u.apair.atom));
+JS_STATIC_ASSERT(offsetof(JSParseNode, pn_u.name.slot) ==
+ offsetof(JSParseNode, pn_u.lexical.slot));
+
+/*
+ * JS parsers, from lowest to highest precedence.
+ *
+ * Each parser takes a context, a token stream, and a tree context struct.
+ * Each returns a parse node tree or null on error.
+ */
+
+typedef JSParseNode *
+JSParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc);
+
+typedef JSParseNode *
+JSMemberParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowCallSyntax);
+
+typedef JSParseNode *
+JSPrimaryParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType tt, JSBool afterDot);
+
+typedef JSParseNode *
+JSParenParser(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *pn1, JSBool *genexp);
+
+static JSParser FunctionStmt;
+static JSParser FunctionExpr;
+static JSParser Statements;
+static JSParser Statement;
+static JSParser Variables;
+static JSParser Expr;
+static JSParser AssignExpr;
+static JSParser CondExpr;
+static JSParser OrExpr;
+static JSParser AndExpr;
+static JSParser BitOrExpr;
+static JSParser BitXorExpr;
+static JSParser BitAndExpr;
+static JSParser EqExpr;
+static JSParser RelExpr;
+static JSParser ShiftExpr;
+static JSParser AddExpr;
+static JSParser MulExpr;
+static JSParser UnaryExpr;
+static JSMemberParser MemberExpr;
+static JSPrimaryParser PrimaryExpr;
+static JSParenParser ParenExpr;
+
+/*
+ * Insist that the next token be of type tt, or report errno and return null.
+ * NB: this macro uses cx and ts from its lexical environment.
+ */
+#define MUST_MATCH_TOKEN(tt, errno) \
+ JS_BEGIN_MACRO \
+ if (js_GetToken(cx, ts) != tt) { \
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, errno); \
+ return NULL; \
+ } \
+ JS_END_MACRO
+
+#ifdef METER_PARSENODES
+static uint32 parsenodes = 0;
+static uint32 maxparsenodes = 0;
+static uint32 recyclednodes = 0;
+#endif
+
+JSBool
+js_InitParseContext(JSContext *cx, JSParseContext *pc, JSPrincipals *principals,
+ JSStackFrame *callerFrame,
+ const jschar *base, size_t length,
+ FILE *fp, const char *filename, uintN lineno)
+{
+ JS_ASSERT_IF(callerFrame, callerFrame->script);
+
+ pc->tempPoolMark = JS_ARENA_MARK(&cx->tempPool);
+ if (!js_InitTokenStream(cx, TS(pc), base, length, fp, filename, lineno)) {
+ JS_ARENA_RELEASE(&cx->tempPool, pc->tempPoolMark);
+ return JS_FALSE;
+ }
+ if (principals)
+ JSPRINCIPALS_HOLD(cx, principals);
+ pc->principals = principals;
+ pc->callerFrame = callerFrame;
+ pc->nodeList = NULL;
+ pc->traceListHead = NULL;
+
+ /* Root atoms and objects allocated for the parsed tree. */
+ JS_KEEP_ATOMS(cx->runtime);
+ JS_PUSH_TEMP_ROOT_PARSE_CONTEXT(cx, pc, &pc->tempRoot);
+ return JS_TRUE;
+}
+
+void
+js_FinishParseContext(JSContext *cx, JSParseContext *pc)
+{
+ if (pc->principals)
+ JSPRINCIPALS_DROP(cx, pc->principals);
+ JS_ASSERT(pc->tempRoot.u.parseContext == pc);
+ JS_POP_TEMP_ROOT(cx, &pc->tempRoot);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ js_CloseTokenStream(cx, TS(pc));
+ JS_ARENA_RELEASE(&cx->tempPool, pc->tempPoolMark);
+}
+
+void
+js_InitCompilePrincipals(JSContext *cx, JSParseContext *pc,
+ JSPrincipals *principals)
+{
+ JS_ASSERT(!pc->principals);
+ if (principals)
+ JSPRINCIPALS_HOLD(cx, principals);
+ pc->principals = principals;
+}
+
+JSParsedObjectBox *
+js_NewParsedObjectBox(JSContext *cx, JSParseContext *pc, JSObject *obj)
+{
+ JSParsedObjectBox *pob;
+
+ /*
+ * We use JSContext.tempPool to allocate parsed objects and place them on
+ * a list in JSTokenStream to ensure GC safety. Thus the tempPool arenas
+ * containing the entries must be alive until we are done with scanning,
+ * parsing and code generation for the whole script or top-level function.
+ */
+ JS_ASSERT(obj);
+ JS_ARENA_ALLOCATE_TYPE(pob, JSParsedObjectBox, &cx->tempPool);
+ if (!pob) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ pob->traceLink = pc->traceListHead;
+ pob->emitLink = NULL;
+ pob->object = obj;
+ pc->traceListHead = pob;
+ return pob;
+}
+
+
+void
+js_TraceParseContext(JSTracer *trc, JSParseContext *pc)
+{
+ JSParsedObjectBox *pob;
+
+ JS_ASSERT(pc->tempRoot.u.parseContext == pc);
+ pob = pc->traceListHead;
+ while (pob) {
+ JS_CALL_OBJECT_TRACER(trc, pob->object, "parser.object");
+ pob = pob->traceLink;
+ }
+}
+
+static JSParseNode *
+RecycleTree(JSParseNode *pn, JSTreeContext *tc)
+{
+ JSParseNode *next;
+
+ if (!pn)
+ return NULL;
+
+ /* Catch back-to-back dup recycles. */
+ JS_ASSERT(pn != tc->parseContext->nodeList);
+ next = pn->pn_next;
+ pn->pn_next = tc->parseContext->nodeList;
+ tc->parseContext->nodeList = pn;
+#ifdef METER_PARSENODES
+ recyclednodes++;
+#endif
+ return next;
+}
+
+static JSParseNode *
+NewOrRecycledNode(JSContext *cx, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = tc->parseContext->nodeList;
+ if (!pn) {
+ JS_ARENA_ALLOCATE_TYPE(pn, JSParseNode, &cx->tempPool);
+ if (!pn)
+ js_ReportOutOfScriptQuota(cx);
+ } else {
+ tc->parseContext->nodeList = pn->pn_next;
+
+ /* Recycle immediate descendents only, to save work and working set. */
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ RecycleTree(pn->pn_body, tc);
+ break;
+ case PN_LIST:
+ if (pn->pn_head) {
+ /* XXX check for dup recycles in the list */
+ *pn->pn_tail = tc->parseContext->nodeList;
+ tc->parseContext->nodeList = pn->pn_head;
+#ifdef METER_PARSENODES
+ recyclednodes += pn->pn_count;
+#endif
+ }
+ break;
+ case PN_TERNARY:
+ RecycleTree(pn->pn_kid1, tc);
+ RecycleTree(pn->pn_kid2, tc);
+ RecycleTree(pn->pn_kid3, tc);
+ break;
+ case PN_BINARY:
+ if (pn->pn_left != pn->pn_right)
+ RecycleTree(pn->pn_left, tc);
+ RecycleTree(pn->pn_right, tc);
+ break;
+ case PN_UNARY:
+ RecycleTree(pn->pn_kid, tc);
+ break;
+ case PN_NAME:
+ RecycleTree(pn->pn_expr, tc);
+ break;
+ case PN_NULLARY:
+ break;
+ }
+ }
+ if (pn) {
+#ifdef METER_PARSENODES
+ parsenodes++;
+ if (parsenodes - recyclednodes > maxparsenodes)
+ maxparsenodes = parsenodes - recyclednodes;
+#endif
+ memset(&pn->pn_u, 0, sizeof pn->pn_u);
+ pn->pn_next = NULL;
+ }
+ return pn;
+}
+
+/*
+ * Allocate a JSParseNode from cx's temporary arena.
+ */
+static JSParseNode *
+NewParseNode(JSContext *cx, JSTokenStream *ts, JSParseNodeArity arity,
+ JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSToken *tp;
+
+ pn = NewOrRecycledNode(cx, tc);
+ if (!pn)
+ return NULL;
+ tp = &CURRENT_TOKEN(ts);
+ pn->pn_type = tp->type;
+ pn->pn_pos = tp->pos;
+ pn->pn_op = JSOP_NOP;
+ pn->pn_arity = arity;
+ return pn;
+}
+
+static JSParseNode *
+NewBinary(JSContext *cx, JSTokenType tt,
+ JSOp op, JSParseNode *left, JSParseNode *right,
+ JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn1, *pn2;
+
+ if (!left || !right)
+ return NULL;
+
+ /*
+ * Flatten a left-associative (left-heavy) tree of a given operator into
+ * a list, to reduce js_FoldConstants and js_EmitTree recursion.
+ */
+ if (left->pn_type == tt &&
+ left->pn_op == op &&
+ (js_CodeSpec[op].format & JOF_LEFTASSOC)) {
+ if (left->pn_arity != PN_LIST) {
+ pn1 = left->pn_left, pn2 = left->pn_right;
+ left->pn_arity = PN_LIST;
+ PN_INIT_LIST_1(left, pn1);
+ PN_APPEND(left, pn2);
+ if (tt == TOK_PLUS) {
+ if (pn1->pn_type == TOK_STRING)
+ left->pn_extra |= PNX_STRCAT;
+ else if (pn1->pn_type != TOK_NUMBER)
+ left->pn_extra |= PNX_CANTFOLD;
+ if (pn2->pn_type == TOK_STRING)
+ left->pn_extra |= PNX_STRCAT;
+ else if (pn2->pn_type != TOK_NUMBER)
+ left->pn_extra |= PNX_CANTFOLD;
+ }
+ }
+ PN_APPEND(left, right);
+ left->pn_pos.end = right->pn_pos.end;
+ if (tt == TOK_PLUS) {
+ if (right->pn_type == TOK_STRING)
+ left->pn_extra |= PNX_STRCAT;
+ else if (right->pn_type != TOK_NUMBER)
+ left->pn_extra |= PNX_CANTFOLD;
+ }
+ return left;
+ }
+
+ /*
+ * Fold constant addition immediately, to conserve node space and, what's
+ * more, so js_FoldConstants never sees mixed addition and concatenation
+ * operations with more than one leading non-string operand in a PN_LIST
+ * generated for expressions such as 1 + 2 + "pt" (which should evaluate
+ * to "3pt", not "12pt").
+ */
+ if (tt == TOK_PLUS &&
+ left->pn_type == TOK_NUMBER &&
+ right->pn_type == TOK_NUMBER) {
+ left->pn_dval += right->pn_dval;
+ left->pn_pos.end = right->pn_pos.end;
+ RecycleTree(right, tc);
+ return left;
+ }
+
+ pn = NewOrRecycledNode(cx, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = tt;
+ pn->pn_pos.begin = left->pn_pos.begin;
+ pn->pn_pos.end = right->pn_pos.end;
+ pn->pn_op = op;
+ pn->pn_arity = PN_BINARY;
+ pn->pn_left = left;
+ pn->pn_right = right;
+ return pn;
+}
+
+#if JS_HAS_GETTER_SETTER
+static JSTokenType
+CheckGetterOrSetter(JSContext *cx, JSTokenStream *ts, JSTokenType tt)
+{
+ JSAtom *atom;
+ JSRuntime *rt;
+ JSOp op;
+ const char *name;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_NAME);
+ atom = CURRENT_TOKEN(ts).t_atom;
+ rt = cx->runtime;
+ if (atom == rt->atomState.getterAtom)
+ op = JSOP_GETTER;
+ else if (atom == rt->atomState.setterAtom)
+ op = JSOP_SETTER;
+ else
+ return TOK_NAME;
+ if (js_PeekTokenSameLine(cx, ts) != tt)
+ return TOK_NAME;
+ (void) js_GetToken(cx, ts);
+ if (CURRENT_TOKEN(ts).t_op != JSOP_NOP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_GETTER_OR_SETTER,
+ (op == JSOP_GETTER)
+ ? js_getter_str
+ : js_setter_str);
+ return TOK_ERROR;
+ }
+ CURRENT_TOKEN(ts).t_op = op;
+ if (JS_HAS_STRICT_OPTION(cx)) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_DEPRECATED_USAGE,
+ name)) {
+ return TOK_ERROR;
+ }
+ }
+ return tt;
+}
+#endif
+
+/*
+ * Parse a top-level JS script.
+ */
+JSParseNode *
+js_ParseScript(JSContext *cx, JSObject *chain, JSParseContext *pc)
+{
+ JSTreeContext tc;
+ JSParseNode *pn;
+
+ /*
+ * Protect atoms from being collected by a GC activation, which might
+ * - nest on this thread due to out of memory (the so-called "last ditch"
+ * GC attempted within js_NewGCThing), or
+ * - run for any reason on another thread if this thread is suspended on
+ * an object lock before it finishes generating bytecode into a script
+ * protected from the GC by a root or a stack frame reference.
+ */
+ TREE_CONTEXT_INIT(&tc, pc);
+ tc.u.scopeChain = chain;
+ pn = Statements(cx, TS(pc), &tc);
+ if (pn) {
+ if (!js_MatchToken(cx, TS(pc), TOK_EOF)) {
+ js_ReportCompileErrorNumber(cx, TS(pc), NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ pn = NULL;
+ } else {
+ pn->pn_type = TOK_LC;
+ if (!js_FoldConstants(cx, pn, &tc))
+ pn = NULL;
+ }
+ }
+
+ TREE_CONTEXT_FINISH(cx, &tc);
+ return pn;
+}
+
+/*
+ * Compile a top-level script.
+ */
+extern JSScript *
+js_CompileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *callerFrame,
+ JSPrincipals *principals, uint32 tcflags,
+ const jschar *chars, size_t length,
+ FILE *file, const char *filename, uintN lineno)
+{
+ JSParseContext pc;
+ JSArenaPool codePool, notePool;
+ JSCodeGenerator cg;
+ JSTokenType tt;
+ JSParseNode *pn;
+ uint32 scriptGlobals;
+ JSScript *script;
+#ifdef METER_PARSENODES
+ void *sbrk(ptrdiff_t), *before = sbrk(0);
+#endif
+
+ JS_ASSERT(!(tcflags & ~(TCF_COMPILE_N_GO | TCF_NO_SCRIPT_RVAL |
+ TCF_STATIC_DEPTH_MASK)));
+
+ /*
+ * The scripted callerFrame can only be given for compile-and-go scripts
+ * and non-zero static depth requires callerFrame.
+ */
+ JS_ASSERT_IF(callerFrame, tcflags & TCF_COMPILE_N_GO);
+ JS_ASSERT_IF(TCF_GET_STATIC_DEPTH(tcflags) != 0, callerFrame);
+
+ if (!js_InitParseContext(cx, &pc, principals, callerFrame, chars, length,
+ file, filename, lineno)) {
+ return NULL;
+ }
+
+ JS_INIT_ARENA_POOL(&codePool, "code", 1024, sizeof(jsbytecode),
+ &cx->scriptStackQuota);
+ JS_INIT_ARENA_POOL(&notePool, "note", 1024, sizeof(jssrcnote),
+ &cx->scriptStackQuota);
+ js_InitCodeGenerator(cx, &cg, &pc, &codePool, &notePool,
+ pc.tokenStream.lineno);
+
+ MUST_FLOW_THROUGH("out");
+ cg.treeContext.flags |= (uint16) tcflags;
+ cg.treeContext.u.scopeChain = scopeChain;
+ cg.staticDepth = TCF_GET_STATIC_DEPTH(tcflags);
+
+ if ((tcflags & TCF_COMPILE_N_GO) && callerFrame && callerFrame->fun) {
+ /*
+ * An eval script in a caller frame needs to have its enclosing function
+ * captured in case it uses an upvar reference, and someone wishes to
+ * decompile it while running.
+ */
+ JSParsedObjectBox *pob = js_NewParsedObjectBox(cx, &pc, callerFrame->callee);
+ pob->emitLink = cg.objectList.lastPob;
+ cg.objectList.lastPob = pob;
+ cg.objectList.length++;
+ }
+
+ /* Inline Statements() to emit as we go to save space. */
+ for (;;) {
+ pc.tokenStream.flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, &pc.tokenStream);
+ pc.tokenStream.flags &= ~TSF_OPERAND;
+ if (tt <= TOK_EOF) {
+ if (tt == TOK_EOF)
+ break;
+ JS_ASSERT(tt == TOK_ERROR);
+ script = NULL;
+ goto out;
+ }
+
+ pn = Statement(cx, &pc.tokenStream, &cg.treeContext);
+ if (!pn) {
+ script = NULL;
+ goto out;
+ }
+ JS_ASSERT(!cg.treeContext.blockNode);
+
+ if (!js_FoldConstants(cx, pn, &cg.treeContext) ||
+ !js_EmitTree(cx, &cg, pn)) {
+ script = NULL;
+ goto out;
+ }
+ RecycleTree(pn, &cg.treeContext);
+ }
+
+ /*
+ * Global variables and regexps shares the index space with locals. Due to
+ * incremental code generation we need to patch the bytecode to adjust the
+ * local references to skip the globals.
+ */
+ scriptGlobals = cg.treeContext.ngvars + cg.regexpList.length;
+ if (scriptGlobals != 0) {
+ jsbytecode *code, *end;
+ JSOp op;
+ const JSCodeSpec *cs;
+ uintN len, slot;
+
+ if (scriptGlobals >= SLOTNO_LIMIT)
+ goto too_many_slots;
+ code = CG_BASE(&cg);
+ for (end = code + CG_OFFSET(&cg); code != end; code += len) {
+ JS_ASSERT(code < end);
+ op = (JSOp) *code;
+ cs = &js_CodeSpec[op];
+ len = (cs->length > 0)
+ ? (uintN) cs->length
+ : js_GetVariableBytecodeLength(code);
+ if (JOF_TYPE(cs->format) == JOF_LOCAL ||
+ (JOF_TYPE(cs->format) == JOF_SLOTATOM)) {
+ /*
+ * JSOP_GETARGPROP also has JOF_SLOTATOM type, but it may be
+ * emitted only for a function.
+ */
+ JS_ASSERT((JOF_TYPE(cs->format) == JOF_SLOTATOM) ==
+ (op == JSOP_GETLOCALPROP));
+ slot = GET_SLOTNO(code);
+ slot += scriptGlobals;
+ if (slot >= SLOTNO_LIMIT)
+ goto too_many_slots;
+ SET_SLOTNO(code, slot);
+ }
+ }
+ }
+
+#ifdef METER_PARSENODES
+ printf("Parser growth: %d (%u nodes, %u max, %u unrecycled)\n",
+ (char *)sbrk(0) - (char *)before,
+ parsenodes,
+ maxparsenodes,
+ parsenodes - recyclednodes);
+ before = sbrk(0);
+#endif
+
+ /*
+ * Nowadays the threaded interpreter needs a stop instruction, so we
+ * do have to emit that here.
+ */
+ if (js_Emit1(cx, &cg, JSOP_STOP) < 0) {
+ script = NULL;
+ goto out;
+ }
+#ifdef METER_PARSENODES
+ printf("Code-gen growth: %d (%u bytecodes, %u srcnotes)\n",
+ (char *)sbrk(0) - (char *)before, CG_OFFSET(cg), cg->noteCount);
+#endif
+#ifdef JS_ARENAMETER
+ JS_DumpArenaStats(stdout);
+#endif
+ script = js_NewScriptFromCG(cx, &cg);
+
+#ifdef JS_SCOPE_DEPTH_METER
+ if (script) {
+ JSObject *obj = scopeChain;
+ uintN depth = 1;
+ while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL)
+ ++depth;
+ JS_BASIC_STATS_ACCUM(&cx->runtime->hostenvScopeDepthStats, depth);
+ }
+#endif
+
+ out:
+ js_FinishCodeGenerator(cx, &cg);
+ JS_FinishArenaPool(&codePool);
+ JS_FinishArenaPool(&notePool);
+ js_FinishParseContext(cx, &pc);
+ return script;
+
+ too_many_slots:
+ js_ReportCompileErrorNumber(cx, &pc.tokenStream, NULL,
+ JSREPORT_ERROR, JSMSG_TOO_MANY_LOCALS);
+ script = NULL;
+ goto out;
+}
+
+/*
+ * Insist on a final return before control flows out of pn. Try to be a bit
+ * smart about loops: do {...; return e2;} while(0) at the end of a function
+ * that contains an early return e1 will get a strict warning. Similarly for
+ * iloops: while (true){...} is treated as though ... returns.
+ */
+#define ENDS_IN_OTHER 0
+#define ENDS_IN_RETURN 1
+#define ENDS_IN_BREAK 2
+
+static int
+HasFinalReturn(JSParseNode *pn)
+{
+ JSParseNode *pn2, *pn3;
+ uintN rv, rv2, hasDefault;
+
+ switch (pn->pn_type) {
+ case TOK_LC:
+ if (!pn->pn_head)
+ return ENDS_IN_OTHER;
+ return HasFinalReturn(PN_LAST(pn));
+
+ case TOK_IF:
+ if (!pn->pn_kid3)
+ return ENDS_IN_OTHER;
+ return HasFinalReturn(pn->pn_kid2) & HasFinalReturn(pn->pn_kid3);
+
+ case TOK_WHILE:
+ pn2 = pn->pn_left;
+ if (pn2->pn_type == TOK_PRIMARY && pn2->pn_op == JSOP_TRUE)
+ return ENDS_IN_RETURN;
+ if (pn2->pn_type == TOK_NUMBER && pn2->pn_dval)
+ return ENDS_IN_RETURN;
+ return ENDS_IN_OTHER;
+
+ case TOK_DO:
+ pn2 = pn->pn_right;
+ if (pn2->pn_type == TOK_PRIMARY) {
+ if (pn2->pn_op == JSOP_FALSE)
+ return HasFinalReturn(pn->pn_left);
+ if (pn2->pn_op == JSOP_TRUE)
+ return ENDS_IN_RETURN;
+ }
+ if (pn2->pn_type == TOK_NUMBER) {
+ if (pn2->pn_dval == 0)
+ return HasFinalReturn(pn->pn_left);
+ return ENDS_IN_RETURN;
+ }
+ return ENDS_IN_OTHER;
+
+ case TOK_FOR:
+ pn2 = pn->pn_left;
+ if (pn2->pn_arity == PN_TERNARY && !pn2->pn_kid2)
+ return ENDS_IN_RETURN;
+ return ENDS_IN_OTHER;
+
+ case TOK_SWITCH:
+ rv = ENDS_IN_RETURN;
+ hasDefault = ENDS_IN_OTHER;
+ pn2 = pn->pn_right;
+ if (pn2->pn_type == TOK_LEXICALSCOPE)
+ pn2 = pn2->pn_expr;
+ for (pn2 = pn2->pn_head; rv && pn2; pn2 = pn2->pn_next) {
+ if (pn2->pn_type == TOK_DEFAULT)
+ hasDefault = ENDS_IN_RETURN;
+ pn3 = pn2->pn_right;
+ JS_ASSERT(pn3->pn_type == TOK_LC);
+ if (pn3->pn_head) {
+ rv2 = HasFinalReturn(PN_LAST(pn3));
+ if (rv2 == ENDS_IN_OTHER && pn2->pn_next)
+ /* Falling through to next case or default. */;
+ else
+ rv &= rv2;
+ }
+ }
+ /* If a final switch has no default case, we judge it harshly. */
+ rv &= hasDefault;
+ return rv;
+
+ case TOK_BREAK:
+ return ENDS_IN_BREAK;
+
+ case TOK_WITH:
+ return HasFinalReturn(pn->pn_right);
+
+ case TOK_RETURN:
+ return ENDS_IN_RETURN;
+
+ case TOK_COLON:
+ case TOK_LEXICALSCOPE:
+ return HasFinalReturn(pn->pn_expr);
+
+ case TOK_THROW:
+ return ENDS_IN_RETURN;
+
+ case TOK_TRY:
+ /* If we have a finally block that returns, we are done. */
+ if (pn->pn_kid3) {
+ rv = HasFinalReturn(pn->pn_kid3);
+ if (rv == ENDS_IN_RETURN)
+ return rv;
+ }
+
+ /* Else check the try block and any and all catch statements. */
+ rv = HasFinalReturn(pn->pn_kid1);
+ if (pn->pn_kid2) {
+ JS_ASSERT(pn->pn_kid2->pn_arity == PN_LIST);
+ for (pn2 = pn->pn_kid2->pn_head; pn2; pn2 = pn2->pn_next)
+ rv &= HasFinalReturn(pn2);
+ }
+ return rv;
+
+ case TOK_CATCH:
+ /* Check this catch block's body. */
+ return HasFinalReturn(pn->pn_kid3);
+
+ case TOK_LET:
+ /* Non-binary let statements are let declarations. */
+ if (pn->pn_arity != PN_BINARY)
+ return ENDS_IN_OTHER;
+ return HasFinalReturn(pn->pn_right);
+
+ default:
+ return ENDS_IN_OTHER;
+ }
+}
+
+static JSBool
+ReportBadReturn(JSContext *cx, JSTreeContext *tc, uintN flags, uintN errnum,
+ uintN anonerrnum)
+{
+ const char *name;
+
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ if (tc->u.fun->atom) {
+ name = js_AtomToPrintableString(cx, tc->u.fun->atom);
+ } else {
+ errnum = anonerrnum;
+ name = NULL;
+ }
+ return js_ReportCompileErrorNumber(cx, TS(tc->parseContext), NULL, flags,
+ errnum, name);
+}
+
+static JSBool
+CheckFinalReturn(JSContext *cx, JSTreeContext *tc, JSParseNode *pn)
+{
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ return HasFinalReturn(pn) == ENDS_IN_RETURN ||
+ ReportBadReturn(cx, tc, JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE);
+}
+
+static JSParseNode *
+FunctionBody(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSStmtInfo stmtInfo;
+ uintN oldflags, firstLine;
+ JSParseNode *pn;
+
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
+ stmtInfo.flags = SIF_BODY_BLOCK;
+
+ oldflags = tc->flags;
+ tc->flags &= ~(TCF_RETURN_EXPR | TCF_RETURN_VOID);
+
+ /*
+ * Save the body's first line, and store it in pn->pn_pos.begin.lineno
+ * later, because we may have not peeked in ts yet, so Statements won't
+ * acquire a valid pn->pn_pos.begin from the current token.
+ */
+ firstLine = ts->lineno;
+#if JS_HAS_EXPR_CLOSURES
+ if (CURRENT_TOKEN(ts).type == TOK_LC) {
+ pn = Statements(cx, ts, tc);
+ } else {
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (pn) {
+ pn->pn_kid = AssignExpr(cx, ts, tc);
+ if (!pn->pn_kid) {
+ pn = NULL;
+ } else {
+ if (tc->flags & TCF_FUN_IS_GENERATOR) {
+ ReportBadReturn(cx, tc, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_RETURN,
+ JSMSG_BAD_ANON_GENERATOR_RETURN);
+ pn = NULL;
+ } else {
+ pn->pn_type = TOK_RETURN;
+ pn->pn_op = JSOP_RETURN;
+ pn->pn_pos.end = pn->pn_kid->pn_pos.end;
+ }
+ }
+ }
+ }
+#else
+ pn = Statements(cx, ts, tc);
+#endif
+
+ if (pn) {
+ js_PopStatement(tc);
+ pn->pn_pos.begin.lineno = firstLine;
+
+ /* Check for falling off the end of a function that returns a value. */
+ if (JS_HAS_STRICT_OPTION(cx) && (tc->flags & TCF_RETURN_EXPR) &&
+ !CheckFinalReturn(cx, tc, pn)) {
+ pn = NULL;
+ }
+ }
+
+ tc->flags = oldflags | (tc->flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS));
+ return pn;
+}
+
+/*
+ * Compile a JS function body, which might appear as the value of an event
+ * handler attribute in an HTML <INPUT> tag.
+ */
+JSBool
+js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno)
+{
+ JSParseContext pc;
+ JSArenaPool codePool, notePool;
+ JSCodeGenerator funcg;
+ JSParseNode *pn;
+
+ if (!js_InitParseContext(cx, &pc, principals, NULL, chars, length, NULL,
+ filename, lineno)) {
+ return JS_FALSE;
+ }
+
+ /* No early return from this point until js_FinishParseContext call. */
+ JS_INIT_ARENA_POOL(&codePool, "code", 1024, sizeof(jsbytecode),
+ &cx->scriptStackQuota);
+ JS_INIT_ARENA_POOL(&notePool, "note", 1024, sizeof(jssrcnote),
+ &cx->scriptStackQuota);
+ js_InitCodeGenerator(cx, &funcg, &pc, &codePool, &notePool,
+ pc.tokenStream.lineno);
+ funcg.treeContext.flags |= TCF_IN_FUNCTION;
+ funcg.treeContext.u.fun = fun;
+
+ /*
+ * Farble the body so that it looks like a block statement to js_EmitTree,
+ * which is called beneath FunctionBody; see Statements, further below in
+ * this file. FunctionBody pushes a STMT_BLOCK record around its call to
+ * Statements, so Statements will not compile each statement as it loops
+ * to save JSParseNode space -- it will not compile at all, only build a
+ * JSParseNode tree.
+ *
+ * Therefore we must fold constants, allocate try notes, and generate code
+ * for this function, including a stop opcode at the end.
+ */
+ CURRENT_TOKEN(&pc.tokenStream).type = TOK_LC;
+ pn = FunctionBody(cx, &pc.tokenStream, &funcg.treeContext);
+ if (pn) {
+ if (!js_MatchToken(cx, &pc.tokenStream, TOK_EOF)) {
+ js_ReportCompileErrorNumber(cx, &pc.tokenStream, NULL,
+ JSREPORT_ERROR, JSMSG_SYNTAX_ERROR);
+ pn = NULL;
+ } else {
+ if (!js_FoldConstants(cx, pn, &funcg.treeContext) ||
+ !js_EmitFunctionScript(cx, &funcg, pn)) {
+ pn = NULL;
+ }
+ }
+ }
+
+ /* Restore saved state and release code generation arenas. */
+ js_FinishCodeGenerator(cx, &funcg);
+ JS_FinishArenaPool(&codePool);
+ JS_FinishArenaPool(&notePool);
+ js_FinishParseContext(cx, &pc);
+ return pn != NULL;
+}
+
+/*
+ * Parameter block types for the several Binder functions. We use a common
+ * helper function signature in order to share code among destructuring and
+ * simple variable declaration parsers. In the destructuring case, the binder
+ * function is called indirectly from the variable declaration parser by way
+ * of CheckDestructuring and its friends.
+ */
+typedef struct BindData BindData;
+
+typedef JSBool
+(*Binder)(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc);
+
+struct BindData {
+ JSParseNode *pn; /* error source coordinate */
+ JSOp op; /* prolog bytecode or nop */
+ Binder binder; /* binder, discriminates u */
+ union {
+ struct {
+ uintN overflow;
+ } let;
+ } u;
+};
+
+static JSBool
+BindArg(JSContext *cx, JSAtom *atom, JSTreeContext *tc)
+{
+ const char *name;
+
+ /*
+ * Check for a duplicate parameter name, a "feature" required by ECMA-262.
+ */
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ if (js_LookupLocal(cx, tc->u.fun, atom, NULL) != JSLOCAL_NONE) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, TS(tc->parseContext), NULL,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_DUPLICATE_FORMAL,
+ name)) {
+ return JS_FALSE;
+ }
+ }
+
+ return js_AddLocal(cx, tc->u.fun, atom, JSLOCAL_ARG);
+}
+
+static JSBool
+BindLocalVariable(JSContext *cx, JSFunction *fun, JSAtom *atom,
+ JSLocalKind localKind)
+{
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+
+ /*
+ * Don't bind a variable with the hidden name 'arguments', per ECMA-262.
+ * Instead 'var arguments' always restates the predefined property of the
+ * activation objects with unhidden name 'arguments'. Assignment to such
+ * a variable must be handled specially.
+ */
+ if (atom == cx->runtime->atomState.argumentsAtom)
+ return JS_TRUE;
+
+ return js_AddLocal(cx, fun, atom, localKind);
+}
+
+#if JS_HAS_DESTRUCTURING
+/*
+ * Forward declaration to maintain top-down presentation.
+ */
+static JSParseNode *
+DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
+ JSTokenType tt);
+
+static JSBool
+BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
+ JSTreeContext *tc)
+{
+ JSAtomListElement *ale;
+ const char *name;
+
+ JS_ASSERT(tc->flags & TCF_IN_FUNCTION);
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ if (!ale) {
+ ale = js_IndexAtom(cx, atom, &tc->decls);
+ if (!ale)
+ return JS_FALSE;
+ ALE_SET_JSOP(ale, data->op);
+ }
+
+ if (js_LookupLocal(cx, tc->u.fun, atom, NULL) != JSLOCAL_NONE) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_DUPLICATE_FORMAL,
+ name)) {
+ return JS_FALSE;
+ }
+ } else {
+ if (!BindLocalVariable(cx, tc->u.fun, atom, JSLOCAL_VAR))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+#endif /* JS_HAS_DESTRUCTURING */
+
+static JSFunction *
+NewCompilerFunction(JSContext *cx, JSTreeContext *tc, JSAtom *atom,
+ uintN lambda)
+{
+ JSObject *parent;
+ JSFunction *fun;
+
+ JS_ASSERT((lambda & ~JSFUN_LAMBDA) == 0);
+ parent = (tc->flags & TCF_IN_FUNCTION)
+ ? FUN_OBJECT(tc->u.fun)
+ : tc->u.scopeChain;
+ fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED | lambda,
+ parent, atom);
+ if (fun && !(tc->flags & TCF_COMPILE_N_GO)) {
+ STOBJ_CLEAR_PARENT(FUN_OBJECT(fun));
+ STOBJ_CLEAR_PROTO(FUN_OBJECT(fun));
+ }
+ return fun;
+}
+
+static JSParseNode *
+FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ uintN lambda)
+{
+ JSOp op, prevop;
+ JSParseNode *pn, *body, *result;
+ JSTokenType tt;
+ JSAtom *funAtom;
+ JSParsedObjectBox *funpob;
+ JSAtomListElement *ale;
+ JSFunction *fun;
+ JSTreeContext funtc;
+#if JS_HAS_DESTRUCTURING
+ JSParseNode *item, *list = NULL;
+#endif
+
+ /* Make a TOK_FUNCTION node. */
+#if JS_HAS_GETTER_SETTER
+ op = CURRENT_TOKEN(ts).t_op;
+#endif
+ pn = NewParseNode(cx, ts, PN_FUNC, tc);
+ if (!pn)
+ return NULL;
+#ifdef DEBUG
+ pn->pn_index = (uint32) -1;
+#endif
+
+ /* Scan the optional function name into funAtom. */
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_NAME) {
+ funAtom = CURRENT_TOKEN(ts).t_atom;
+ } else {
+ if (lambda == 0 && (cx->options & JSOPTION_ANONFUNFIX)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ funAtom = NULL;
+ js_UngetToken(ts);
+ }
+
+ /*
+ * Record names for function statements in tc->decls so we know when to
+ * avoid optimizing variable references that might name a function.
+ */
+ if (lambda == 0 && funAtom) {
+ ATOM_LIST_SEARCH(ale, &tc->decls, funAtom);
+ if (ale) {
+ prevop = ALE_JSOP(ale);
+ if (JS_HAS_STRICT_OPTION(cx) || prevop == JSOP_DEFCONST) {
+ const char *name = js_AtomToPrintableString(cx, funAtom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, ts, NULL,
+ (prevop != JSOP_DEFCONST)
+ ? JSREPORT_WARNING |
+ JSREPORT_STRICT
+ : JSREPORT_ERROR,
+ JSMSG_REDECLARED_VAR,
+ (prevop == JSOP_DEFFUN)
+ ? js_function_str
+ : (prevop == JSOP_DEFCONST)
+ ? js_const_str
+ : js_var_str,
+ name)) {
+ return NULL;
+ }
+ }
+ if (!AT_TOP_LEVEL(tc) && prevop == JSOP_DEFVAR)
+ tc->flags |= TCF_FUN_CLOSURE_VS_VAR;
+ } else {
+ ale = js_IndexAtom(cx, funAtom, &tc->decls);
+ if (!ale)
+ return NULL;
+ }
+ ALE_SET_JSOP(ale, JSOP_DEFFUN);
+
+ /*
+ * A function nested at top level inside another's body needs only a
+ * local variable to bind its name to its value, and not an activation
+ * object property (it might also need the activation property, if the
+ * outer function contains with statements, e.g., but the stack slot
+ * wins when jsemit.c's BindNameToSlot can optimize a JSOP_NAME into a
+ * JSOP_GETLOCAL bytecode).
+ */
+ if (AT_TOP_LEVEL(tc) && (tc->flags & TCF_IN_FUNCTION)) {
+ JSLocalKind localKind;
+
+ /*
+ * Define a property on the outer function so that BindNameToSlot
+ * can properly optimize accesses. Note that we need a variable,
+ * not an argument, for the function statement. Thus we add a
+ * variable even if the parameter with the given name already
+ * exists.
+ */
+ localKind = js_LookupLocal(cx, tc->u.fun, funAtom, NULL);
+ if (localKind == JSLOCAL_NONE || localKind == JSLOCAL_ARG) {
+ if (!js_AddLocal(cx, tc->u.fun, funAtom, JSLOCAL_VAR))
+ return NULL;
+ }
+ }
+ }
+
+ fun = NewCompilerFunction(cx, tc, funAtom, lambda);
+ if (!fun)
+ return NULL;
+
+#if JS_HAS_GETTER_SETTER
+ if (op != JSOP_NOP)
+ fun->flags |= (op == JSOP_GETTER) ? JSPROP_GETTER : JSPROP_SETTER;
+#endif
+
+ /*
+ * Create wrapping box for fun->object early to protect against a
+ * last-ditch GC.
+ */
+ funpob = js_NewParsedObjectBox(cx, tc->parseContext, FUN_OBJECT(fun));
+ if (!funpob)
+ return NULL;
+
+ /* Initialize early for possible flags mutation via DestructuringExpr. */
+ TREE_CONTEXT_INIT(&funtc, tc->parseContext);
+ funtc.flags |= TCF_IN_FUNCTION | (tc->flags & TCF_COMPILE_N_GO);
+ funtc.u.fun = fun;
+
+ /* Now parse formal argument list and compute fun->nargs. */
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_FORMAL);
+ if (!js_MatchToken(cx, ts, TOK_RP)) {
+ do {
+ tt = js_GetToken(cx, ts);
+ switch (tt) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_LB:
+ case TOK_LC:
+ {
+ BindData data;
+ JSParseNode *lhs, *rhs;
+ jsint slot;
+
+ /*
+ * A destructuring formal parameter turns into one or more
+ * local variables initialized from properties of a single
+ * anonymous positional parameter, so here we must tweak our
+ * binder and its data.
+ */
+ data.pn = NULL;
+ data.op = JSOP_DEFVAR;
+ data.binder = BindDestructuringArg;
+ lhs = DestructuringExpr(cx, &data, &funtc, tt);
+ if (!lhs)
+ return NULL;
+
+ /*
+ * Adjust fun->nargs to count the single anonymous positional
+ * parameter that is to be destructured.
+ */
+ slot = fun->nargs;
+ if (!js_AddLocal(cx, fun, NULL, JSLOCAL_ARG))
+ return NULL;
+
+ /*
+ * Synthesize a destructuring assignment from the single
+ * anonymous positional parameter into the destructuring
+ * left-hand-side expression and accumulate it in list.
+ */
+ rhs = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!rhs)
+ return NULL;
+ rhs->pn_type = TOK_NAME;
+ rhs->pn_op = JSOP_GETARG;
+ rhs->pn_atom = cx->runtime->atomState.emptyAtom;
+ rhs->pn_slot = slot;
+
+ item = NewBinary(cx, TOK_ASSIGN, JSOP_NOP, lhs, rhs, tc);
+ if (!item)
+ return NULL;
+ if (!list) {
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = TOK_COMMA;
+ PN_INIT_LIST(list);
+ }
+ PN_APPEND(list, item);
+ break;
+ }
+#endif /* JS_HAS_DESTRUCTURING */
+
+ case TOK_NAME:
+ if (!BindArg(cx, CURRENT_TOKEN(ts).t_atom, &funtc))
+ return NULL;
+ break;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_MISSING_FORMAL);
+ return NULL;
+ }
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FORMAL);
+ }
+
+#if JS_HAS_EXPR_CLOSURES
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt != TOK_LC) {
+ js_UngetToken(ts);
+ fun->flags |= JSFUN_EXPR_CLOSURE;
+ }
+#else
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_BODY);
+#endif
+ pn->pn_pos.begin = CURRENT_TOKEN(ts).pos.begin;
+
+ body = FunctionBody(cx, ts, &funtc);
+ if (!body)
+ return NULL;
+
+#if JS_HAS_EXPR_CLOSURES
+ if (tt == TOK_LC)
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
+ else if (lambda == 0)
+ js_MatchToken(cx, ts, TOK_SEMI);
+#else
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
+#endif
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+
+#if JS_HAS_DESTRUCTURING
+ /*
+ * If there were destructuring formal parameters, prepend the initializing
+ * comma expression that we synthesized to body. If the body is a lexical
+ * scope node, we must make a special TOK_SEQ node, to prepend the formal
+ * parameter destructuring code without bracing the decompilation of the
+ * function body's lexical scope.
+ */
+ if (list) {
+ if (body->pn_arity != PN_LIST) {
+ JSParseNode *block;
+
+ block = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!block)
+ return NULL;
+ block->pn_type = TOK_SEQ;
+ block->pn_pos = body->pn_pos;
+ PN_INIT_LIST_1(block, body);
+
+ body = block;
+ }
+
+ item = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!item)
+ return NULL;
+
+ item->pn_type = TOK_SEMI;
+ item->pn_pos.begin = item->pn_pos.end = body->pn_pos.begin;
+ item->pn_kid = list;
+ item->pn_next = body->pn_head;
+ body->pn_head = item;
+ if (body->pn_tail == &body->pn_head)
+ body->pn_tail = &item->pn_next;
+ ++body->pn_count;
+ }
+#endif
+
+ /*
+ * If we collected flags that indicate nested heavyweight functions, or
+ * this function contains heavyweight-making statements (references to
+ * __parent__ or __proto__; use of with, or eval; and assignment to
+ * arguments), flag the function as heavyweight (requiring a call object
+ * per invocation).
+ */
+ if (funtc.flags & TCF_FUN_HEAVYWEIGHT) {
+ fun->flags |= JSFUN_HEAVYWEIGHT;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ } else {
+ /*
+ * If this function is a named statement function not at top-level
+ * (i.e. not a top-level function definiton or expression), then
+ * our enclosing function, if any, must be heavyweight.
+ *
+ * The TCF_FUN_USES_NONLOCALS flag is set only by the code generator,
+ * so it won't be set here. Assert that it's not. We have to check
+ * it later, in js_EmitTree, after js_EmitFunctionScript has traversed
+ * the function's body.
+ */
+ JS_ASSERT(!(funtc.flags & TCF_FUN_USES_NONLOCALS));
+ if (lambda == 0 && funAtom && !AT_TOP_LEVEL(tc))
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+
+ result = pn;
+ if (lambda != 0) {
+ /*
+ * ECMA ed. 3 standard: function expression, possibly anonymous.
+ */
+ op = funAtom ? JSOP_NAMEDFUNOBJ : JSOP_ANONFUNOBJ;
+ } else if (!funAtom) {
+ /*
+ * If this anonymous function definition is *not* embedded within a
+ * larger expression, we treat it as an expression statement, not as
+ * a function declaration -- and not as a syntax error (as ECMA-262
+ * Edition 3 would have it). Backward compatibility must trump all,
+ * unless JSOPTION_ANONFUNFIX is set.
+ */
+ result = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!result)
+ return NULL;
+ result->pn_type = TOK_SEMI;
+ result->pn_pos = pn->pn_pos;
+ result->pn_kid = pn;
+ op = JSOP_ANONFUNOBJ;
+ } else if (!AT_TOP_LEVEL(tc)) {
+ /*
+ * ECMA ed. 3 extension: a function expression statement not at the
+ * top level, e.g., in a compound statement such as the "then" part
+ * of an "if" statement, binds a closure only if control reaches that
+ * sub-statement.
+ */
+ op = JSOP_DEFFUN;
+ } else {
+ op = JSOP_NOP;
+ }
+
+ pn->pn_funpob = funpob;
+ pn->pn_op = op;
+ pn->pn_body = body;
+ pn->pn_flags = funtc.flags & (TCF_FUN_FLAGS | TCF_HAS_DEFXMLNS | TCF_COMPILE_N_GO);
+ TREE_CONTEXT_FINISH(cx, &funtc);
+ return result;
+}
+
+static JSParseNode *
+FunctionStmt(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ return FunctionDef(cx, ts, tc, 0);
+}
+
+static JSParseNode *
+FunctionExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ return FunctionDef(cx, ts, tc, JSFUN_LAMBDA);
+}
+
+/*
+ * Parse the statements in a block, creating a TOK_LC node that lists the
+ * statements' trees. If called from block-parsing code, the caller must
+ * match { before and } after.
+ */
+static JSParseNode *
+Statements(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2, *saveBlock;
+ JSTokenType tt;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ saveBlock = tc->blockNode;
+ tc->blockNode = pn;
+ PN_INIT_LIST(pn);
+
+ for (;;) {
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt <= TOK_EOF || tt == TOK_RC) {
+ if (tt == TOK_ERROR)
+ return NULL;
+ break;
+ }
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2) {
+ if (ts->flags & TSF_EOF)
+ ts->flags |= TSF_UNEXPECTED_EOF;
+ return NULL;
+ }
+
+ if (pn2->pn_type == TOK_FUNCTION) {
+ /*
+ * PNX_FUNCDEFS notifies the emitter that the block contains top-
+ * level function definitions that should be processed before the
+ * rest of nodes.
+ *
+ * TCF_HAS_FUNCTION_STMT is for the TOK_LC case in Statement. It
+ * is relevant only for function definitions not at top-level,
+ * which we call function statements.
+ */
+ if (AT_TOP_LEVEL(tc))
+ pn->pn_extra |= PNX_FUNCDEFS;
+ else
+ tc->flags |= TCF_HAS_FUNCTION_STMT;
+ }
+ PN_APPEND(pn, pn2);
+ }
+
+ /*
+ * Handle the case where there was a let declaration under this block. If
+ * it replaced tc->blockNode with a new block node then we must refresh pn
+ * and then restore tc->blockNode.
+ */
+ if (tc->blockNode != pn)
+ pn = tc->blockNode;
+ tc->blockNode = saveBlock;
+
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ return pn;
+}
+
+static JSParseNode *
+Condition(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_COND);
+ pn = ParenExpr(cx, ts, tc, NULL, NULL);
+ if (!pn)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_COND);
+
+ /*
+ * Check for (a = b) and warn about possible (a == b) mistype iff b's
+ * operator has greater precedence than ==.
+ */
+ if (pn->pn_type == TOK_ASSIGN &&
+ pn->pn_op == JSOP_NOP &&
+ pn->pn_right->pn_type > TOK_EQOP)
+ {
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_EQUAL_AS_ASSIGN,
+ "")) {
+ return NULL;
+ }
+ }
+ return pn;
+}
+
+static JSBool
+MatchLabel(JSContext *cx, JSTokenStream *ts, JSParseNode *pn)
+{
+ JSAtom *label;
+ JSTokenType tt;
+
+ tt = js_PeekTokenSameLine(cx, ts);
+ if (tt == TOK_ERROR)
+ return JS_FALSE;
+ if (tt == TOK_NAME) {
+ (void) js_GetToken(cx, ts);
+ label = CURRENT_TOKEN(ts).t_atom;
+ } else {
+ label = NULL;
+ }
+ pn->pn_atom = label;
+ return JS_TRUE;
+}
+
+static JSBool
+BindLet(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
+{
+ JSObject *blockObj;
+ JSScopeProperty *sprop;
+ JSAtomListElement *ale;
+ uintN n;
+
+ blockObj = tc->blockChain;
+ sprop = SCOPE_GET_PROPERTY(OBJ_SCOPE(blockObj), ATOM_TO_JSID(atom));
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ if (sprop || (ale && ALE_JSOP(ale) == JSOP_DEFCONST)) {
+ const char *name;
+
+ if (sprop) {
+ JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
+ JS_ASSERT((uint16)sprop->shortid < OBJ_BLOCK_COUNT(cx, blockObj));
+ }
+
+ name = js_AtomToPrintableString(cx, atom);
+ if (name) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_ERROR, JSMSG_REDECLARED_VAR,
+ (ale && ALE_JSOP(ale) == JSOP_DEFCONST)
+ ? js_const_str
+ : "variable",
+ name);
+ }
+ return JS_FALSE;
+ }
+
+ n = OBJ_BLOCK_COUNT(cx, blockObj);
+ if (n == JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_ERROR, data->u.let.overflow);
+ return JS_FALSE;
+ }
+
+ /* Use JSPROP_ENUMERATE to aid the disassembler. */
+ return js_DefineNativeProperty(cx, blockObj, ATOM_TO_JSID(atom),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE |
+ JSPROP_PERMANENT |
+ JSPROP_SHARED,
+ SPROP_HAS_SHORTID, (int16) n, NULL);
+}
+
+static JSBool
+BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, JSTreeContext *tc)
+{
+ JSStmtInfo *stmt;
+ JSAtomListElement *ale;
+ JSOp op, prevop;
+ const char *name;
+ JSLocalKind localKind;
+
+ stmt = js_LexicalLookup(tc, atom, NULL);
+ ATOM_LIST_SEARCH(ale, &tc->decls, atom);
+ op = data->op;
+ if ((stmt && stmt->type != STMT_WITH) || ale) {
+ prevop = ale ? ALE_JSOP(ale) : JSOP_DEFVAR;
+ if (JS_HAS_STRICT_OPTION(cx)
+ ? op != JSOP_DEFVAR || prevop != JSOP_DEFVAR
+ : op == JSOP_DEFCONST || prevop == JSOP_DEFCONST) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name ||
+ !js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ (op != JSOP_DEFCONST &&
+ prevop != JSOP_DEFCONST)
+ ? JSREPORT_WARNING |
+ JSREPORT_STRICT
+ : JSREPORT_ERROR,
+ JSMSG_REDECLARED_VAR,
+ (prevop == JSOP_DEFFUN)
+ ? js_function_str
+ : (prevop == JSOP_DEFCONST)
+ ? js_const_str
+ : js_var_str,
+ name)) {
+ return JS_FALSE;
+ }
+ }
+ if (op == JSOP_DEFVAR && prevop == JSOP_DEFFUN)
+ tc->flags |= TCF_FUN_CLOSURE_VS_VAR;
+ }
+ if (!ale) {
+ ale = js_IndexAtom(cx, atom, &tc->decls);
+ if (!ale)
+ return JS_FALSE;
+ }
+ ALE_SET_JSOP(ale, op);
+
+ if (!(tc->flags & TCF_IN_FUNCTION)) {
+ /*
+ * Don't lookup global variables or variables in an active frame at
+ * compile time.
+ */
+ return JS_TRUE;
+ }
+
+ localKind = js_LookupLocal(cx, tc->u.fun, atom, NULL);
+ if (localKind == JSLOCAL_NONE) {
+ /*
+ * Property not found in current variable scope: we have not seen this
+ * variable before. Define a new local variable by adding a property
+ * to the function's scope, allocating one slot in the function's vars
+ * frame. Any locals declared in with statement bodies are handled at
+ * runtime, by script prolog JSOP_DEFVAR opcodes generated for
+ * slot-less vars.
+ */
+ localKind = (data->op == JSOP_DEFCONST) ? JSLOCAL_CONST : JSLOCAL_VAR;
+ if (!js_InWithStatement(tc) &&
+ !BindLocalVariable(cx, tc->u.fun, atom, localKind)) {
+ return JS_FALSE;
+ }
+ } else if (localKind == JSLOCAL_ARG) {
+ name = js_AtomToPrintableString(cx, atom);
+ if (!name)
+ return JS_FALSE;
+
+ if (op == JSOP_DEFCONST) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_ERROR, JSMSG_REDECLARED_PARAM,
+ name);
+ return JS_FALSE;
+ }
+ if (!js_ReportCompileErrorNumber(cx, TS(tc->parseContext), data->pn,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_VAR_HIDES_ARG, name)) {
+ return JS_FALSE;
+ }
+ } else {
+ /* Not an argument, must be a redeclared local var. */
+ JS_ASSERT(localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+MakeSetCall(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, uintN msg)
+{
+ JSParseNode *pn2;
+
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ JS_ASSERT(pn->pn_op == JSOP_CALL || pn->pn_op == JSOP_EVAL || pn->pn_op == JSOP_APPLY);
+ pn2 = pn->pn_head;
+ if (pn2->pn_type == TOK_FUNCTION && (pn2->pn_flags & TCF_GENEXP_LAMBDA)) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), pn,
+ JSREPORT_ERROR, msg);
+ return JS_FALSE;
+ }
+ pn->pn_op = JSOP_SETCALL;
+ return JS_TRUE;
+}
+
+#if JS_HAS_DESTRUCTURING
+
+static JSBool
+BindDestructuringVar(JSContext *cx, BindData *data, JSParseNode *pn,
+ JSTreeContext *tc)
+{
+ JSAtom *atom;
+
+ /*
+ * Destructuring is a form of assignment, so just as for an initialized
+ * simple variable, we must check for assignment to 'arguments' and flag
+ * the enclosing function (if any) as heavyweight.
+ */
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ atom = pn->pn_atom;
+ if (atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+
+ data->pn = pn;
+ if (!data->binder(cx, data, atom, tc))
+ return JS_FALSE;
+ data->pn = NULL;
+
+ /*
+ * Select the appropriate name-setting opcode, which may be specialized
+ * further for local variable and argument slot optimizations. At this
+ * point, we can't select the optimal final opcode, yet we must preserve
+ * the CONST bit and convey "set", not "get".
+ */
+ if (data->op == JSOP_DEFCONST) {
+ pn->pn_op = JSOP_SETCONST;
+ pn->pn_const = JS_TRUE;
+ } else {
+ pn->pn_op = JSOP_SETNAME;
+ pn->pn_const = JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Here, we are destructuring {... P: Q, ...} = R, where P is any id, Q is any
+ * LHS expression except a destructuring initialiser, and R is on the stack.
+ * Because R is already evaluated, the usual LHS-specialized bytecodes won't
+ * work. After pushing R[P] we need to evaluate Q's "reference base" QB and
+ * then push its property name QN. At this point the stack looks like
+ *
+ * [... R, R[P], QB, QN]
+ *
+ * We need to set QB[QN] = R[P]. This is a job for JSOP_ENUMELEM, which takes
+ * its operands with left-hand side above right-hand side:
+ *
+ * [rval, lval, xval]
+ *
+ * and pops all three values, setting lval[xval] = rval. But we cannot select
+ * JSOP_ENUMELEM yet, because the LHS may turn out to be an arg or local var,
+ * which can be optimized further. So we select JSOP_SETNAME.
+ */
+static JSBool
+BindDestructuringLHS(JSContext *cx, JSParseNode *pn, JSTreeContext *tc)
+{
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+
+ switch (pn->pn_type) {
+ case TOK_NAME:
+ if (pn->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ /* FALL THROUGH */
+ case TOK_DOT:
+ case TOK_LB:
+ pn->pn_op = JSOP_SETNAME;
+ break;
+
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!MakeSetCall(cx, pn, tc, JSMSG_BAD_LEFTSIDE_OF_ASS))
+ return JS_FALSE;
+ break;
+#endif
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (pn->pn_op == JSOP_XMLNAME) {
+ pn->pn_op = JSOP_BINDXMLNAME;
+ break;
+ }
+ /* FALL THROUGH */
+#endif
+
+ default:
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), pn,
+ JSREPORT_ERROR, JSMSG_BAD_LEFTSIDE_OF_ASS);
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+typedef struct FindPropValData {
+ uint32 numvars; /* # of destructuring vars in left side */
+ uint32 maxstep; /* max # of steps searching right side */
+ JSDHashTable table; /* hash table for O(1) right side search */
+} FindPropValData;
+
+typedef struct FindPropValEntry {
+ JSDHashEntryHdr hdr;
+ JSParseNode *pnkey;
+ JSParseNode *pnval;
+} FindPropValEntry;
+
+#define ASSERT_VALID_PROPERTY_KEY(pnkey) \
+ JS_ASSERT((pnkey)->pn_arity == PN_NULLARY && \
+ ((pnkey)->pn_type == TOK_NUMBER || \
+ (pnkey)->pn_type == TOK_STRING || \
+ (pnkey)->pn_type == TOK_NAME))
+
+static JSDHashNumber
+HashFindPropValKey(JSDHashTable *table, const void *key)
+{
+ const JSParseNode *pnkey = (const JSParseNode *)key;
+
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ return (pnkey->pn_type == TOK_NUMBER)
+ ? (JSDHashNumber) (JSDOUBLE_HI32(pnkey->pn_dval) ^
+ JSDOUBLE_LO32(pnkey->pn_dval))
+ : ATOM_HASH(pnkey->pn_atom);
+}
+
+static JSBool
+MatchFindPropValEntry(JSDHashTable *table,
+ const JSDHashEntryHdr *entry,
+ const void *key)
+{
+ const FindPropValEntry *fpve = (const FindPropValEntry *)entry;
+ const JSParseNode *pnkey = (const JSParseNode *)key;
+
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ return pnkey->pn_type == fpve->pnkey->pn_type &&
+ ((pnkey->pn_type == TOK_NUMBER)
+ ? pnkey->pn_dval == fpve->pnkey->pn_dval
+ : pnkey->pn_atom == fpve->pnkey->pn_atom);
+}
+
+static const JSDHashTableOps FindPropValOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ HashFindPropValKey,
+ MatchFindPropValEntry,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+#define STEP_HASH_THRESHOLD 10
+#define BIG_DESTRUCTURING 5
+#define BIG_OBJECT_INIT 20
+
+static JSParseNode *
+FindPropertyValue(JSParseNode *pn, JSParseNode *pnid, FindPropValData *data)
+{
+ FindPropValEntry *entry;
+ JSParseNode *pnhit, *pnhead, *pnprop, *pnkey;
+ uint32 step;
+
+ /* If we have a hash table, use it as the sole source of truth. */
+ if (data->table.ops) {
+ entry = (FindPropValEntry *)
+ JS_DHashTableOperate(&data->table, pnid, JS_DHASH_LOOKUP);
+ return JS_DHASH_ENTRY_IS_BUSY(&entry->hdr) ? entry->pnval : NULL;
+ }
+
+ /* If pn is not an object initialiser node, we can't do anything here. */
+ if (pn->pn_type != TOK_RC)
+ return NULL;
+
+ /*
+ * We must search all the way through pn's list, to handle the case of an
+ * id duplicated for two or more property initialisers.
+ */
+ pnhit = NULL;
+ step = 0;
+ ASSERT_VALID_PROPERTY_KEY(pnid);
+ pnhead = pn->pn_head;
+ if (pnhead && pnhead->pn_type == TOK_DEFSHARP)
+ pnhead = pnhead->pn_next;
+ if (pnid->pn_type == TOK_NUMBER) {
+ for (pnprop = pnhead; pnprop; pnprop = pnprop->pn_next) {
+ JS_ASSERT(pnprop->pn_type == TOK_COLON);
+ if (pnprop->pn_op == JSOP_NOP) {
+ pnkey = pnprop->pn_left;
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ if (pnkey->pn_type == TOK_NUMBER &&
+ pnkey->pn_dval == pnid->pn_dval) {
+ pnhit = pnprop;
+ }
+ ++step;
+ }
+ }
+ } else {
+ for (pnprop = pnhead; pnprop; pnprop = pnprop->pn_next) {
+ JS_ASSERT(pnprop->pn_type == TOK_COLON);
+ if (pnprop->pn_op == JSOP_NOP) {
+ pnkey = pnprop->pn_left;
+ ASSERT_VALID_PROPERTY_KEY(pnkey);
+ if (pnkey->pn_type == pnid->pn_type &&
+ pnkey->pn_atom == pnid->pn_atom) {
+ pnhit = pnprop;
+ }
+ ++step;
+ }
+ }
+ }
+ if (!pnhit)
+ return NULL;
+
+ /* Hit via full search -- see whether it's time to create the hash table. */
+ JS_ASSERT(!data->table.ops);
+ if (step > data->maxstep) {
+ data->maxstep = step;
+ if (step >= STEP_HASH_THRESHOLD &&
+ data->numvars >= BIG_DESTRUCTURING &&
+ pn->pn_count >= BIG_OBJECT_INIT &&
+ JS_DHashTableInit(&data->table, &FindPropValOps, pn,
+ sizeof(FindPropValEntry),
+ JS_DHASH_DEFAULT_CAPACITY(pn->pn_count)))
+ {
+ for (pn = pnhead; pn; pn = pn->pn_next) {
+ JS_ASSERT(pnprop->pn_type == TOK_COLON);
+ ASSERT_VALID_PROPERTY_KEY(pn->pn_left);
+ entry = (FindPropValEntry *)
+ JS_DHashTableOperate(&data->table, pn->pn_left,
+ JS_DHASH_ADD);
+ entry->pnval = pn->pn_right;
+ }
+ }
+ }
+ return pnhit->pn_right;
+}
+
+/*
+ * If data is null, the caller is AssignExpr and instead of binding variables,
+ * we specialize lvalues in the propery value positions of the left-hand side.
+ * If right is null, just check for well-formed lvalues.
+ */
+static JSBool
+CheckDestructuring(JSContext *cx, BindData *data,
+ JSParseNode *left, JSParseNode *right,
+ JSTreeContext *tc)
+{
+ JSBool ok;
+ FindPropValData fpvd;
+ JSParseNode *lhs, *rhs, *pn, *pn2;
+
+ if (left->pn_type == TOK_ARRAYCOMP) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), left,
+ JSREPORT_ERROR, JSMSG_ARRAY_COMP_LEFTSIDE);
+ return JS_FALSE;
+ }
+
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (right && right->pn_arity == PN_LIST && (right->pn_extra & PNX_SHORTHAND)) {
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), right,
+ JSREPORT_ERROR, JSMSG_BAD_OBJECT_INIT);
+ return JS_FALSE;
+ }
+#endif
+
+ fpvd.table.ops = NULL;
+ lhs = left->pn_head;
+ if (lhs && lhs->pn_type == TOK_DEFSHARP) {
+ pn = lhs;
+ goto no_var_name;
+ }
+
+ if (left->pn_type == TOK_RB) {
+ rhs = (right && right->pn_type == left->pn_type)
+ ? right->pn_head
+ : NULL;
+
+ while (lhs) {
+ pn = lhs, pn2 = rhs;
+ if (!data) {
+ /* Skip parenthesization if not in a variable declaration. */
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+ if (pn2) {
+ while (pn2->pn_type == TOK_RP)
+ pn2 = pn2->pn_kid;
+ }
+ }
+
+ /* Nullary comma is an elision; binary comma is an expression.*/
+ if (pn->pn_type != TOK_COMMA || pn->pn_arity != PN_NULLARY) {
+ if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
+ ok = CheckDestructuring(cx, data, pn, pn2, tc);
+ } else {
+ if (data) {
+ if (pn->pn_type != TOK_NAME)
+ goto no_var_name;
+
+ ok = BindDestructuringVar(cx, data, pn, tc);
+ } else {
+ ok = BindDestructuringLHS(cx, pn, tc);
+ }
+ }
+ if (!ok)
+ goto out;
+ }
+
+ lhs = lhs->pn_next;
+ if (rhs)
+ rhs = rhs->pn_next;
+ }
+ } else {
+ JS_ASSERT(left->pn_type == TOK_RC);
+ fpvd.numvars = left->pn_count;
+ fpvd.maxstep = 0;
+ rhs = NULL;
+
+ while (lhs) {
+ JS_ASSERT(lhs->pn_type == TOK_COLON);
+ pn = lhs->pn_right;
+ if (!data) {
+ /* Skip parenthesization if not in a variable declaration. */
+ while (pn->pn_type == TOK_RP)
+ pn = pn->pn_kid;
+ }
+
+ if (pn->pn_type == TOK_RB || pn->pn_type == TOK_RC) {
+ if (right) {
+ rhs = FindPropertyValue(right, lhs->pn_left, &fpvd);
+ if (rhs && !data) {
+ while (rhs->pn_type == TOK_RP)
+ rhs = rhs->pn_kid;
+ }
+ }
+
+ ok = CheckDestructuring(cx, data, pn, rhs, tc);
+ } else if (data) {
+ if (pn->pn_type != TOK_NAME)
+ goto no_var_name;
+
+ ok = BindDestructuringVar(cx, data, pn, tc);
+ } else {
+ ok = BindDestructuringLHS(cx, pn, tc);
+ }
+ if (!ok)
+ goto out;
+
+ lhs = lhs->pn_next;
+ }
+ }
+
+ /*
+ * The catch/finally handler implementation in the interpreter assumes
+ * that any operation that introduces a new scope (like a "let" or "with"
+ * block) increases the stack depth. This way, it is possible to restore
+ * the scope chain based on stack depth of the handler alone. "let" with
+ * an empty destructuring pattern like in
+ *
+ * let [] = 1;
+ *
+ * would violate this assumption as the there would be no let locals to
+ * store on the stack. To satisfy it we add an empty property to such
+ * blocks so that OBJ_BLOCK_COUNT(cx, blockObj), which gives the number of
+ * slots, would be always positive.
+ *
+ * Note that we add such a property even if the block has locals due to
+ * later let declarations in it. We optimize for code simplicity here,
+ * not the fastest runtime performance with empty [] or {}.
+ */
+ if (data &&
+ data->binder == BindLet &&
+ OBJ_BLOCK_COUNT(cx, tc->blockChain) == 0) {
+ ok = js_DefineNativeProperty(cx, tc->blockChain,
+ ATOM_TO_JSID(cx->runtime->
+ atomState.emptyAtom),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE |
+ JSPROP_PERMANENT |
+ JSPROP_SHARED,
+ SPROP_HAS_SHORTID, 0, NULL);
+ if (!ok)
+ goto out;
+ }
+
+ ok = JS_TRUE;
+
+ out:
+ if (fpvd.table.ops)
+ JS_DHashTableFinish(&fpvd.table);
+ return ok;
+
+ no_var_name:
+ js_ReportCompileErrorNumber(cx, TS(tc->parseContext), pn, JSREPORT_ERROR,
+ JSMSG_NO_VARIABLE_NAME);
+ ok = JS_FALSE;
+ goto out;
+}
+
+static JSParseNode *
+DestructuringExpr(JSContext *cx, BindData *data, JSTreeContext *tc,
+ JSTokenType tt)
+{
+ JSParseNode *pn;
+
+ pn = PrimaryExpr(cx, TS(tc->parseContext), tc, tt, JS_FALSE);
+ if (!pn)
+ return NULL;
+ if (!CheckDestructuring(cx, data, pn, NULL, tc))
+ return NULL;
+ return pn;
+}
+
+// Currently used only #if JS_HAS_DESTRUCTURING, in Statement's TOK_FOR case.
+static JSParseNode *
+CloneParseTree(JSContext *cx, JSParseNode *opn, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2, *opn2;
+
+ pn = NewOrRecycledNode(cx, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = opn->pn_type;
+ pn->pn_pos = opn->pn_pos;
+ pn->pn_op = opn->pn_op;
+ pn->pn_arity = opn->pn_arity;
+
+ switch (pn->pn_arity) {
+#define NULLCHECK(e) JS_BEGIN_MACRO if (!(e)) return NULL; JS_END_MACRO
+
+ case PN_FUNC:
+ NULLCHECK(pn->pn_funpob =
+ js_NewParsedObjectBox(cx, tc->parseContext, opn->pn_funpob->object));
+ NULLCHECK(pn->pn_body = CloneParseTree(cx, opn->pn_body, tc));
+ pn->pn_flags = opn->pn_flags;
+ pn->pn_index = opn->pn_index;
+ break;
+
+ case PN_LIST:
+ PN_INIT_LIST(pn);
+ for (opn2 = opn->pn_head; opn2; opn2 = opn2->pn_next) {
+ NULLCHECK(pn2 = CloneParseTree(cx, opn2, tc));
+ PN_APPEND(pn, pn2);
+ }
+ pn->pn_extra = opn->pn_extra;
+ break;
+
+ case PN_TERNARY:
+ NULLCHECK(pn->pn_kid1 = CloneParseTree(cx, opn->pn_kid1, tc));
+ NULLCHECK(pn->pn_kid2 = CloneParseTree(cx, opn->pn_kid2, tc));
+ NULLCHECK(pn->pn_kid3 = CloneParseTree(cx, opn->pn_kid3, tc));
+ break;
+
+ case PN_BINARY:
+ NULLCHECK(pn->pn_left = CloneParseTree(cx, opn->pn_left, tc));
+ if (opn->pn_right != opn->pn_left)
+ NULLCHECK(pn->pn_right = CloneParseTree(cx, opn->pn_right, tc));
+ else
+ pn->pn_right = pn->pn_left;
+ pn->pn_val = opn->pn_val;
+ pn->pn_iflags = opn->pn_iflags;
+ break;
+
+ case PN_UNARY:
+ NULLCHECK(pn->pn_kid = CloneParseTree(cx, opn->pn_kid, tc));
+ pn->pn_num = opn->pn_num;
+ pn->pn_hidden = opn->pn_hidden;
+ break;
+
+ case PN_NAME:
+ // PN_NAME could mean several arms in pn_u, so copy the whole thing.
+ pn->pn_u = opn->pn_u;
+ if (opn->pn_expr)
+ NULLCHECK(pn->pn_expr = CloneParseTree(cx, opn->pn_expr, tc));
+ break;
+
+ case PN_NULLARY:
+ // Even PN_NULLARY may have data (apair for E4X -- what a botch).
+ pn->pn_u = opn->pn_u;
+ break;
+
+#undef NULLCHECK
+ }
+ return pn;
+}
+
+#endif /* JS_HAS_DESTRUCTURING */
+
+extern const char js_with_statement_str[];
+
+static JSParseNode *
+ContainsStmt(JSParseNode *pn, JSTokenType tt)
+{
+ JSParseNode *pn2, *pnt;
+
+ if (!pn)
+ return NULL;
+ if (pn->pn_type == tt)
+ return pn;
+ switch (pn->pn_arity) {
+ case PN_LIST:
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ pnt = ContainsStmt(pn2, tt);
+ if (pnt)
+ return pnt;
+ }
+ break;
+ case PN_TERNARY:
+ pnt = ContainsStmt(pn->pn_kid1, tt);
+ if (pnt)
+ return pnt;
+ pnt = ContainsStmt(pn->pn_kid2, tt);
+ if (pnt)
+ return pnt;
+ return ContainsStmt(pn->pn_kid3, tt);
+ case PN_BINARY:
+ /*
+ * Limit recursion if pn is a binary expression, which can't contain a
+ * var statement.
+ */
+ if (pn->pn_op != JSOP_NOP)
+ return NULL;
+ pnt = ContainsStmt(pn->pn_left, tt);
+ if (pnt)
+ return pnt;
+ return ContainsStmt(pn->pn_right, tt);
+ case PN_UNARY:
+ if (pn->pn_op != JSOP_NOP)
+ return NULL;
+ return ContainsStmt(pn->pn_kid, tt);
+ case PN_NAME:
+ return ContainsStmt(pn->pn_expr, tt);
+ default:;
+ }
+ return NULL;
+}
+
+static JSParseNode *
+ReturnOrYield(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParser operandParser)
+{
+ JSTokenType tt, tt2;
+ JSParseNode *pn, *pn2;
+
+ tt = CURRENT_TOKEN(ts).type;
+ if (tt == TOK_RETURN && !(tc->flags & TCF_IN_FUNCTION)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_RETURN_OR_YIELD, js_return_str);
+ return NULL;
+ }
+
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+
+#if JS_HAS_GENERATORS
+ if (tt == TOK_YIELD)
+ tc->flags |= TCF_FUN_IS_GENERATOR;
+#endif
+
+ /* This is ugly, but we don't want to require a semicolon. */
+ ts->flags |= TSF_OPERAND;
+ tt2 = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt2 == TOK_ERROR)
+ return NULL;
+
+ if (tt2 != TOK_EOF && tt2 != TOK_EOL && tt2 != TOK_SEMI && tt2 != TOK_RC
+#if JS_HAS_GENERATORS
+ && (tt != TOK_YIELD ||
+ (tt2 != tt && tt2 != TOK_RB && tt2 != TOK_RP &&
+ tt2 != TOK_COLON && tt2 != TOK_COMMA))
+#endif
+ ) {
+ pn2 = operandParser(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+#if JS_HAS_GENERATORS
+ if (tt == TOK_RETURN)
+#endif
+ tc->flags |= TCF_RETURN_EXPR;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_kid = pn2;
+ } else {
+#if JS_HAS_GENERATORS
+ if (tt == TOK_RETURN)
+#endif
+ tc->flags |= TCF_RETURN_VOID;
+ }
+
+ if ((~tc->flags & (TCF_RETURN_EXPR | TCF_FUN_IS_GENERATOR)) == 0) {
+ /* As in Python (see PEP-255), disallow return v; in generators. */
+ ReportBadReturn(cx, tc, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_RETURN,
+ JSMSG_BAD_ANON_GENERATOR_RETURN);
+ return NULL;
+ }
+
+ if (JS_HAS_STRICT_OPTION(cx) &&
+ (~tc->flags & (TCF_RETURN_EXPR | TCF_RETURN_VOID)) == 0 &&
+ !ReportBadReturn(cx, tc, JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_NO_RETURN_VALUE,
+ JSMSG_ANON_NO_RETURN_VALUE)) {
+ return NULL;
+ }
+
+ return pn;
+}
+
+static JSParseNode *
+PushLexicalScope(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSStmtInfo *stmtInfo)
+{
+ JSParseNode *pn;
+ JSObject *obj;
+ JSParsedObjectBox *blockpob;
+
+ pn = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn)
+ return NULL;
+
+ obj = js_NewBlockObject(cx);
+ if (!obj)
+ return NULL;
+
+ blockpob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
+ if (!blockpob)
+ return NULL;
+
+ js_PushBlockScope(tc, stmtInfo, obj, -1);
+ pn->pn_type = TOK_LEXICALSCOPE;
+ pn->pn_op = JSOP_LEAVEBLOCK;
+ pn->pn_pob = blockpob;
+ pn->pn_slot = -1;
+ return pn;
+}
+
+#if JS_HAS_BLOCK_SCOPE
+
+static JSParseNode *
+LetBlock(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc, JSBool statement)
+{
+ JSParseNode *pn, *pnblock, *pnlet;
+ JSStmtInfo stmtInfo;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LET);
+
+ /* Create the let binary node. */
+ pnlet = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pnlet)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_LET);
+
+ /* This is a let block or expression of the form: let (a, b, c) .... */
+ pnblock = PushLexicalScope(cx, ts, tc, &stmtInfo);
+ if (!pnblock)
+ return NULL;
+ pn = pnblock;
+ pn->pn_expr = pnlet;
+
+ pnlet->pn_left = Variables(cx, ts, tc);
+ if (!pnlet->pn_left)
+ return NULL;
+ pnlet->pn_left->pn_extra = PNX_POPVAR;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_LET);
+
+ ts->flags |= TSF_OPERAND;
+ if (statement && !js_MatchToken(cx, ts, TOK_LC)) {
+ /*
+ * If this is really an expression in let statement guise, then we
+ * need to wrap the TOK_LET node in a TOK_SEMI node so that we pop
+ * the return value of the expression.
+ */
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_SEMI;
+ pn->pn_num = -1;
+ pn->pn_kid = pnblock;
+
+ statement = JS_FALSE;
+ }
+ ts->flags &= ~TSF_OPERAND;
+
+ if (statement) {
+ pnlet->pn_right = Statements(cx, ts, tc);
+ if (!pnlet->pn_right)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_LET);
+ } else {
+ /*
+ * Change pnblock's opcode to the variant that propagates the last
+ * result down after popping the block, and clear statement.
+ */
+ pnblock->pn_op = JSOP_LEAVEBLOCKEXPR;
+ pnlet->pn_right = AssignExpr(cx, ts, tc);
+ if (!pnlet->pn_right)
+ return NULL;
+ }
+
+ js_PopStatement(tc);
+ return pn;
+}
+
+#endif /* JS_HAS_BLOCK_SCOPE */
+
+static JSParseNode *
+Statement(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode *pn, *pn1, *pn2, *pn3, *pn4;
+ JSStmtInfo stmtInfo, *stmt, *stmt2;
+ JSAtom *label;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_FUNCTION);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+
+ switch (tt) {
+ case TOK_FUNCTION:
+#if JS_HAS_XML_SUPPORT
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_DBLCOLON)
+ goto expression;
+#endif
+ return FunctionStmt(cx, ts, tc);
+
+ case TOK_IF:
+ /* An IF node has three kids: condition, then, and optional else. */
+ pn = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn)
+ return NULL;
+ pn1 = Condition(cx, ts, tc);
+ if (!pn1)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_IF, -1);
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ ts->flags |= TSF_OPERAND;
+ if (js_MatchToken(cx, ts, TOK_ELSE)) {
+ ts->flags &= ~TSF_OPERAND;
+ stmtInfo.type = STMT_ELSE;
+ pn3 = Statement(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+ pn->pn_pos.end = pn3->pn_pos.end;
+ } else {
+ ts->flags &= ~TSF_OPERAND;
+ pn3 = NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ }
+ js_PopStatement(tc);
+ pn->pn_kid1 = pn1;
+ pn->pn_kid2 = pn2;
+ pn->pn_kid3 = pn3;
+ return pn;
+
+ case TOK_SWITCH:
+ {
+ JSParseNode *pn5, *saveBlock;
+ JSBool seenDefault = JS_FALSE;
+
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_SWITCH);
+
+ /* pn1 points to the switch's discriminant. */
+ pn1 = ParenExpr(cx, ts, tc, NULL, NULL);
+ if (!pn1)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_SWITCH);
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_SWITCH);
+
+ /* pn2 is a list of case nodes. The default case has pn_left == NULL */
+ pn2 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn2)
+ return NULL;
+ saveBlock = tc->blockNode;
+ tc->blockNode = pn2;
+ PN_INIT_LIST(pn2);
+
+ js_PushStatement(tc, &stmtInfo, STMT_SWITCH, -1);
+
+ while ((tt = js_GetToken(cx, ts)) != TOK_RC) {
+ switch (tt) {
+ case TOK_DEFAULT:
+ if (seenDefault) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_TOO_MANY_DEFAULTS);
+ return NULL;
+ }
+ seenDefault = JS_TRUE;
+ /* FALL THROUGH */
+
+ case TOK_CASE:
+ pn3 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn3)
+ return NULL;
+ if (tt == TOK_CASE) {
+ pn3->pn_left = Expr(cx, ts, tc);
+ if (!pn3->pn_left)
+ return NULL;
+ }
+ PN_APPEND(pn2, pn3);
+ if (pn2->pn_count == JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_TOO_MANY_CASES);
+ return NULL;
+ }
+ break;
+
+ case TOK_ERROR:
+ return NULL;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_SWITCH);
+ return NULL;
+ }
+ MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_AFTER_CASE);
+
+ pn4 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn4)
+ return NULL;
+ pn4->pn_type = TOK_LC;
+ PN_INIT_LIST(pn4);
+ ts->flags |= TSF_OPERAND;
+ while ((tt = js_PeekToken(cx, ts)) != TOK_RC &&
+ tt != TOK_CASE && tt != TOK_DEFAULT) {
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_ERROR)
+ return NULL;
+ pn5 = Statement(cx, ts, tc);
+ if (!pn5)
+ return NULL;
+ pn4->pn_pos.end = pn5->pn_pos.end;
+ PN_APPEND(pn4, pn5);
+ ts->flags |= TSF_OPERAND;
+ }
+ ts->flags &= ~TSF_OPERAND;
+
+ /* Fix the PN_LIST so it doesn't begin at the TOK_COLON. */
+ if (pn4->pn_head)
+ pn4->pn_pos.begin = pn4->pn_head->pn_pos.begin;
+ pn3->pn_pos.end = pn4->pn_pos.end;
+ pn3->pn_right = pn4;
+ }
+
+ /*
+ * Handle the case where there was a let declaration in any case in
+ * the switch body, but not within an inner block. If it replaced
+ * tc->blockNode with a new block node then we must refresh pn2 and
+ * then restore tc->blockNode.
+ */
+ if (tc->blockNode != pn2)
+ pn2 = tc->blockNode;
+ tc->blockNode = saveBlock;
+ js_PopStatement(tc);
+
+ pn->pn_pos.end = pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ pn->pn_left = pn1;
+ pn->pn_right = pn2;
+ return pn;
+ }
+
+ case TOK_WHILE:
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_WHILE_LOOP, -1);
+ pn2 = Condition(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_left = pn2;
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ js_PopStatement(tc);
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_right = pn2;
+ return pn;
+
+ case TOK_DO:
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_DO_LOOP, -1);
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_left = pn2;
+ MUST_MATCH_TOKEN(TOK_WHILE, JSMSG_WHILE_AFTER_DO);
+ pn2 = Condition(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ js_PopStatement(tc);
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_right = pn2;
+ if (JSVERSION_NUMBER(cx) != JSVERSION_ECMA_3) {
+ /*
+ * All legacy and extended versions must do automatic semicolon
+ * insertion after do-while. See the testcase and discussion in
+ * http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
+ */
+ (void) js_MatchToken(cx, ts, TOK_SEMI);
+ return pn;
+ }
+ break;
+
+ case TOK_FOR:
+ {
+ JSParseNode *pnseq = NULL;
+#if JS_HAS_BLOCK_SCOPE
+ JSParseNode *pnlet = NULL;
+ JSStmtInfo blockInfo;
+#endif
+
+ /* A FOR node is binary, left is loop control and right is the body. */
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ js_PushStatement(tc, &stmtInfo, STMT_FOR_LOOP, -1);
+
+ pn->pn_op = JSOP_ITER;
+ pn->pn_iflags = 0;
+ if (js_MatchToken(cx, ts, TOK_NAME)) {
+ if (CURRENT_TOKEN(ts).t_atom == cx->runtime->atomState.eachAtom)
+ pn->pn_iflags = JSITER_FOREACH;
+ else
+ js_UngetToken(ts);
+ }
+
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_SEMI) {
+ if (pn->pn_iflags & JSITER_FOREACH)
+ goto bad_for_each;
+
+ /* No initializer -- set first kid of left sub-node to null. */
+ pn1 = NULL;
+ } else {
+ /*
+ * Set pn1 to a var list or an initializing expression.
+ *
+ * Set the TCF_IN_FOR_INIT flag during parsing of the first clause
+ * of the for statement. This flag will be used by the RelExpr
+ * production; if it is set, then the 'in' keyword will not be
+ * recognized as an operator, leaving it available to be parsed as
+ * part of a for/in loop.
+ *
+ * A side effect of this restriction is that (unparenthesized)
+ * expressions involving an 'in' operator are illegal in the init
+ * clause of an ordinary for loop.
+ */
+ tc->flags |= TCF_IN_FOR_INIT;
+ if (tt == TOK_VAR) {
+ (void) js_GetToken(cx, ts);
+ pn1 = Variables(cx, ts, tc);
+#if JS_HAS_BLOCK_SCOPE
+ } else if (tt == TOK_LET) {
+ (void) js_GetToken(cx, ts);
+ if (js_PeekToken(cx, ts) == TOK_LP) {
+ pn1 = LetBlock(cx, ts, tc, JS_FALSE);
+ tt = TOK_LEXICALSCOPE;
+ } else {
+ pnlet = PushLexicalScope(cx, ts, tc, &blockInfo);
+ if (!pnlet)
+ return NULL;
+ blockInfo.flags |= SIF_FOR_BLOCK;
+ pn1 = Variables(cx, ts, tc);
+ }
+#endif
+ } else {
+ pn1 = Expr(cx, ts, tc);
+ if (pn1) {
+ while (pn1->pn_type == TOK_RP)
+ pn1 = pn1->pn_kid;
+ }
+ }
+ tc->flags &= ~TCF_IN_FOR_INIT;
+ if (!pn1)
+ return NULL;
+ }
+
+ /*
+ * We can be sure that it's a for/in loop if there's still an 'in'
+ * keyword here, even if JavaScript recognizes 'in' as an operator,
+ * as we've excluded 'in' from being parsed in RelExpr by setting
+ * the TCF_IN_FOR_INIT flag in our JSTreeContext.
+ */
+ if (pn1 && js_MatchToken(cx, ts, TOK_IN)) {
+ pn->pn_iflags |= JSITER_ENUMERATE;
+ stmtInfo.type = STMT_FOR_IN_LOOP;
+
+ /* Check that the left side of the 'in' is valid. */
+ JS_ASSERT(!TOKEN_TYPE_IS_DECL(tt) || pn1->pn_type == tt);
+ if (TOKEN_TYPE_IS_DECL(tt)
+ ? (pn1->pn_count > 1 || pn1->pn_op == JSOP_DEFCONST
+#if JS_HAS_DESTRUCTURING
+ || (JSVERSION_NUMBER(cx) == JSVERSION_1_7 &&
+ pn->pn_op == JSOP_ITER &&
+ !(pn->pn_iflags & JSITER_FOREACH) &&
+ (pn1->pn_head->pn_type == TOK_RC ||
+ (pn1->pn_head->pn_type == TOK_RB &&
+ pn1->pn_head->pn_count != 2) ||
+ (pn1->pn_head->pn_type == TOK_ASSIGN &&
+ (pn1->pn_head->pn_left->pn_type != TOK_RB ||
+ pn1->pn_head->pn_left->pn_count != 2))))
+#endif
+ )
+ : (pn1->pn_type != TOK_NAME &&
+ pn1->pn_type != TOK_DOT &&
+#if JS_HAS_DESTRUCTURING
+ ((JSVERSION_NUMBER(cx) == JSVERSION_1_7 &&
+ pn->pn_op == JSOP_ITER &&
+ !(pn->pn_iflags & JSITER_FOREACH))
+ ? (pn1->pn_type != TOK_RB || pn1->pn_count != 2)
+ : (pn1->pn_type != TOK_RB && pn1->pn_type != TOK_RC)) &&
+#endif
+#if JS_HAS_LVALUE_RETURN
+ pn1->pn_type != TOK_LP &&
+#endif
+#if JS_HAS_XML_SUPPORT
+ (pn1->pn_type != TOK_UNARYOP ||
+ pn1->pn_op != JSOP_XMLNAME) &&
+#endif
+ pn1->pn_type != TOK_LB)) {
+ js_ReportCompileErrorNumber(cx, ts, pn1, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_LEFTSIDE);
+ return NULL;
+ }
+
+ /* pn2 points to the name or destructuring pattern on in's left. */
+ pn2 = NULL;
+
+ if (TOKEN_TYPE_IS_DECL(tt)) {
+ /* Tell js_EmitTree(TOK_VAR) that pn1 is part of a for/in. */
+ pn1->pn_extra |= PNX_FORINVAR;
+
+ /*
+ * Rewrite 'for (<decl> x = i in o)' where <decl> is 'let',
+ * 'var', or 'const' to hoist the initializer or the entire
+ * decl out of the loop head. TOK_VAR is the type for both
+ * 'var' and 'const'.
+ */
+ pn2 = pn1->pn_head;
+ if (pn2->pn_type == TOK_NAME && pn2->pn_expr
+#if JS_HAS_DESTRUCTURING
+ || pn2->pn_type == TOK_ASSIGN
+#endif
+ ) {
+ pnseq = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pnseq)
+ return NULL;
+ pnseq->pn_type = TOK_SEQ;
+ pnseq->pn_pos.begin = pn->pn_pos.begin;
+ if (tt == TOK_LET) {
+ /*
+ * Hoist just the 'i' from 'for (let x = i in o)' to
+ * before the loop, glued together via pnseq.
+ */
+ pn3 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_type = TOK_SEMI;
+ pn3->pn_op = JSOP_NOP;
+#if JS_HAS_DESTRUCTURING
+ if (pn2->pn_type == TOK_ASSIGN) {
+ pn4 = pn2->pn_right;
+ pn2 = pn1->pn_head = pn2->pn_left;
+ } else
+#endif
+ {
+ pn4 = pn2->pn_expr;
+ pn2->pn_expr = NULL;
+ }
+ pn3->pn_pos = pn4->pn_pos;
+ pn3->pn_kid = pn4;
+ PN_INIT_LIST_1(pnseq, pn3);
+ } else {
+ /*
+ * All of 'var x = i' is hoisted above 'for (x in o)',
+ * so clear PNX_FORINVAR.
+ *
+ * Request JSOP_POP here since the var is for a simple
+ * name (it is not a destructuring binding's left-hand
+ * side) and it has an initializer.
+ */
+ pn1->pn_extra &= ~PNX_FORINVAR;
+ pn1->pn_extra |= PNX_POPVAR;
+ PN_INIT_LIST_1(pnseq, pn1);
+
+#if JS_HAS_DESTRUCTURING
+ if (pn2->pn_type == TOK_ASSIGN) {
+ pn1 = CloneParseTree(cx, pn2->pn_left, tc);
+ if (!pn1)
+ return NULL;
+ } else
+#endif
+ {
+ pn1 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn1)
+ return NULL;
+ pn1->pn_type = TOK_NAME;
+ pn1->pn_op = JSOP_NAME;
+ pn1->pn_pos = pn2->pn_pos;
+ pn1->pn_atom = pn2->pn_atom;
+ pn1->pn_expr = NULL;
+ pn1->pn_slot = -1;
+ pn1->pn_const = pn2->pn_const;
+ }
+ pn2 = pn1;
+ }
+ }
+ }
+
+ if (!pn2) {
+ pn2 = pn1;
+#if JS_HAS_LVALUE_RETURN
+ if (pn2->pn_type == TOK_LP &&
+ !MakeSetCall(cx, pn2, tc, JSMSG_BAD_LEFTSIDE_OF_ASS)) {
+ return NULL;
+ }
+#endif
+#if JS_HAS_XML_SUPPORT
+ if (pn2->pn_type == TOK_UNARYOP)
+ pn2->pn_op = JSOP_BINDXMLNAME;
+#endif
+ }
+
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ /* Beware 'for (arguments in ...)' with or without a 'var'. */
+ if (pn2->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+
+#if JS_HAS_DESTRUCTURING
+ case TOK_ASSIGN:
+ pn2 = pn2->pn_left;
+ JS_ASSERT(pn2->pn_type == TOK_RB || pn2->pn_type == TOK_RC);
+ /* FALL THROUGH */
+ case TOK_RB:
+ case TOK_RC:
+ /* Check for valid lvalues in var-less destructuring for-in. */
+ if (pn1 == pn2 && !CheckDestructuring(cx, NULL, pn2, NULL, tc))
+ return NULL;
+
+ if (JSVERSION_NUMBER(cx) == JSVERSION_1_7) {
+ /*
+ * Destructuring for-in requires [key, value] enumeration
+ * in JS1.7.
+ */
+ JS_ASSERT(pn->pn_op == JSOP_ITER);
+ if (!(pn->pn_iflags & JSITER_FOREACH))
+ pn->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE;
+ }
+ break;
+#endif
+
+ default:;
+ }
+
+ /* Parse the object expression as the right operand of 'in'. */
+ pn2 = NewBinary(cx, TOK_IN, JSOP_NOP, pn1, Expr(cx, ts, tc), tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_left = pn2;
+ } else {
+ if (pn->pn_iflags & JSITER_FOREACH)
+ goto bad_for_each;
+ pn->pn_op = JSOP_NOP;
+
+ /* Parse the loop condition or null into pn2. */
+ MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_INIT);
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_SEMI) {
+ pn2 = NULL;
+ } else {
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ }
+
+ /* Parse the update expression or null into pn3. */
+ MUST_MATCH_TOKEN(TOK_SEMI, JSMSG_SEMI_AFTER_FOR_COND);
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_RP) {
+ pn3 = NULL;
+ } else {
+ pn3 = Expr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+ }
+
+ /* Build the FORHEAD node to use as the left kid of pn. */
+ pn4 = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn4)
+ return NULL;
+ pn4->pn_type = TOK_FORHEAD;
+ pn4->pn_op = JSOP_NOP;
+ pn4->pn_kid1 = pn1;
+ pn4->pn_kid2 = pn2;
+ pn4->pn_kid3 = pn3;
+ pn->pn_left = pn4;
+ }
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
+
+ /* Parse the loop body into pn->pn_right. */
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_right = pn2;
+
+ /* Record the absolute line number for source note emission. */
+ pn->pn_pos.end = pn2->pn_pos.end;
+
+#if JS_HAS_BLOCK_SCOPE
+ if (pnlet) {
+ js_PopStatement(tc);
+ pnlet->pn_expr = pn;
+ pn = pnlet;
+ }
+#endif
+ if (pnseq) {
+ pnseq->pn_pos.end = pn->pn_pos.end;
+ PN_APPEND(pnseq, pn);
+ pn = pnseq;
+ }
+ js_PopStatement(tc);
+ return pn;
+
+ bad_for_each:
+ js_ReportCompileErrorNumber(cx, ts, pn, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_EACH_LOOP);
+ return NULL;
+ }
+
+ case TOK_TRY: {
+ JSParseNode *catchList, *lastCatch;
+
+ /*
+ * try nodes are ternary.
+ * kid1 is the try Statement
+ * kid2 is the catch node list or null
+ * kid3 is the finally Statement
+ *
+ * catch nodes are ternary.
+ * kid1 is the lvalue (TOK_NAME, TOK_LB, or TOK_LC)
+ * kid2 is the catch guard or null if no guard
+ * kid3 is the catch block
+ *
+ * catch lvalue nodes are either:
+ * TOK_NAME for a single identifier
+ * TOK_RB or TOK_RC for a destructuring left-hand side
+ *
+ * finally nodes are TOK_LC Statement lists.
+ */
+ pn = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = JSOP_NOP;
+
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_TRY);
+ js_PushStatement(tc, &stmtInfo, STMT_TRY, -1);
+ pn->pn_kid1 = Statements(cx, ts, tc);
+ if (!pn->pn_kid1)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_TRY);
+ js_PopStatement(tc);
+
+ catchList = NULL;
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_CATCH) {
+ catchList = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!catchList)
+ return NULL;
+ catchList->pn_type = TOK_RESERVED;
+ PN_INIT_LIST(catchList);
+ lastCatch = NULL;
+
+ do {
+ JSParseNode *pnblock;
+ BindData data;
+
+ /* Check for another catch after unconditional catch. */
+ if (lastCatch && !lastCatch->pn_kid2) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_AFTER_GENERAL);
+ return NULL;
+ }
+
+ /*
+ * Create a lexical scope node around the whole catch clause,
+ * including the head.
+ */
+ pnblock = PushLexicalScope(cx, ts, tc, &stmtInfo);
+ if (!pnblock)
+ return NULL;
+ stmtInfo.type = STMT_CATCH;
+
+ /*
+ * Legal catch forms are:
+ * catch (lhs)
+ * catch (lhs if <boolean_expression>)
+ * where lhs is a name or a destructuring left-hand side.
+ * (the latter is legal only #ifdef JS_HAS_CATCH_GUARD)
+ */
+ pn2 = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn2)
+ return NULL;
+ pnblock->pn_expr = pn2;
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_CATCH);
+
+ /*
+ * Contrary to ECMA Ed. 3, the catch variable is lexically
+ * scoped, not a property of a new Object instance. This is
+ * an intentional change that anticipates ECMA Ed. 4.
+ */
+ data.pn = NULL;
+ data.op = JSOP_NOP;
+ data.binder = BindLet;
+ data.u.let.overflow = JSMSG_TOO_MANY_CATCH_VARS;
+
+ tt = js_GetToken(cx, ts);
+ switch (tt) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_LB:
+ case TOK_LC:
+ pn3 = DestructuringExpr(cx, &data, tc, tt);
+ if (!pn3)
+ return NULL;
+ break;
+#endif
+
+ case TOK_NAME:
+ label = CURRENT_TOKEN(ts).t_atom;
+ if (!data.binder(cx, &data, label, tc))
+ return NULL;
+
+ pn3 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_atom = label;
+ pn3->pn_slot = -1;
+ break;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_IDENTIFIER);
+ return NULL;
+ }
+
+ pn2->pn_kid1 = pn3;
+#if JS_HAS_CATCH_GUARD
+ /*
+ * We use 'catch (x if x === 5)' (not 'catch (x : x === 5)')
+ * to avoid conflicting with the JS2/ECMAv4 type annotation
+ * catchguard syntax.
+ */
+ if (js_MatchToken(cx, ts, TOK_IF)) {
+ pn2->pn_kid2 = Expr(cx, ts, tc);
+ if (!pn2->pn_kid2)
+ return NULL;
+ }
+#endif
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_CATCH);
+
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_CATCH);
+ pn2->pn_kid3 = Statements(cx, ts, tc);
+ if (!pn2->pn_kid3)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_CATCH);
+ js_PopStatement(tc);
+
+ PN_APPEND(catchList, pnblock);
+ lastCatch = pn2;
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ } while (tt == TOK_CATCH);
+ }
+ pn->pn_kid2 = catchList;
+
+ if (tt == TOK_FINALLY) {
+ MUST_MATCH_TOKEN(TOK_LC, JSMSG_CURLY_BEFORE_FINALLY);
+ js_PushStatement(tc, &stmtInfo, STMT_FINALLY, -1);
+ pn->pn_kid3 = Statements(cx, ts, tc);
+ if (!pn->pn_kid3)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_FINALLY);
+ js_PopStatement(tc);
+ } else {
+ js_UngetToken(ts);
+ }
+ if (!catchList && !pn->pn_kid3) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_OR_FINALLY);
+ return NULL;
+ }
+ return pn;
+ }
+
+ case TOK_THROW:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+
+ /* ECMA-262 Edition 3 says 'throw [no LineTerminator here] Expr'. */
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_ERROR)
+ return NULL;
+ if (tt == TOK_EOF || tt == TOK_EOL || tt == TOK_SEMI || tt == TOK_RC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_op = JSOP_THROW;
+ pn->pn_kid = pn2;
+ break;
+
+ /* TOK_CATCH and TOK_FINALLY are both handled in the TOK_TRY case */
+ case TOK_CATCH:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CATCH_WITHOUT_TRY);
+ return NULL;
+
+ case TOK_FINALLY:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_FINALLY_WITHOUT_TRY);
+ return NULL;
+
+ case TOK_BREAK:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ if (!MatchLabel(cx, ts, pn))
+ return NULL;
+ stmt = tc->topStmt;
+ label = pn->pn_atom;
+ if (label) {
+ for (; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_LABEL_NOT_FOUND);
+ return NULL;
+ }
+ if (stmt->type == STMT_LABEL && stmt->u.label == label)
+ break;
+ }
+ } else {
+ for (; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_TOUGH_BREAK);
+ return NULL;
+ }
+ if (STMT_IS_LOOP(stmt) || stmt->type == STMT_SWITCH)
+ break;
+ }
+ }
+ if (label)
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ break;
+
+ case TOK_CONTINUE:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ if (!MatchLabel(cx, ts, pn))
+ return NULL;
+ stmt = tc->topStmt;
+ label = pn->pn_atom;
+ if (label) {
+ for (stmt2 = NULL; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_LABEL_NOT_FOUND);
+ return NULL;
+ }
+ if (stmt->type == STMT_LABEL) {
+ if (stmt->u.label == label) {
+ if (!stmt2 || !STMT_IS_LOOP(stmt2)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_ERROR,
+ JSMSG_BAD_CONTINUE);
+ return NULL;
+ }
+ break;
+ }
+ } else {
+ stmt2 = stmt;
+ }
+ }
+ } else {
+ for (; ; stmt = stmt->down) {
+ if (!stmt) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_CONTINUE);
+ return NULL;
+ }
+ if (STMT_IS_LOOP(stmt))
+ break;
+ }
+ }
+ if (label)
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ break;
+
+ case TOK_WITH:
+ pn = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_BEFORE_WITH);
+ pn2 = ParenExpr(cx, ts, tc, NULL, NULL);
+ if (!pn2)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_WITH);
+ pn->pn_left = pn2;
+
+ js_PushStatement(tc, &stmtInfo, STMT_WITH, -1);
+ pn2 = Statement(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ js_PopStatement(tc);
+
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_right = pn2;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ return pn;
+
+ case TOK_VAR:
+ pn = Variables(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ /* Tell js_EmitTree to generate a final POP. */
+ pn->pn_extra |= PNX_POPVAR;
+ break;
+
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+ {
+ JSObject *obj;
+ JSParsedObjectBox *blockpob;
+
+ /* Check for a let statement or let expression. */
+ if (js_PeekToken(cx, ts) == TOK_LP) {
+ pn = LetBlock(cx, ts, tc, JS_TRUE);
+ if (!pn || pn->pn_op == JSOP_LEAVEBLOCK)
+ return pn;
+
+ /* Let expressions require automatic semicolon insertion. */
+ JS_ASSERT(pn->pn_type == TOK_SEMI ||
+ pn->pn_op == JSOP_LEAVEBLOCKEXPR);
+ break;
+ }
+
+ /*
+ * This is a let declaration. We must be directly under a block per
+ * the proposed ES4 specs, but not an implicit block created due to
+ * 'for (let ...)'. If we pass this error test, make the enclosing
+ * JSStmtInfo be our scope. Further let declarations in this block
+ * will find this scope statement and use the same block object.
+ *
+ * If we are the first let declaration in this block (i.e., when the
+ * enclosing maybe-scope JSStmtInfo isn't yet a scope statement) then
+ * we also need to set tc->blockNode to be our TOK_LEXICALSCOPE.
+ */
+ stmt = tc->topStmt;
+ if (stmt &&
+ (!STMT_MAYBE_SCOPE(stmt) || (stmt->flags & SIF_FOR_BLOCK))) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_LET_DECL_NOT_IN_BLOCK);
+ return NULL;
+ }
+
+ if (stmt && (stmt->flags & SIF_SCOPE)) {
+ JS_ASSERT(tc->blockChain == stmt->u.blockObj);
+ obj = tc->blockChain;
+ } else {
+ if (!stmt || (stmt->flags & SIF_BODY_BLOCK)) {
+ /*
+ * ES4 specifies that let at top level and at body-block scope
+ * does not shadow var, so convert back to var.
+ */
+ CURRENT_TOKEN(ts).type = TOK_VAR;
+ CURRENT_TOKEN(ts).t_op = JSOP_DEFVAR;
+
+ pn = Variables(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_extra |= PNX_POPVAR;
+ break;
+ }
+
+ /*
+ * Some obvious assertions here, but they may help clarify the
+ * situation. This stmt is not yet a scope, so it must not be a
+ * catch block (which is a lexical scope by definition).
+ */
+ JS_ASSERT(!(stmt->flags & SIF_SCOPE));
+ JS_ASSERT(stmt != tc->topScopeStmt);
+ JS_ASSERT(stmt->type == STMT_BLOCK ||
+ stmt->type == STMT_SWITCH ||
+ stmt->type == STMT_TRY ||
+ stmt->type == STMT_FINALLY);
+ JS_ASSERT(!stmt->downScope);
+
+ /* Convert the block statement into a scope statement. */
+ obj = js_NewBlockObject(cx);
+ if (!obj)
+ return NULL;
+ blockpob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
+ if (!blockpob)
+ return NULL;
+
+ /*
+ * Insert stmt on the tc->topScopeStmt/stmtInfo.downScope linked
+ * list stack, if it isn't already there. If it is there, but it
+ * lacks the SIF_SCOPE flag, it must be a try, catch, or finally
+ * block.
+ */
+ stmt->flags |= SIF_SCOPE;
+ stmt->downScope = tc->topScopeStmt;
+ tc->topScopeStmt = stmt;
+ JS_SCOPE_DEPTH_METERING(++tc->scopeDepth > tc->maxScopeDepth &&
+ (tc->maxScopeDepth = tc->scopeDepth));
+
+ STOBJ_SET_PARENT(obj, tc->blockChain);
+ tc->blockChain = obj;
+ stmt->u.blockObj = obj;
+
+#ifdef DEBUG
+ pn1 = tc->blockNode;
+ JS_ASSERT(!pn1 || pn1->pn_type != TOK_LEXICALSCOPE);
+#endif
+
+ /* Create a new lexical scope node for these statements. */
+ pn1 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn1)
+ return NULL;
+
+ pn1->pn_type = TOK_LEXICALSCOPE;
+ pn1->pn_op = JSOP_LEAVEBLOCK;
+ pn1->pn_pos = tc->blockNode->pn_pos;
+ pn1->pn_pob = blockpob;
+ pn1->pn_expr = tc->blockNode;
+ pn1->pn_slot = -1;
+ tc->blockNode = pn1;
+ }
+
+ pn = Variables(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_extra = PNX_POPVAR;
+ break;
+ }
+#endif /* JS_HAS_BLOCK_SCOPE */
+
+ case TOK_RETURN:
+ pn = ReturnOrYield(cx, ts, tc, Expr);
+ if (!pn)
+ return NULL;
+ break;
+
+ case TOK_LC:
+ {
+ uintN oldflags;
+
+ oldflags = tc->flags;
+ tc->flags = oldflags & ~TCF_HAS_FUNCTION_STMT;
+ js_PushStatement(tc, &stmtInfo, STMT_BLOCK, -1);
+ pn = Statements(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_COMPOUND);
+ js_PopStatement(tc);
+
+ /*
+ * If we contain a function statement and our container is top-level
+ * or another block, flag pn to preserve braces when decompiling.
+ */
+ if ((tc->flags & TCF_HAS_FUNCTION_STMT) &&
+ (!tc->topStmt || tc->topStmt->type == STMT_BLOCK)) {
+ pn->pn_extra |= PNX_NEEDBRACES;
+ }
+ tc->flags = oldflags | (tc->flags & (TCF_FUN_FLAGS | TCF_RETURN_FLAGS));
+ return pn;
+ }
+
+ case TOK_EOL:
+ case TOK_SEMI:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_SEMI;
+ return pn;
+
+#if JS_HAS_DEBUGGER_KEYWORD
+ case TOK_DEBUGGER:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_DEBUGGER;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+#endif /* JS_HAS_DEBUGGER_KEYWORD */
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_DEFAULT:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ if (!js_MatchToken(cx, ts, TOK_NAME) ||
+ CURRENT_TOKEN(ts).t_atom != cx->runtime->atomState.xmlAtom ||
+ !js_MatchToken(cx, ts, TOK_NAME) ||
+ CURRENT_TOKEN(ts).t_atom != cx->runtime->atomState.namespaceAtom ||
+ !js_MatchToken(cx, ts, TOK_ASSIGN) ||
+ CURRENT_TOKEN(ts).t_op != JSOP_NOP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_DEFAULT_XML_NAMESPACE);
+ return NULL;
+ }
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_op = JSOP_DEFXMLNS;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_kid = pn2;
+ tc->flags |= TCF_HAS_DEFXMLNS;
+ break;
+#endif
+
+ case TOK_ERROR:
+ return NULL;
+
+ default:
+#if JS_HAS_XML_SUPPORT
+ expression:
+#endif
+ js_UngetToken(ts);
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+
+ if (js_PeekToken(cx, ts) == TOK_COLON) {
+ if (pn2->pn_type != TOK_NAME) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_LABEL);
+ return NULL;
+ }
+ label = pn2->pn_atom;
+ for (stmt = tc->topStmt; stmt; stmt = stmt->down) {
+ if (stmt->type == STMT_LABEL && stmt->u.label == label) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_DUPLICATE_LABEL);
+ return NULL;
+ }
+ }
+ (void) js_GetToken(cx, ts);
+
+ /* Push a label struct and parse the statement. */
+ js_PushStatement(tc, &stmtInfo, STMT_LABEL, -1);
+ stmtInfo.u.label = label;
+ pn = Statement(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ /* Normalize empty statement to empty block for the decompiler. */
+ if (pn->pn_type == TOK_SEMI && !pn->pn_kid) {
+ pn->pn_type = TOK_LC;
+ pn->pn_arity = PN_LIST;
+ PN_INIT_LIST(pn);
+ }
+
+ /* Pop the label, set pn_expr, and return early. */
+ js_PopStatement(tc);
+ pn2->pn_type = TOK_COLON;
+ pn2->pn_pos.end = pn->pn_pos.end;
+ pn2->pn_expr = pn;
+ return pn2;
+ }
+
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_SEMI;
+ pn->pn_pos = pn2->pn_pos;
+ pn->pn_kid = pn2;
+ break;
+ }
+
+ /* Check termination of this primitive statement. */
+ if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_ERROR)
+ return NULL;
+ if (tt != TOK_EOF && tt != TOK_EOL && tt != TOK_SEMI && tt != TOK_RC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SEMI_BEFORE_STMNT);
+ return NULL;
+ }
+ }
+
+ (void) js_MatchToken(cx, ts, TOK_SEMI);
+ return pn;
+}
+
+static JSParseNode *
+Variables(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSBool let;
+ JSStmtInfo *scopeStmt;
+ BindData data;
+ JSParseNode *pn, *pn2;
+ JSAtom *atom;
+
+ /*
+ * The three options here are:
+ * - TOK_LET: We are parsing a let declaration.
+ * - TOK_LP: We are parsing the head of a let block.
+ * - Otherwise, we're parsing var declarations.
+ */
+ tt = CURRENT_TOKEN(ts).type;
+ let = (tt == TOK_LET || tt == TOK_LP);
+ JS_ASSERT(let || tt == TOK_VAR);
+
+ /* Make sure that Statement set the tree context up correctly. */
+ scopeStmt = tc->topScopeStmt;
+ if (let) {
+ while (scopeStmt && !(scopeStmt->flags & SIF_SCOPE)) {
+ JS_ASSERT(!STMT_MAYBE_SCOPE(scopeStmt));
+ scopeStmt = scopeStmt->downScope;
+ }
+ JS_ASSERT(scopeStmt);
+ }
+
+ data.pn = NULL;
+ data.op = let ? JSOP_NOP : CURRENT_TOKEN(ts).t_op;
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = data.op;
+ PN_INIT_LIST(pn);
+
+ /*
+ * The tricky part of this code is to create special parsenode opcodes for
+ * getting and setting variables (which will be stored as special slots in
+ * the frame). The most complicated case is an eval() inside a function.
+ * If the evaluated string references variables in the enclosing function,
+ * then we need to generate the special variable opcodes. We determine
+ * this by looking up the variable's id in the current variable object.
+ * Fortunately, we can avoid doing this for let declared variables.
+ */
+ if (let) {
+ JS_ASSERT(tc->blockChain == scopeStmt->u.blockObj);
+ data.binder = BindLet;
+ data.u.let.overflow = JSMSG_TOO_MANY_LOCALS;
+ } else {
+ data.binder = BindVarOrConst;
+ }
+
+ do {
+ tt = js_GetToken(cx, ts);
+#if JS_HAS_DESTRUCTURING
+ if (tt == TOK_LB || tt == TOK_LC) {
+ pn2 = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
+ if (!pn2)
+ return NULL;
+
+ if ((tc->flags & TCF_IN_FOR_INIT) &&
+ js_PeekToken(cx, ts) == TOK_IN) {
+ if (!CheckDestructuring(cx, &data, pn2, NULL, tc))
+ return NULL;
+ PN_APPEND(pn, pn2);
+ continue;
+ }
+
+ MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_BAD_DESTRUCT_DECL);
+ if (CURRENT_TOKEN(ts).t_op != JSOP_NOP)
+ goto bad_var_init;
+
+ pn2 = NewBinary(cx, TOK_ASSIGN, JSOP_NOP,
+ pn2, AssignExpr(cx, ts, tc),
+ tc);
+ if (!pn2 ||
+ !CheckDestructuring(cx, &data,
+ pn2->pn_left, pn2->pn_right,
+ tc)) {
+ return NULL;
+ }
+ PN_APPEND(pn, pn2);
+ continue;
+ }
+#endif
+
+ if (tt != TOK_NAME) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NO_VARIABLE_NAME);
+ return NULL;
+ }
+ atom = CURRENT_TOKEN(ts).t_atom;
+ if (!data.binder(cx, &data, atom, tc))
+ return NULL;
+
+ pn2 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_op = JSOP_NAME;
+ pn2->pn_atom = atom;
+ pn2->pn_slot = -1;
+ if (!let)
+ pn2->pn_const = (data.op == JSOP_DEFCONST);
+ PN_APPEND(pn, pn2);
+
+ if (js_MatchToken(cx, ts, TOK_ASSIGN)) {
+ if (CURRENT_TOKEN(ts).t_op != JSOP_NOP)
+ goto bad_var_init;
+
+ pn2->pn_expr = AssignExpr(cx, ts, tc);
+ if (!pn2->pn_expr)
+ return NULL;
+ pn2->pn_op = (!let && data.op == JSOP_DEFCONST)
+ ? JSOP_SETCONST
+ : JSOP_SETNAME;
+ if (!let && atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+
+ pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
+ return pn;
+
+bad_var_init:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_VAR_INIT);
+ return NULL;
+}
+
+static JSParseNode *
+Expr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+
+ pn = AssignExpr(cx, ts, tc);
+ if (pn && js_MatchToken(cx, ts, TOK_COMMA)) {
+ pn2 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ PN_INIT_LIST_1(pn2, pn);
+ pn = pn2;
+ do {
+#if JS_HAS_GENERATORS
+ pn2 = PN_LAST(pn);
+ if (pn2->pn_type == TOK_YIELD) {
+ js_ReportCompileErrorNumber(cx, ts, pn2, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_yield_str);
+ return NULL;
+ }
+#endif
+ pn2 = AssignExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ PN_APPEND(pn, pn2);
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+ pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
+ }
+ return pn;
+}
+
+static JSParseNode *
+AssignExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+ JSTokenType tt;
+ JSOp op;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+#if JS_HAS_GENERATORS
+ ts->flags |= TSF_OPERAND;
+ if (js_MatchToken(cx, ts, TOK_YIELD)) {
+ ts->flags &= ~TSF_OPERAND;
+ return ReturnOrYield(cx, ts, tc, AssignExpr);
+ }
+ ts->flags &= ~TSF_OPERAND;
+#endif
+
+ pn = CondExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ tt = js_GetToken(cx, ts);
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_ASSIGN);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+ if (tt != TOK_ASSIGN) {
+ js_UngetToken(ts);
+ return pn;
+ }
+
+ op = CURRENT_TOKEN(ts).t_op;
+ for (pn2 = pn; pn2->pn_type == TOK_RP; pn2 = pn2->pn_kid)
+ continue;
+ switch (pn2->pn_type) {
+ case TOK_NAME:
+ pn2->pn_op = JSOP_SETNAME;
+ if (pn2->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+ case TOK_DOT:
+ pn2->pn_op = JSOP_SETPROP;
+ break;
+ case TOK_LB:
+ pn2->pn_op = JSOP_SETELEM;
+ break;
+#if JS_HAS_DESTRUCTURING
+ case TOK_RB:
+ case TOK_RC:
+ if (op != JSOP_NOP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_DESTRUCT_ASS);
+ return NULL;
+ }
+ pn = AssignExpr(cx, ts, tc);
+ if (!pn || !CheckDestructuring(cx, NULL, pn2, pn, tc))
+ return NULL;
+ return NewBinary(cx, TOK_ASSIGN, op, pn2, pn, tc);
+#endif
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!MakeSetCall(cx, pn2, tc, JSMSG_BAD_LEFTSIDE_OF_ASS))
+ return NULL;
+ break;
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (pn2->pn_op == JSOP_XMLNAME) {
+ pn2->pn_op = JSOP_SETXMLNAME;
+ break;
+ }
+ /* FALL THROUGH */
+#endif
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_LEFTSIDE_OF_ASS);
+ return NULL;
+ }
+
+ return NewBinary(cx, TOK_ASSIGN, op, pn2, AssignExpr(cx, ts, tc), tc);
+}
+
+static JSParseNode *
+CondExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn1, *pn2, *pn3;
+ uintN oldflags;
+
+ pn = OrExpr(cx, ts, tc);
+ if (pn && js_MatchToken(cx, ts, TOK_HOOK)) {
+ pn1 = pn;
+ pn = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn)
+ return NULL;
+ /*
+ * Always accept the 'in' operator in the middle clause of a ternary,
+ * where it's unambiguous, even if we might be parsing the init of a
+ * for statement.
+ */
+ oldflags = tc->flags;
+ tc->flags &= ~TCF_IN_FOR_INIT;
+ pn2 = AssignExpr(cx, ts, tc);
+ tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS);
+
+ if (!pn2)
+ return NULL;
+ MUST_MATCH_TOKEN(TOK_COLON, JSMSG_COLON_IN_COND);
+ pn3 = AssignExpr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+ pn->pn_pos.begin = pn1->pn_pos.begin;
+ pn->pn_pos.end = pn3->pn_pos.end;
+ pn->pn_kid1 = pn1;
+ pn->pn_kid2 = pn2;
+ pn->pn_kid3 = pn3;
+ }
+ return pn;
+}
+
+static JSParseNode *
+OrExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = AndExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_OR))
+ pn = NewBinary(cx, TOK_OR, JSOP_OR, pn, AndExpr(cx, ts, tc), tc);
+ return pn;
+}
+
+static JSParseNode *
+AndExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BitOrExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_AND))
+ pn = NewBinary(cx, TOK_AND, JSOP_AND, pn, BitOrExpr(cx, ts, tc), tc);
+ return pn;
+}
+
+static JSParseNode *
+BitOrExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BitXorExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_BITOR)) {
+ pn = NewBinary(cx, TOK_BITOR, JSOP_BITOR, pn, BitXorExpr(cx, ts, tc),
+ tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+BitXorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BitAndExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_BITXOR)) {
+ pn = NewBinary(cx, TOK_BITXOR, JSOP_BITXOR, pn, BitAndExpr(cx, ts, tc),
+ tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+BitAndExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = EqExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_BITAND))
+ pn = NewBinary(cx, TOK_BITAND, JSOP_BITAND, pn, EqExpr(cx, ts, tc), tc);
+ return pn;
+}
+
+static JSParseNode *
+EqExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSOp op;
+
+ pn = RelExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_EQOP)) {
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, TOK_EQOP, op, pn, RelExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+RelExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSTokenType tt;
+ JSOp op;
+ uintN inForInitFlag = tc->flags & TCF_IN_FOR_INIT;
+
+ /*
+ * Uses of the in operator in ShiftExprs are always unambiguous,
+ * so unset the flag that prohibits recognizing it.
+ */
+ tc->flags &= ~TCF_IN_FOR_INIT;
+
+ pn = ShiftExpr(cx, ts, tc);
+ while (pn &&
+ (js_MatchToken(cx, ts, TOK_RELOP) ||
+ /*
+ * Recognize the 'in' token as an operator only if we're not
+ * currently in the init expr of a for loop.
+ */
+ (inForInitFlag == 0 && js_MatchToken(cx, ts, TOK_IN)) ||
+ js_MatchToken(cx, ts, TOK_INSTANCEOF))) {
+ tt = CURRENT_TOKEN(ts).type;
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, tt, op, pn, ShiftExpr(cx, ts, tc), tc);
+ }
+ /* Restore previous state of inForInit flag. */
+ tc->flags |= inForInitFlag;
+
+ return pn;
+}
+
+static JSParseNode *
+ShiftExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSOp op;
+
+ pn = AddExpr(cx, ts, tc);
+ while (pn && js_MatchToken(cx, ts, TOK_SHOP)) {
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, TOK_SHOP, op, pn, AddExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+AddExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSTokenType tt;
+ JSOp op;
+
+ pn = MulExpr(cx, ts, tc);
+ while (pn &&
+ (js_MatchToken(cx, ts, TOK_PLUS) ||
+ js_MatchToken(cx, ts, TOK_MINUS))) {
+ tt = CURRENT_TOKEN(ts).type;
+ op = (tt == TOK_PLUS) ? JSOP_ADD : JSOP_SUB;
+ pn = NewBinary(cx, tt, op, pn, MulExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+MulExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSTokenType tt;
+ JSOp op;
+
+ pn = UnaryExpr(cx, ts, tc);
+ while (pn &&
+ (js_MatchToken(cx, ts, TOK_STAR) ||
+ js_MatchToken(cx, ts, TOK_DIVOP))) {
+ tt = CURRENT_TOKEN(ts).type;
+ op = CURRENT_TOKEN(ts).t_op;
+ pn = NewBinary(cx, tt, op, pn, UnaryExpr(cx, ts, tc), tc);
+ }
+ return pn;
+}
+
+static JSParseNode *
+SetLvalKid(JSContext *cx, JSTokenStream *ts, JSParseNode *pn, JSParseNode *kid,
+ const char *name)
+{
+ while (kid->pn_type == TOK_RP)
+ kid = kid->pn_kid;
+ if (kid->pn_type != TOK_NAME &&
+ kid->pn_type != TOK_DOT &&
+#if JS_HAS_LVALUE_RETURN
+ (kid->pn_type != TOK_LP ||
+ (kid->pn_op != JSOP_CALL && kid->pn_op != JSOP_EVAL && kid->pn_op != JSOP_APPLY)) &&
+#endif
+#if JS_HAS_XML_SUPPORT
+ (kid->pn_type != TOK_UNARYOP || kid->pn_op != JSOP_XMLNAME) &&
+#endif
+ kid->pn_type != TOK_LB) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_OPERAND, name);
+ return NULL;
+ }
+ pn->pn_kid = kid;
+ return kid;
+}
+
+static const char incop_name_str[][10] = {"increment", "decrement"};
+
+static JSBool
+SetIncOpKid(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *pn, JSParseNode *kid,
+ JSTokenType tt, JSBool preorder)
+{
+ JSOp op;
+
+ kid = SetLvalKid(cx, ts, pn, kid, incop_name_str[tt == TOK_DEC]);
+ if (!kid)
+ return JS_FALSE;
+ switch (kid->pn_type) {
+ case TOK_NAME:
+ op = (tt == TOK_INC)
+ ? (preorder ? JSOP_INCNAME : JSOP_NAMEINC)
+ : (preorder ? JSOP_DECNAME : JSOP_NAMEDEC);
+ if (kid->pn_atom == cx->runtime->atomState.argumentsAtom)
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ break;
+
+ case TOK_DOT:
+ op = (tt == TOK_INC)
+ ? (preorder ? JSOP_INCPROP : JSOP_PROPINC)
+ : (preorder ? JSOP_DECPROP : JSOP_PROPDEC);
+ break;
+
+#if JS_HAS_LVALUE_RETURN
+ case TOK_LP:
+ if (!MakeSetCall(cx, kid, tc, JSMSG_BAD_INCOP_OPERAND))
+ return JS_FALSE;
+ /* FALL THROUGH */
+#endif
+#if JS_HAS_XML_SUPPORT
+ case TOK_UNARYOP:
+ if (kid->pn_op == JSOP_XMLNAME)
+ kid->pn_op = JSOP_SETXMLNAME;
+ /* FALL THROUGH */
+#endif
+ case TOK_LB:
+ op = (tt == TOK_INC)
+ ? (preorder ? JSOP_INCELEM : JSOP_ELEMINC)
+ : (preorder ? JSOP_DECELEM : JSOP_ELEMDEC);
+ break;
+
+ default:
+ JS_ASSERT(0);
+ op = JSOP_NOP;
+ }
+ pn->pn_op = op;
+ return JS_TRUE;
+}
+
+static JSParseNode *
+UnaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode *pn, *pn2;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+
+ switch (tt) {
+ case TOK_UNARYOP:
+ case TOK_PLUS:
+ case TOK_MINUS:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_UNARYOP; /* PLUS and MINUS are binary */
+ pn->pn_op = CURRENT_TOKEN(ts).t_op;
+ pn2 = UnaryExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ pn->pn_kid = pn2;
+ break;
+
+ case TOK_INC:
+ case TOK_DEC:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn2 = MemberExpr(cx, ts, tc, JS_TRUE);
+ if (!pn2)
+ return NULL;
+ if (!SetIncOpKid(cx, ts, tc, pn, pn2, tt, JS_TRUE))
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ break;
+
+ case TOK_DELETE:
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn2 = UnaryExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+
+ /*
+ * Under ECMA3, deleting any unary expression is valid -- it simply
+ * returns true. Here we strip off any parentheses and fold constants
+ * before checking for a call expression, in order to rule out delete
+ * of a generator expression.
+ */
+ while (pn2->pn_type == TOK_RP)
+ pn2 = pn2->pn_kid;
+ if (!js_FoldConstants(cx, pn2, tc))
+ return NULL;
+ if (pn2->pn_type == TOK_LP &&
+ pn2->pn_op != JSOP_SETCALL &&
+ !MakeSetCall(cx, pn2, tc, JSMSG_BAD_DELETE_OPERAND)) {
+ return NULL;
+ }
+ pn->pn_kid = pn2;
+ break;
+
+ case TOK_ERROR:
+ return NULL;
+
+ default:
+ js_UngetToken(ts);
+ pn = MemberExpr(cx, ts, tc, JS_TRUE);
+ if (!pn)
+ return NULL;
+
+ /* Don't look across a newline boundary for a postfix incop. */
+ if (ON_CURRENT_LINE(ts, pn->pn_pos)) {
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekTokenSameLine(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_INC || tt == TOK_DEC) {
+ (void) js_GetToken(cx, ts);
+ pn2 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn2)
+ return NULL;
+ if (!SetIncOpKid(cx, ts, tc, pn2, pn, tt, JS_FALSE))
+ return NULL;
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn = pn2;
+ }
+ }
+ break;
+ }
+ return pn;
+}
+
+#if JS_HAS_GENERATORS
+
+/*
+ * Starting from a |for| keyword after the first array initialiser element or
+ * an expression in an open parenthesis, parse the tail of the comprehension
+ * or generator expression signified by this |for| keyword in context.
+ *
+ * Return null on failure, else return the top-most parse node for the array
+ * comprehension or generator expression, with a unary node as the body of the
+ * (possibly nested) for-loop, initialized by |type, op, kid|.
+ */
+static JSParseNode *
+ComprehensionTail(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType type, JSOp op, JSParseNode *kid)
+{
+ JSParseNode *pn, *pn2, *pn3, **pnp;
+ JSStmtInfo stmtInfo;
+ BindData data;
+ JSRuntime *rt;
+ JSTokenType tt;
+ JSAtom *atom;
+
+ JS_ASSERT(type == TOK_SEMI || type == TOK_ARRAYPUSH);
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_FOR);
+
+ /*
+ * Make a parse-node and literal object representing the block scope of
+ * this array comprehension or generator expression.
+ */
+ pn = PushLexicalScope(cx, ts, tc, &stmtInfo);
+ if (!pn)
+ return NULL;
+ pnp = &pn->pn_expr;
+
+ data.pn = NULL;
+ data.op = JSOP_NOP;
+ data.binder = BindLet;
+ data.u.let.overflow = JSMSG_ARRAY_INIT_TOO_BIG;
+
+ rt = cx->runtime;
+ do {
+ /*
+ * FOR node is binary, left is loop control and right is body. Use
+ * index to count each block-local let-variable on the left-hand side
+ * of the IN.
+ */
+ pn2 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn2)
+ return NULL;
+
+ pn2->pn_op = JSOP_ITER;
+ pn2->pn_iflags = JSITER_ENUMERATE;
+ if (js_MatchToken(cx, ts, TOK_NAME)) {
+ if (CURRENT_TOKEN(ts).t_atom == rt->atomState.eachAtom)
+ pn2->pn_iflags |= JSITER_FOREACH;
+ else
+ js_UngetToken(ts);
+ }
+ MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
+
+ tt = js_GetToken(cx, ts);
+ switch (tt) {
+#if JS_HAS_DESTRUCTURING
+ case TOK_LB:
+ case TOK_LC:
+ pn3 = DestructuringExpr(cx, &data, tc, tt);
+ if (!pn3)
+ return NULL;
+
+ if (pn3->pn_type != TOK_RB || pn3->pn_count != 2) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_FOR_LEFTSIDE);
+ return NULL;
+ }
+
+ if (JSVERSION_NUMBER(cx) == JSVERSION_1_7) {
+ /* Destructuring requires [key, value] enumeration in JS1.7. */
+ JS_ASSERT(pn2->pn_op == JSOP_ITER);
+ JS_ASSERT(pn2->pn_iflags & JSITER_ENUMERATE);
+ if (!(pn2->pn_iflags & JSITER_FOREACH))
+ pn2->pn_iflags |= JSITER_FOREACH | JSITER_KEYVALUE;
+ }
+ break;
+#endif
+
+ case TOK_NAME:
+ atom = CURRENT_TOKEN(ts).t_atom;
+ if (!data.binder(cx, &data, atom, tc))
+ return NULL;
+
+ /*
+ * Create a name node with pn_op JSOP_NAME. We can't set pn_op to
+ * JSOP_GETLOCAL here, because we don't yet know the block's depth
+ * in the operand stack frame. The code generator computes that,
+ * and it tries to bind all names to slots, so we must let it do
+ * the deed.
+ */
+ pn3 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_op = JSOP_NAME;
+ pn3->pn_atom = atom;
+ pn3->pn_slot = -1;
+ break;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NO_VARIABLE_NAME);
+
+ case TOK_ERROR:
+ return NULL;
+ }
+
+ MUST_MATCH_TOKEN(TOK_IN, JSMSG_IN_AFTER_FOR_NAME);
+ pn3 = NewBinary(cx, TOK_IN, JSOP_NOP, pn3,
+ Expr(cx, ts, tc), tc);
+ if (!pn3)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_AFTER_FOR_CTRL);
+ pn2->pn_left = pn3;
+ *pnp = pn2;
+ pnp = &pn2->pn_right;
+ } while (js_MatchToken(cx, ts, TOK_FOR));
+
+ if (js_MatchToken(cx, ts, TOK_IF)) {
+ pn2 = NewParseNode(cx, ts, PN_TERNARY, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_kid1 = Condition(cx, ts, tc);
+ if (!pn2->pn_kid1)
+ return NULL;
+ *pnp = pn2;
+ pnp = &pn2->pn_kid2;
+ }
+
+ pn2 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_type = type;
+ pn2->pn_op = op;
+ pn2->pn_kid = kid;
+ *pnp = pn2;
+
+ js_PopStatement(tc);
+ return pn;
+}
+
+#if JS_HAS_GENERATOR_EXPRS
+
+/*
+ * Starting from a |for| keyword after an expression, parse the comprehension
+ * tail completing this generator expression. Wrap the expression at kid in a
+ * generator function that is immediately called to evaluate to the generator
+ * iterator that is the value of this generator expression.
+ *
+ * Callers pass a blank unary node via pn, which GeneratorExpr fills in as the
+ * yield expression, which ComprehensionTail in turn wraps in a TOK_SEMI-type
+ * expression-statement node that constitutes the body of the |for| loop(s) in
+ * the generator function.
+ *
+ * Note how unlike Python, we do not evaluate the expression to the right of
+ * the first |in| in the chain of |for| heads. Instead, a generator expression
+ * is merely sugar for a generator function expression and its application.
+ */
+static JSParseNode *
+GeneratorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ uintN oldflags, JSParseNode *pn, JSParseNode *kid)
+{
+ JSParseNode *body, *lambda;
+ JSFunction *fun;
+
+ /* Initialize pn, connecting it to kid. */
+ JS_ASSERT(pn->pn_arity == PN_UNARY);
+ pn->pn_type = TOK_YIELD;
+ pn->pn_op = JSOP_YIELD;
+ pn->pn_pos = kid->pn_pos;
+ pn->pn_kid = kid;
+ pn->pn_hidden = JS_TRUE;
+
+ /*
+ * Parse the comprehension tail at hand, making pn the kid of the loop
+ * body's expression statement.
+ */
+ body = ComprehensionTail(cx, ts, tc, TOK_SEMI, JSOP_NOP, pn);
+ if (!body)
+ return NULL;
+ body->pn_pos.begin = kid->pn_pos.begin;
+
+ /*
+ * Make the generator function and flag it as interpreted ASAP (see the
+ * comment in FunctionBody).
+ */
+ fun = NewCompilerFunction(cx, tc, NULL, JSFUN_LAMBDA);
+ if (!fun)
+ return NULL;
+
+ /*
+ * This generator function is referenced by an anonymous function object
+ * node. Here is where we must take care to propagate certain tc->flags
+ * that may have changed from oldflags to reflect crucial facts about the
+ * expression on the left of |for| and in the comprehension tail after it.
+ */
+ lambda = NewParseNode(cx, ts, PN_FUNC, tc);
+ if (!lambda)
+ return NULL;
+ lambda->pn_type = TOK_FUNCTION;
+ lambda->pn_op = JSOP_ANONFUNOBJ;
+ lambda->pn_pos.begin = body->pn_pos.begin;
+ lambda->pn_funpob = js_NewParsedObjectBox(cx, tc->parseContext,
+ FUN_OBJECT(fun));
+ if (!lambda->pn_funpob)
+ return NULL;
+ lambda->pn_body = body;
+ lambda->pn_flags = TCF_FUN_IS_GENERATOR | TCF_GENEXP_LAMBDA |
+ ((oldflags ^ tc->flags) & TCF_FUN_FLAGS);
+
+ /*
+ * Re-use pn to name the result node, a call expression invoking the
+ * anonymous generator function object.
+ */
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_LP;
+ pn->pn_op = JSOP_CALL;
+ pn->pn_pos.begin = lambda->pn_pos.begin;
+ PN_INIT_LIST_1(pn, lambda);
+
+ body->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ tc->flags = oldflags;
+ return pn;
+}
+
+static const char js_generator_str[] = "generator";
+
+#endif /* JS_HAS_GENERATOR_EXPRS */
+#endif /* JS_HAS_GENERATORS */
+
+static JSBool
+ArgumentList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *listNode)
+{
+ JSBool matched;
+
+ ts->flags |= TSF_OPERAND;
+ matched = js_MatchToken(cx, ts, TOK_RP);
+ ts->flags &= ~TSF_OPERAND;
+ if (!matched) {
+ do {
+#if JS_HAS_GENERATOR_EXPRS
+ uintN oldflags = tc->flags;
+#endif
+ JSParseNode *argNode = AssignExpr(cx, ts, tc);
+ if (!argNode)
+ return JS_FALSE;
+#if JS_HAS_GENERATORS
+ if (argNode->pn_type == TOK_YIELD &&
+ js_PeekToken(cx, ts) == TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, argNode, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_yield_str);
+ return JS_FALSE;
+ }
+#endif
+#if JS_HAS_GENERATOR_EXPRS
+ if (js_MatchToken(cx, ts, TOK_FOR)) {
+ JSParseNode *pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return JS_FALSE;
+ argNode = GeneratorExpr(cx, ts, tc, oldflags, pn, argNode);
+ if (!argNode)
+ return JS_FALSE;
+ if (listNode->pn_count > 1 ||
+ js_PeekToken(cx, ts) == TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, argNode, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_generator_str);
+ return JS_FALSE;
+ }
+ }
+#endif
+ PN_APPEND(listNode, argNode);
+ } while (js_MatchToken(cx, ts, TOK_COMMA));
+
+ if (js_GetToken(cx, ts) != TOK_RP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_PAREN_AFTER_ARGS);
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSParseNode *
+MemberExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowCallSyntax)
+{
+ JSParseNode *pn, *pn2, *pn3;
+ JSTokenType tt;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ /* Check for new expression first. */
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_NEW) {
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn2 = MemberExpr(cx, ts, tc, JS_FALSE);
+ if (!pn2)
+ return NULL;
+ pn->pn_op = JSOP_NEW;
+ PN_INIT_LIST_1(pn, pn2);
+ pn->pn_pos.begin = pn2->pn_pos.begin;
+
+ if (js_MatchToken(cx, ts, TOK_LP) && !ArgumentList(cx, ts, tc, pn))
+ return NULL;
+ if (pn->pn_count > ARGC_LIMIT) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_CON_ARGS);
+ return NULL;
+ }
+ pn->pn_pos.end = PN_LAST(pn)->pn_pos.end;
+ } else {
+ pn = PrimaryExpr(cx, ts, tc, tt, JS_FALSE);
+ if (!pn)
+ return NULL;
+
+ if (pn->pn_type == TOK_ANYNAME ||
+ pn->pn_type == TOK_AT ||
+ pn->pn_type == TOK_DBLCOLON) {
+ pn2 = NewOrRecycledNode(cx, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_type = TOK_UNARYOP;
+ pn2->pn_pos = pn->pn_pos;
+ pn2->pn_op = JSOP_XMLNAME;
+ pn2->pn_arity = PN_UNARY;
+ pn2->pn_kid = pn;
+ pn = pn2;
+ }
+ }
+
+ while ((tt = js_GetToken(cx, ts)) > TOK_EOF) {
+ if (tt == TOK_DOT) {
+ pn2 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_slot = -1;
+#if JS_HAS_XML_SUPPORT
+ ts->flags |= TSF_OPERAND | TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
+ pn3 = PrimaryExpr(cx, ts, tc, tt, JS_TRUE);
+ if (!pn3)
+ return NULL;
+ tt = PN_TYPE(pn3);
+ if (tt == TOK_NAME) {
+ pn2->pn_op = JSOP_GETPROP;
+ pn2->pn_expr = pn;
+ pn2->pn_atom = pn3->pn_atom;
+ RecycleTree(pn3, tc);
+ } else {
+ if (TOKEN_TYPE_IS_XML(tt)) {
+ pn2->pn_type = TOK_LB;
+ pn2->pn_op = JSOP_GETELEM;
+ } else if (tt == TOK_RP) {
+ JSParseNode *group = pn3;
+
+ /* Recycle the useless TOK_RP node. */
+ pn3 = group->pn_kid;
+ group->pn_kid = NULL;
+ RecycleTree(group, tc);
+ pn2->pn_type = TOK_FILTER;
+ pn2->pn_op = JSOP_FILTER;
+
+ /* A filtering predicate is like a with statement. */
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NAME_AFTER_DOT);
+ return NULL;
+ }
+ pn2->pn_arity = PN_BINARY;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ }
+#else
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ MUST_MATCH_TOKEN(TOK_NAME, JSMSG_NAME_AFTER_DOT);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ pn2->pn_op = JSOP_GETPROP;
+ pn2->pn_expr = pn;
+ pn2->pn_atom = CURRENT_TOKEN(ts).t_atom;
+#endif
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+#if JS_HAS_XML_SUPPORT
+ } else if (tt == TOK_DBLDOT) {
+ pn2 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn2)
+ return NULL;
+ ts->flags |= TSF_OPERAND | TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~(TSF_OPERAND | TSF_KEYWORD_IS_NAME);
+ pn3 = PrimaryExpr(cx, ts, tc, tt, JS_TRUE);
+ if (!pn3)
+ return NULL;
+ tt = PN_TYPE(pn3);
+ if (tt == TOK_NAME) {
+ pn3->pn_type = TOK_STRING;
+ pn3->pn_arity = PN_NULLARY;
+ pn3->pn_op = JSOP_QNAMEPART;
+ } else if (!TOKEN_TYPE_IS_XML(tt)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_NAME_AFTER_DOT);
+ return NULL;
+ }
+ pn2->pn_op = JSOP_DESCENDANTS;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+#endif
+ } else if (tt == TOK_LB) {
+ pn2 = NewParseNode(cx, ts, PN_BINARY, tc);
+ if (!pn2)
+ return NULL;
+ pn3 = Expr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_IN_INDEX);
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+
+ /*
+ * Optimize o['p'] to o.p by rewriting pn2, but avoid rewriting
+ * o['0'] to use JSOP_GETPROP, to keep fast indexing disjoint in
+ * the interpreter from fast property access. However, if the
+ * bracketed string is a uint32, we rewrite pn3 to be a number
+ * instead of a string.
+ */
+ do {
+ if (pn3->pn_type == TOK_STRING) {
+ jsuint index;
+
+ if (!js_IdIsIndex(ATOM_TO_JSID(pn3->pn_atom), &index)) {
+ pn2->pn_type = TOK_DOT;
+ pn2->pn_op = JSOP_GETPROP;
+ pn2->pn_arity = PN_NAME;
+ pn2->pn_expr = pn;
+ pn2->pn_atom = pn3->pn_atom;
+ break;
+ }
+ pn3->pn_type = TOK_NUMBER;
+ pn3->pn_op = JSOP_DOUBLE;
+ pn3->pn_dval = index;
+ }
+ pn2->pn_op = JSOP_GETELEM;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ } while (0);
+ } else if (allowCallSyntax && tt == TOK_LP) {
+ pn2 = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn2)
+ return NULL;
+
+ pn2->pn_op = JSOP_CALL;
+ if (pn->pn_op == JSOP_NAME &&
+ pn->pn_atom == cx->runtime->atomState.evalAtom) {
+ /* Pick JSOP_EVAL and flag tc as heavyweight if eval(...). */
+ pn2->pn_op = JSOP_EVAL;
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ } else if (pn->pn_op == JSOP_GETPROP &&
+ (pn->pn_atom == cx->runtime->atomState.applyAtom ||
+ pn->pn_atom == cx->runtime->atomState.callAtom)) {
+ /* Pick JSOP_APPLY if apply(...). */
+ pn2->pn_op = JSOP_APPLY;
+ }
+
+ PN_INIT_LIST_1(pn2, pn);
+ pn2->pn_pos.begin = pn->pn_pos.begin;
+
+ if (!ArgumentList(cx, ts, tc, pn2))
+ return NULL;
+ if (pn2->pn_count > ARGC_LIMIT) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_TOO_MANY_FUN_ARGS);
+ return NULL;
+ }
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ } else {
+ js_UngetToken(ts);
+ return pn;
+ }
+
+ pn = pn2;
+ }
+ if (tt == TOK_ERROR)
+ return NULL;
+ return pn;
+}
+
+static JSParseNode *
+BracketedExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ uintN oldflags;
+ JSParseNode *pn;
+
+ /*
+ * Always accept the 'in' operator in a parenthesized expression,
+ * where it's unambiguous, even if we might be parsing the init of a
+ * for statement.
+ */
+ oldflags = tc->flags;
+ tc->flags &= ~TCF_IN_FOR_INIT;
+ pn = Expr(cx, ts, tc);
+ tc->flags = oldflags | (tc->flags & TCF_FUN_FLAGS);
+ return pn;
+}
+
+#if JS_HAS_XML_SUPPORT
+
+static JSParseNode *
+EndBracketedExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = BracketedExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_ATTR_EXPR);
+ return pn;
+}
+
+/*
+ * From the ECMA-357 grammar in 11.1.1 and 11.1.2:
+ *
+ * AttributeIdentifier:
+ * @ PropertySelector
+ * @ QualifiedIdentifier
+ * @ [ Expression ]
+ *
+ * PropertySelector:
+ * Identifier
+ * *
+ *
+ * QualifiedIdentifier:
+ * PropertySelector :: PropertySelector
+ * PropertySelector :: [ Expression ]
+ *
+ * We adapt AttributeIdentifier and QualifiedIdentier to be LL(1), like so:
+ *
+ * AttributeIdentifier:
+ * @ QualifiedIdentifier
+ * @ [ Expression ]
+ *
+ * PropertySelector:
+ * Identifier
+ * *
+ *
+ * QualifiedIdentifier:
+ * PropertySelector :: PropertySelector
+ * PropertySelector :: [ Expression ]
+ * PropertySelector
+ *
+ * As PrimaryExpression: Identifier is in ECMA-262 and we want the semantics
+ * for that rule to result in a name node, but ECMA-357 extends the grammar
+ * to include PrimaryExpression: QualifiedIdentifier, we must factor further:
+ *
+ * QualifiedIdentifier:
+ * PropertySelector QualifiedSuffix
+ *
+ * QualifiedSuffix:
+ * :: PropertySelector
+ * :: [ Expression ]
+ * /nothing/
+ *
+ * And use this production instead of PrimaryExpression: QualifiedIdentifier:
+ *
+ * PrimaryExpression:
+ * Identifier QualifiedSuffix
+ *
+ * We hoist the :: match into callers of QualifiedSuffix, in order to tweak
+ * PropertySelector vs. Identifier pn_arity, pn_op, and other members.
+ */
+static JSParseNode *
+PropertySelector(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ if (pn->pn_type == TOK_STAR) {
+ pn->pn_type = TOK_ANYNAME;
+ pn->pn_op = JSOP_ANYNAME;
+ pn->pn_atom = cx->runtime->atomState.starAtom;
+ } else {
+ JS_ASSERT(pn->pn_type == TOK_NAME);
+ pn->pn_op = JSOP_QNAMEPART;
+ pn->pn_arity = PN_NAME;
+ pn->pn_atom = CURRENT_TOKEN(ts).t_atom;
+ pn->pn_slot = -1;
+ }
+ return pn;
+}
+
+static JSParseNode *
+QualifiedSuffix(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ JSTreeContext *tc)
+{
+ JSParseNode *pn2, *pn3;
+ JSTokenType tt;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_DBLCOLON);
+ pn2 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn2)
+ return NULL;
+
+ /* Left operand of :: must be evaluated if it is an identifier. */
+ if (pn->pn_op == JSOP_QNAMEPART)
+ pn->pn_op = JSOP_NAME;
+
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_STAR || tt == TOK_NAME) {
+ /* Inline and specialize PropertySelector for JSOP_QNAMECONST. */
+ pn2->pn_op = JSOP_QNAMECONST;
+ pn2->pn_atom = (tt == TOK_STAR)
+ ? cx->runtime->atomState.starAtom
+ : CURRENT_TOKEN(ts).t_atom;
+ pn2->pn_expr = pn;
+ pn2->pn_slot = -1;
+ return pn2;
+ }
+
+ if (tt != TOK_LB) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ pn3 = EndBracketedExpr(cx, ts, tc);
+ if (!pn3)
+ return NULL;
+
+ pn2->pn_op = JSOP_QNAME;
+ pn2->pn_arity = PN_BINARY;
+ pn2->pn_left = pn;
+ pn2->pn_right = pn3;
+ return pn2;
+}
+
+static JSParseNode *
+QualifiedIdentifier(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+
+ pn = PropertySelector(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ if (js_MatchToken(cx, ts, TOK_DBLCOLON))
+ pn = QualifiedSuffix(cx, ts, pn, tc);
+ return pn;
+}
+
+static JSParseNode *
+AttributeIdentifier(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+ JSTokenType tt;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_AT);
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = JSOP_TOATTRNAME;
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt == TOK_STAR || tt == TOK_NAME) {
+ pn2 = QualifiedIdentifier(cx, ts, tc);
+ } else if (tt == TOK_LB) {
+ pn2 = EndBracketedExpr(cx, ts, tc);
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ if (!pn2)
+ return NULL;
+ pn->pn_kid = pn2;
+ return pn;
+}
+
+/*
+ * Make a TOK_LC unary node whose pn_kid is an expression.
+ */
+static JSParseNode *
+XMLExpr(JSContext *cx, JSTokenStream *ts, JSBool inTag, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2;
+ uintN oldflags;
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LC);
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+
+ /*
+ * Turn off XML tag mode, but don't restore it after parsing this braced
+ * expression. Instead, simply restore ts's old flags. This is required
+ * because XMLExpr is called both from within a tag, and from within text
+ * contained in an element, but outside of any start, end, or point tag.
+ */
+ oldflags = ts->flags;
+ ts->flags = oldflags & ~TSF_XMLTAGMODE;
+ pn2 = Expr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_IN_XML_EXPR);
+ ts->flags = oldflags;
+ pn->pn_kid = pn2;
+ pn->pn_op = inTag ? JSOP_XMLTAGEXPR : JSOP_XMLELTEXPR;
+ return pn;
+}
+
+/*
+ * Make a terminal node for one of TOK_XMLNAME, TOK_XMLATTR, TOK_XMLSPACE,
+ * TOK_XMLTEXT, TOK_XMLCDATA, TOK_XMLCOMMENT, or TOK_XMLPI. When converting
+ * parse tree to XML, we preserve a TOK_XMLSPACE node only if it's the sole
+ * child of a container tag.
+ */
+static JSParseNode *
+XMLAtomNode(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn;
+ JSToken *tp;
+
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ tp = &CURRENT_TOKEN(ts);
+ pn->pn_op = tp->t_op;
+ pn->pn_atom = tp->t_atom;
+ if (tp->type == TOK_XMLPI)
+ pn->pn_atom2 = tp->t_atom2;
+ return pn;
+}
+
+/*
+ * Parse the productions:
+ *
+ * XMLNameExpr:
+ * XMLName XMLNameExpr?
+ * { Expr } XMLNameExpr?
+ *
+ * Return a PN_LIST, PN_UNARY, or PN_NULLARY according as XMLNameExpr produces
+ * a list of names and/or expressions, a single expression, or a single name.
+ * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME; if PN_UNARY, pn_type
+ * will be TOK_LC.
+ */
+static JSParseNode *
+XMLNameExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
+{
+ JSParseNode *pn, *pn2, *list;
+ JSTokenType tt;
+
+ pn = list = NULL;
+ do {
+ tt = CURRENT_TOKEN(ts).type;
+ if (tt == TOK_LC) {
+ pn2 = XMLExpr(cx, ts, JS_TRUE, tc);
+ if (!pn2)
+ return NULL;
+ } else {
+ JS_ASSERT(tt == TOK_XMLNAME);
+ pn2 = XMLAtomNode(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ }
+
+ if (!pn) {
+ pn = pn2;
+ } else {
+ if (!list) {
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = TOK_XMLNAME;
+ list->pn_pos.begin = pn->pn_pos.begin;
+ PN_INIT_LIST_1(list, pn);
+ list->pn_extra = PNX_CANTFOLD;
+ pn = list;
+ }
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+ } while ((tt = js_GetToken(cx, ts)) == TOK_XMLNAME || tt == TOK_LC);
+
+ js_UngetToken(ts);
+ return pn;
+}
+
+/*
+ * Macro to test whether an XMLNameExpr or XMLTagContent node can be folded
+ * at compile time into a JSXML tree.
+ */
+#define XML_FOLDABLE(pn) ((pn)->pn_arity == PN_LIST \
+ ? ((pn)->pn_extra & PNX_CANTFOLD) == 0 \
+ : (pn)->pn_type != TOK_LC)
+
+/*
+ * Parse the productions:
+ *
+ * XMLTagContent:
+ * XMLNameExpr
+ * XMLTagContent S XMLNameExpr S? = S? XMLAttr
+ * XMLTagContent S XMLNameExpr S? = S? { Expr }
+ *
+ * Return a PN_LIST, PN_UNARY, or PN_NULLARY according to how XMLTagContent
+ * produces a list of name and attribute values and/or braced expressions, a
+ * single expression, or a single name.
+ *
+ * If PN_LIST or PN_NULLARY, pn_type will be TOK_XMLNAME for the case where
+ * XMLTagContent: XMLNameExpr. If pn_type is not TOK_XMLNAME but pn_arity is
+ * PN_LIST, pn_type will be tagtype. If PN_UNARY, pn_type will be TOK_LC and
+ * we parsed exactly one expression.
+ */
+static JSParseNode *
+XMLTagContent(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType tagtype, JSAtom **namep)
+{
+ JSParseNode *pn, *pn2, *list;
+ JSTokenType tt;
+
+ pn = XMLNameExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ *namep = (pn->pn_arity == PN_NULLARY) ? pn->pn_atom : NULL;
+ list = NULL;
+
+ while (js_MatchToken(cx, ts, TOK_XMLSPACE)) {
+ tt = js_GetToken(cx, ts);
+ if (tt != TOK_XMLNAME && tt != TOK_LC) {
+ js_UngetToken(ts);
+ break;
+ }
+
+ pn2 = XMLNameExpr(cx, ts, tc);
+ if (!pn2)
+ return NULL;
+ if (!list) {
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = tagtype;
+ list->pn_pos.begin = pn->pn_pos.begin;
+ PN_INIT_LIST_1(list, pn);
+ pn = list;
+ }
+ PN_APPEND(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+ MUST_MATCH_TOKEN(TOK_ASSIGN, JSMSG_NO_ASSIGN_IN_XML_ATTR);
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_XMLATTR) {
+ pn2 = XMLAtomNode(cx, ts, tc);
+ } else if (tt == TOK_LC) {
+ pn2 = XMLExpr(cx, ts, JS_TRUE, tc);
+ pn->pn_extra |= PNX_CANTFOLD;
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_ATTR_VALUE);
+ return NULL;
+ }
+ if (!pn2)
+ return NULL;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+
+ return pn;
+}
+
+#define XML_CHECK_FOR_ERROR_AND_EOF(tt,result) \
+ JS_BEGIN_MACRO \
+ if ((tt) <= TOK_EOF) { \
+ if ((tt) == TOK_EOF) { \
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, \
+ JSMSG_END_OF_XML_SOURCE); \
+ } \
+ return result; \
+ } \
+ JS_END_MACRO
+
+static JSParseNode *
+XMLElementOrList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowList);
+
+/*
+ * Consume XML element tag content, including the TOK_XMLETAGO (</) sequence
+ * that opens the end tag for the container.
+ */
+static JSBool
+XMLElementContent(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode *pn2;
+ JSAtom *textAtom;
+
+ ts->flags &= ~TSF_XMLTAGMODE;
+ for (;;) {
+ ts->flags |= TSF_XMLTEXTMODE;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_XMLTEXTMODE;
+ XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
+
+ JS_ASSERT(tt == TOK_XMLSPACE || tt == TOK_XMLTEXT);
+ textAtom = CURRENT_TOKEN(ts).t_atom;
+ if (textAtom) {
+ /* Non-zero-length XML text scanned. */
+ pn2 = XMLAtomNode(cx, ts, tc);
+ if (!pn2)
+ return JS_FALSE;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ XML_CHECK_FOR_ERROR_AND_EOF(tt, JS_FALSE);
+ if (tt == TOK_XMLETAGO)
+ break;
+
+ if (tt == TOK_LC) {
+ pn2 = XMLExpr(cx, ts, JS_FALSE, tc);
+ pn->pn_extra |= PNX_CANTFOLD;
+ } else if (tt == TOK_XMLSTAGO) {
+ pn2 = XMLElementOrList(cx, ts, tc, JS_FALSE);
+ if (pn2) {
+ pn2->pn_extra &= ~PNX_XMLROOT;
+ pn->pn_extra |= pn2->pn_extra;
+ }
+ } else {
+ JS_ASSERT(tt == TOK_XMLCDATA || tt == TOK_XMLCOMMENT ||
+ tt == TOK_XMLPI);
+ pn2 = XMLAtomNode(cx, ts, tc);
+ }
+ if (!pn2)
+ return JS_FALSE;
+ pn->pn_pos.end = pn2->pn_pos.end;
+ PN_APPEND(pn, pn2);
+ }
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_XMLETAGO);
+ ts->flags |= TSF_XMLTAGMODE;
+ return JS_TRUE;
+}
+
+/*
+ * Return a PN_LIST node containing an XML or XMLList Initialiser.
+ */
+static JSParseNode *
+XMLElementOrList(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowList)
+{
+ JSParseNode *pn, *pn2, *list;
+ JSTokenType tt;
+ JSAtom *startAtom, *endAtom;
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_XMLSTAGO);
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+
+ ts->flags |= TSF_XMLTAGMODE;
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_ERROR)
+ return NULL;
+
+ if (tt == TOK_XMLNAME || tt == TOK_LC) {
+ /*
+ * XMLElement. Append the tag and its contents, if any, to pn.
+ */
+ pn2 = XMLTagContent(cx, ts, tc, TOK_XMLSTAGO, &startAtom);
+ if (!pn2)
+ return NULL;
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_XMLPTAGC) {
+ /* Point tag (/>): recycle pn if pn2 is a list of tag contents. */
+ if (pn2->pn_type == TOK_XMLSTAGO) {
+ PN_INIT_LIST(pn);
+ RecycleTree(pn, tc);
+ pn = pn2;
+ } else {
+ JS_ASSERT(pn2->pn_type == TOK_XMLNAME ||
+ pn2->pn_type == TOK_LC);
+ PN_INIT_LIST_1(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+ }
+ pn->pn_type = TOK_XMLPTAGC;
+ pn->pn_extra |= PNX_XMLROOT;
+ } else {
+ /* We had better have a tag-close (>) at this point. */
+ if (tt != TOK_XMLTAGC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_TAG_SYNTAX);
+ return NULL;
+ }
+ pn2->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+
+ /* Make sure pn2 is a TOK_XMLSTAGO list containing tag contents. */
+ if (pn2->pn_type != TOK_XMLSTAGO) {
+ PN_INIT_LIST_1(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+ pn2 = pn;
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ }
+
+ /* Now make pn a nominal-root TOK_XMLELEM list containing pn2. */
+ pn->pn_type = TOK_XMLELEM;
+ PN_INIT_LIST_1(pn, pn2);
+ if (!XML_FOLDABLE(pn2))
+ pn->pn_extra |= PNX_CANTFOLD;
+ pn->pn_extra |= PNX_XMLROOT;
+
+ /* Get element contents and delimiting end-tag-open sequence. */
+ if (!XMLElementContent(cx, ts, pn, tc))
+ return NULL;
+
+ tt = js_GetToken(cx, ts);
+ XML_CHECK_FOR_ERROR_AND_EOF(tt, NULL);
+ if (tt != TOK_XMLNAME && tt != TOK_LC) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_TAG_SYNTAX);
+ return NULL;
+ }
+
+ /* Parse end tag; check mismatch at compile-time if we can. */
+ pn2 = XMLTagContent(cx, ts, tc, TOK_XMLETAGO, &endAtom);
+ if (!pn2)
+ return NULL;
+ if (pn2->pn_type == TOK_XMLETAGO) {
+ /* Oops, end tag has attributes! */
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_TAG_SYNTAX);
+ return NULL;
+ }
+ if (endAtom && startAtom && endAtom != startAtom) {
+ JSString *str = ATOM_TO_STRING(startAtom);
+
+ /* End vs. start tag name mismatch: point to the tag name. */
+ js_ReportCompileErrorNumber(cx, ts, pn2,
+ JSREPORT_UC | JSREPORT_ERROR,
+ JSMSG_XML_TAG_NAME_MISMATCH,
+ JSSTRING_CHARS(str));
+ return NULL;
+ }
+
+ /* Make a TOK_XMLETAGO list with pn2 as its single child. */
+ JS_ASSERT(pn2->pn_type == TOK_XMLNAME || pn2->pn_type == TOK_LC);
+ list = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!list)
+ return NULL;
+ list->pn_type = TOK_XMLETAGO;
+ PN_INIT_LIST_1(list, pn2);
+ PN_APPEND(pn, list);
+ if (!XML_FOLDABLE(pn2)) {
+ list->pn_extra |= PNX_CANTFOLD;
+ pn->pn_extra |= PNX_CANTFOLD;
+ }
+
+ js_MatchToken(cx, ts, TOK_XMLSPACE);
+ MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_TAG_SYNTAX);
+ }
+
+ /* Set pn_op now that pn has been updated to its final value. */
+ pn->pn_op = JSOP_TOXML;
+ } else if (allowList && tt == TOK_XMLTAGC) {
+ /* XMLList Initialiser. */
+ pn->pn_type = TOK_XMLLIST;
+ pn->pn_op = JSOP_TOXMLLIST;
+ PN_INIT_LIST(pn);
+ pn->pn_extra |= PNX_XMLROOT;
+ if (!XMLElementContent(cx, ts, pn, tc))
+ return NULL;
+
+ MUST_MATCH_TOKEN(TOK_XMLTAGC, JSMSG_BAD_XML_LIST_SYNTAX);
+ } else {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_NAME_SYNTAX);
+ return NULL;
+ }
+
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ ts->flags &= ~TSF_XMLTAGMODE;
+ return pn;
+}
+
+static JSParseNode *
+XMLElementOrListRoot(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSBool allowList)
+{
+ uint32 oldopts;
+ JSParseNode *pn;
+
+ /*
+ * Force XML support to be enabled so that comments and CDATA literals
+ * are recognized, instead of <! followed by -- starting an HTML comment
+ * to end of line (used in script tags to hide content from old browsers
+ * that don't recognize <script>).
+ */
+ oldopts = JS_SetOptions(cx, cx->options | JSOPTION_XML);
+ pn = XMLElementOrList(cx, ts, tc, allowList);
+ JS_SetOptions(cx, oldopts);
+ return pn;
+}
+
+JS_FRIEND_API(JSParseNode *)
+js_ParseXMLText(JSContext *cx, JSObject *chain, JSParseContext *pc,
+ JSBool allowList)
+{
+ JSParseNode *pn;
+ JSTreeContext tc;
+ JSTokenType tt;
+
+ /*
+ * Push a compiler frame if we have no frames, or if the top frame is a
+ * lightweight function activation, or if its scope chain doesn't match
+ * the one passed to us.
+ */
+ TREE_CONTEXT_INIT(&tc, pc);
+ tc.u.scopeChain = chain;
+
+ /* Set XML-only mode to turn off special treatment of {expr} in XML. */
+ TS(pc)->flags |= TSF_OPERAND | TSF_XMLONLYMODE;
+ tt = js_GetToken(cx, TS(pc));
+ TS(pc)->flags &= ~TSF_OPERAND;
+
+ if (tt != TOK_XMLSTAGO) {
+ js_ReportCompileErrorNumber(cx, TS(pc), NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_MARKUP);
+ pn = NULL;
+ } else {
+ pn = XMLElementOrListRoot(cx, TS(pc), &tc, allowList);
+ }
+
+ TS(pc)->flags &= ~TSF_XMLONLYMODE;
+ TREE_CONTEXT_FINISH(cx, &tc);
+ return pn;
+}
+
+#endif /* JS_HAS_XMLSUPPORT */
+
+static JSParseNode *
+PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSTokenType tt, JSBool afterDot)
+{
+ JSParseNode *pn, *pn2, *pn3;
+ JSOp op;
+#if JS_HAS_SHARP_VARS
+ JSParseNode *defsharp;
+ JSBool notsharp;
+#endif
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+#if JS_HAS_SHARP_VARS
+ defsharp = NULL;
+ notsharp = JS_FALSE;
+ again:
+ /*
+ * Control flows here after #n= is scanned. If the following primary is
+ * not valid after such a "sharp variable" definition, the tt switch case
+ * should set notsharp.
+ */
+#endif
+
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_FUNCTION);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+
+ switch (tt) {
+ case TOK_FUNCTION:
+#if JS_HAS_XML_SUPPORT
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ if (js_MatchToken(cx, ts, TOK_DBLCOLON)) {
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ pn2 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn2)
+ return NULL;
+ pn2->pn_type = TOK_FUNCTION;
+ pn = QualifiedSuffix(cx, ts, pn2, tc);
+ if (!pn)
+ return NULL;
+ break;
+ }
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+#endif
+ pn = FunctionExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ break;
+
+ case TOK_LB:
+ {
+ JSBool matched;
+ jsuint index;
+
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_RB;
+ pn->pn_op = JSOP_NEWINIT;
+
+#if JS_HAS_SHARP_VARS
+ if (defsharp) {
+ PN_INIT_LIST_1(pn, defsharp);
+ defsharp = NULL;
+ } else
+#endif
+ PN_INIT_LIST(pn);
+
+ ts->flags |= TSF_OPERAND;
+ matched = js_MatchToken(cx, ts, TOK_RB);
+ ts->flags &= ~TSF_OPERAND;
+ if (!matched) {
+ for (index = 0; ; index++) {
+ if (index == ARRAY_INIT_LIMIT) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_ARRAY_INIT_TOO_BIG);
+ return NULL;
+ }
+
+ ts->flags |= TSF_OPERAND;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ if (tt == TOK_RB) {
+ pn->pn_extra |= PNX_ENDCOMMA;
+ break;
+ }
+
+ if (tt == TOK_COMMA) {
+ /* So CURRENT_TOKEN gets TOK_COMMA and not TOK_LB. */
+ js_MatchToken(cx, ts, TOK_COMMA);
+ pn2 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ } else {
+ pn2 = AssignExpr(cx, ts, tc);
+ }
+ if (!pn2)
+ return NULL;
+ PN_APPEND(pn, pn2);
+
+ if (tt != TOK_COMMA) {
+ /* If we didn't already match TOK_COMMA in above case. */
+ if (!js_MatchToken(cx, ts, TOK_COMMA))
+ break;
+ }
+ }
+
+#if JS_HAS_GENERATORS
+ /*
+ * At this point, (index == 0 && pn->pn_count != 0) implies one
+ * element initialiser was parsed (possibly with a defsharp before
+ * the left bracket).
+ *
+ * An array comprehension of the form:
+ *
+ * [i * j for (i in o) for (j in p) if (i != j)]
+ *
+ * translates to roughly the following let expression:
+ *
+ * let (array = new Array, i, j) {
+ * for (i in o) let {
+ * for (j in p)
+ * if (i != j)
+ * array.push(i * j)
+ * }
+ * array
+ * }
+ *
+ * where array is a nameless block-local variable. The "roughly"
+ * means that an implementation may optimize away the array.push.
+ * An array comprehension opens exactly one block scope, no matter
+ * how many for heads it contains.
+ *
+ * Each let () {...} or for (let ...) ... compiles to:
+ *
+ * JSOP_ENTERBLOCK <o> ... JSOP_LEAVEBLOCK <n>
+ *
+ * where <o> is a literal object representing the block scope,
+ * with <n> properties, naming each var declared in the block.
+ *
+ * Each var declaration in a let-block binds a name in <o> at
+ * compile time, and allocates a slot on the operand stack at
+ * runtime via JSOP_ENTERBLOCK. A block-local var is accessed
+ * by the JSOP_GETLOCAL and JSOP_SETLOCAL ops, and iterated with
+ * JSOP_FORLOCAL. These ops all have an immediate operand, the
+ * local slot's stack index from fp->spbase.
+ *
+ * The array comprehension iteration step, array.push(i * j) in
+ * the example above, is done by <i * j>; JSOP_ARRAYCOMP <array>,
+ * where <array> is the index of array's stack slot.
+ */
+ if (index == 0 &&
+ pn->pn_count != 0 &&
+ js_MatchToken(cx, ts, TOK_FOR)) {
+ JSParseNode *pnexp, *pntop;
+
+ /* Relabel pn as an array comprehension node. */
+ pn->pn_type = TOK_ARRAYCOMP;
+
+ /*
+ * Remove the comprehension expression from pn's linked list
+ * and save it via pnexp. We'll re-install it underneath the
+ * ARRAYPUSH node after we parse the rest of the comprehension.
+ */
+ pnexp = PN_LAST(pn);
+ JS_ASSERT(pn->pn_count == 1 || pn->pn_count == 2);
+ pn->pn_tail = (--pn->pn_count == 1)
+ ? &pn->pn_head->pn_next
+ : &pn->pn_head;
+ *pn->pn_tail = NULL;
+
+ pntop = ComprehensionTail(cx, ts, tc, TOK_ARRAYPUSH,
+ JSOP_ARRAYPUSH, pnexp);
+ if (!pntop)
+ return NULL;
+ PN_APPEND(pn, pntop);
+ }
+#endif /* JS_HAS_GENERATORS */
+
+ MUST_MATCH_TOKEN(TOK_RB, JSMSG_BRACKET_AFTER_LIST);
+ }
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ return pn;
+ }
+
+ case TOK_LC:
+ {
+ JSBool afterComma;
+ JSParseNode *pnval;
+
+ pn = NewParseNode(cx, ts, PN_LIST, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_type = TOK_RC;
+ pn->pn_op = JSOP_NEWINIT;
+
+#if JS_HAS_SHARP_VARS
+ if (defsharp) {
+ PN_INIT_LIST_1(pn, defsharp);
+ defsharp = NULL;
+ } else
+#endif
+ PN_INIT_LIST(pn);
+
+ afterComma = JS_FALSE;
+ for (;;) {
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ switch (tt) {
+ case TOK_NUMBER:
+ pn3 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (pn3)
+ pn3->pn_dval = CURRENT_TOKEN(ts).t_dval;
+ break;
+ case TOK_NAME:
+#if JS_HAS_GETTER_SETTER
+ {
+ JSAtom *atom;
+
+ atom = CURRENT_TOKEN(ts).t_atom;
+ if (atom == cx->runtime->atomState.getAtom)
+ op = JSOP_GETTER;
+ else if (atom == cx->runtime->atomState.setAtom)
+ op = JSOP_SETTER;
+ else
+ goto property_name;
+
+ ts->flags |= TSF_KEYWORD_IS_NAME;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_KEYWORD_IS_NAME;
+ if (tt != TOK_NAME) {
+ js_UngetToken(ts);
+ goto property_name;
+ }
+ pn3 = NewParseNode(cx, ts, PN_NAME, tc);
+ if (!pn3)
+ return NULL;
+ pn3->pn_atom = CURRENT_TOKEN(ts).t_atom;
+ pn3->pn_slot = -1;
+
+ /* We have to fake a 'function' token here. */
+ CURRENT_TOKEN(ts).t_op = JSOP_NOP;
+ CURRENT_TOKEN(ts).type = TOK_FUNCTION;
+ pn2 = FunctionExpr(cx, ts, tc);
+ pn2 = NewBinary(cx, TOK_COLON, op, pn3, pn2, tc);
+ goto skip;
+ }
+ property_name:
+#endif
+ case TOK_STRING:
+ pn3 = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (pn3)
+ pn3->pn_atom = CURRENT_TOKEN(ts).t_atom;
+ break;
+ case TOK_RC:
+ if (afterComma &&
+ !js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_TRAILING_COMMA)) {
+ return NULL;
+ }
+ goto end_obj_init;
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_PROP_ID);
+ return NULL;
+ }
+
+ tt = js_GetToken(cx, ts);
+#if JS_HAS_GETTER_SETTER
+ if (tt == TOK_NAME) {
+ tt = CheckGetterOrSetter(cx, ts, TOK_COLON);
+ if (tt == TOK_ERROR)
+ return NULL;
+ }
+#endif
+
+ if (tt != TOK_COLON) {
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ if (tt != TOK_COMMA && tt != TOK_RC) {
+#endif
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_COLON_AFTER_ID);
+ return NULL;
+#if JS_HAS_DESTRUCTURING_SHORTHAND
+ }
+
+ /*
+ * Support, e.g., |var {x, y} = o| as destructuring shorthand
+ * for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
+ */
+ js_UngetToken(ts);
+ pn->pn_extra |= PNX_SHORTHAND;
+ pnval = pn3;
+ if (pnval->pn_type == TOK_NAME) {
+ pnval->pn_arity = PN_NAME;
+ pnval->pn_expr = NULL;
+ pnval->pn_slot = -1;
+ pnval->pn_const = JS_FALSE;
+ }
+ op = JSOP_NOP;
+#endif
+ } else {
+ op = CURRENT_TOKEN(ts).t_op;
+ pnval = AssignExpr(cx, ts, tc);
+ }
+
+ pn2 = NewBinary(cx, TOK_COLON, op, pn3, pnval, tc);
+#if JS_HAS_GETTER_SETTER
+ skip:
+#endif
+ if (!pn2)
+ return NULL;
+ PN_APPEND(pn, pn2);
+
+ tt = js_GetToken(cx, ts);
+ if (tt == TOK_RC)
+ goto end_obj_init;
+ if (tt != TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_CURLY_AFTER_LIST);
+ return NULL;
+ }
+ afterComma = JS_TRUE;
+ }
+
+ end_obj_init:
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ return pn;
+ }
+
+#if JS_HAS_BLOCK_SCOPE
+ case TOK_LET:
+ pn = LetBlock(cx, ts, tc, JS_FALSE);
+ if (!pn)
+ return NULL;
+ break;
+#endif
+
+#if JS_HAS_SHARP_VARS
+ case TOK_DEFSHARP:
+ if (defsharp)
+ goto badsharp;
+ defsharp = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!defsharp)
+ return NULL;
+ defsharp->pn_num = (jsint) CURRENT_TOKEN(ts).t_dval;
+ ts->flags |= TSF_OPERAND;
+ tt = js_GetToken(cx, ts);
+ ts->flags &= ~TSF_OPERAND;
+ goto again;
+
+ case TOK_USESHARP:
+ /* Check for forward/dangling references at runtime, to allow eval. */
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_num = (jsint) CURRENT_TOKEN(ts).t_dval;
+ notsharp = JS_TRUE;
+ break;
+#endif /* JS_HAS_SHARP_VARS */
+
+ case TOK_LP:
+ {
+ JSBool genexp;
+
+ pn = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn)
+ return NULL;
+ pn2 = ParenExpr(cx, ts, tc, pn, &genexp);
+ if (!pn2)
+ return NULL;
+ if (genexp)
+ return pn2;
+
+ MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
+ if (pn2->pn_type == TOK_RP ||
+ (js_CodeSpec[pn2->pn_op].prec >= js_CodeSpec[JSOP_GETPROP].prec &&
+ !afterDot)) {
+ /*
+ * Avoid redundant JSOP_GROUP opcodes, for efficiency and mainly
+ * to help the decompiler look ahead from a JSOP_ENDINIT to see a
+ * JSOP_GROUP followed by a POP or POPV. That sequence means the
+ * parentheses are mandatory, to disambiguate object initialisers
+ * as expression statements from block statements.
+ *
+ * Also drop pn if pn2 is a member or a primary expression of any
+ * kind. This is required to avoid generating a JSOP_GROUP that
+ * will null the |obj| interpreter register, causing |this| in any
+ * call of that member expression to bind to the global object.
+ */
+ RecycleTree(pn, tc);
+ pn = pn2;
+ } else {
+ pn->pn_type = TOK_RP;
+ pn->pn_kid = pn2;
+ }
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ break;
+ }
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_STAR:
+ pn = QualifiedIdentifier(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ notsharp = JS_TRUE;
+ break;
+
+ case TOK_AT:
+ pn = AttributeIdentifier(cx, ts, tc);
+ if (!pn)
+ return NULL;
+ notsharp = JS_TRUE;
+ break;
+
+ case TOK_XMLSTAGO:
+ pn = XMLElementOrListRoot(cx, ts, tc, JS_TRUE);
+ if (!pn)
+ return NULL;
+ notsharp = JS_TRUE; /* XXXbe could be sharp? */
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ case TOK_STRING:
+#if JS_HAS_SHARP_VARS
+ notsharp = JS_TRUE;
+ /* FALL THROUGH */
+#endif
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLCDATA:
+ case TOK_XMLCOMMENT:
+ case TOK_XMLPI:
+#endif
+ case TOK_NAME:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_atom = CURRENT_TOKEN(ts).t_atom;
+#if JS_HAS_XML_SUPPORT
+ if (tt == TOK_XMLPI)
+ pn->pn_atom2 = CURRENT_TOKEN(ts).t_atom2;
+ else
+#endif
+ pn->pn_op = CURRENT_TOKEN(ts).t_op;
+ if (tt == TOK_NAME) {
+ pn->pn_arity = PN_NAME;
+ pn->pn_slot = -1;
+
+#if JS_HAS_XML_SUPPORT
+ if (js_MatchToken(cx, ts, TOK_DBLCOLON)) {
+ if (afterDot) {
+ JSString *str;
+
+ /*
+ * Here PrimaryExpr is called after '.' or '..' and we
+ * just scanned .name:: or ..name:: . This is the only
+ * case where a keyword after '.' or '..' is not
+ * treated as a property name.
+ */
+ str = ATOM_TO_STRING(pn->pn_atom);
+ tt = js_CheckKeyword(JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ if (tt == TOK_FUNCTION) {
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_type = TOK_FUNCTION;
+ } else if (tt != TOK_EOF) {
+ js_ReportCompileErrorNumber(
+ cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_KEYWORD_NOT_NS);
+ return NULL;
+ }
+ }
+ pn = QualifiedSuffix(cx, ts, pn, tc);
+ if (!pn)
+ return NULL;
+ break;
+ }
+#endif
+
+ /* Unqualified __parent__ and __proto__ uses require activations. */
+ if (pn->pn_atom == cx->runtime->atomState.parentAtom ||
+ pn->pn_atom == cx->runtime->atomState.protoAtom) {
+ tc->flags |= TCF_FUN_HEAVYWEIGHT;
+ }
+ }
+ break;
+
+ case TOK_REGEXP:
+ {
+ JSObject *obj;
+
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+
+ /* Token stream ensures that tokenbuf is NUL-terminated. */
+ JS_ASSERT(*ts->tokenbuf.ptr == (jschar) 0);
+ obj = js_NewRegExpObject(cx, ts,
+ ts->tokenbuf.base,
+ ts->tokenbuf.ptr - ts->tokenbuf.base,
+ CURRENT_TOKEN(ts).t_reflags);
+ if (!obj)
+ return NULL;
+ if (!(tc->flags & TCF_COMPILE_N_GO)) {
+ STOBJ_CLEAR_PARENT(obj);
+ STOBJ_CLEAR_PROTO(obj);
+ }
+
+ pn->pn_pob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
+ if (!pn->pn_pob)
+ return NULL;
+
+ pn->pn_op = JSOP_REGEXP;
+ break;
+ }
+
+ case TOK_NUMBER:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = JSOP_DOUBLE;
+ pn->pn_dval = CURRENT_TOKEN(ts).t_dval;
+#if JS_HAS_SHARP_VARS
+ notsharp = JS_TRUE;
+#endif
+ break;
+
+ case TOK_PRIMARY:
+ pn = NewParseNode(cx, ts, PN_NULLARY, tc);
+ if (!pn)
+ return NULL;
+ pn->pn_op = CURRENT_TOKEN(ts).t_op;
+#if JS_HAS_SHARP_VARS
+ notsharp = JS_TRUE;
+#endif
+ break;
+
+ case TOK_ERROR:
+ /* The scanner or one of its subroutines reported the error. */
+ return NULL;
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+
+#if JS_HAS_SHARP_VARS
+ if (defsharp) {
+ if (notsharp) {
+ badsharp:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_SHARP_VAR_DEF);
+ return NULL;
+ }
+ defsharp->pn_kid = pn;
+ return defsharp;
+ }
+#endif
+ return pn;
+}
+
+static JSParseNode *
+ParenExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
+ JSParseNode *pn1, JSBool *genexp)
+{
+ JSTokenPtr begin;
+ JSParseNode *pn;
+#if JS_HAS_GENERATOR_EXPRS
+ uintN oldflags = tc->flags;
+#endif
+
+ JS_ASSERT(CURRENT_TOKEN(ts).type == TOK_LP);
+ begin = CURRENT_TOKEN(ts).pos.begin;
+
+ if (genexp)
+ *genexp = JS_FALSE;
+ pn = BracketedExpr(cx, ts, tc);
+ if (!pn)
+ return NULL;
+
+#if JS_HAS_GENERATOR_EXPRS
+ if (js_MatchToken(cx, ts, TOK_FOR)) {
+ if (pn->pn_type == TOK_YIELD) {
+ js_ReportCompileErrorNumber(cx, ts, pn, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_yield_str);
+ return NULL;
+ }
+ if (pn->pn_type == TOK_COMMA) {
+ js_ReportCompileErrorNumber(cx, ts, PN_LAST(pn), JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_generator_str);
+ return NULL;
+ }
+ if (!pn1) {
+ pn1 = NewParseNode(cx, ts, PN_UNARY, tc);
+ if (!pn1)
+ return NULL;
+ }
+ pn->pn_pos.begin = begin;
+ pn = GeneratorExpr(cx, ts, tc, oldflags, pn1, pn);
+ if (!pn)
+ return NULL;
+ if (genexp) {
+ if (js_GetToken(cx, ts) != TOK_RP) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_GENERATOR_SYNTAX,
+ js_generator_str);
+ return NULL;
+ }
+ pn->pn_pos.end = CURRENT_TOKEN(ts).pos.end;
+ *genexp = JS_TRUE;
+ }
+ }
+#endif /* JS_HAS_GENERATOR_EXPRS */
+
+ return pn;
+}
+
+/*
+ * Fold from one constant type to another.
+ * XXX handles only strings and numbers for now
+ */
+static JSBool
+FoldType(JSContext *cx, JSParseNode *pn, JSTokenType type)
+{
+ if (pn->pn_type != type) {
+ switch (type) {
+ case TOK_NUMBER:
+ if (pn->pn_type == TOK_STRING) {
+ jsdouble d;
+ if (!JS_ValueToNumber(cx, ATOM_KEY(pn->pn_atom), &d))
+ return JS_FALSE;
+ pn->pn_dval = d;
+ pn->pn_type = TOK_NUMBER;
+ pn->pn_op = JSOP_DOUBLE;
+ }
+ break;
+
+ case TOK_STRING:
+ if (pn->pn_type == TOK_NUMBER) {
+ JSString *str = js_NumberToString(cx, pn->pn_dval);
+ if (!str)
+ return JS_FALSE;
+ pn->pn_atom = js_AtomizeString(cx, str, 0);
+ if (!pn->pn_atom)
+ return JS_FALSE;
+ pn->pn_type = TOK_STRING;
+ pn->pn_op = JSOP_STRING;
+ }
+ break;
+
+ default:;
+ }
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Fold two numeric constants. Beware that pn1 and pn2 are recycled, unless
+ * one of them aliases pn, so you can't safely fetch pn2->pn_next, e.g., after
+ * a successful call to this function.
+ */
+static JSBool
+FoldBinaryNumeric(JSContext *cx, JSOp op, JSParseNode *pn1, JSParseNode *pn2,
+ JSParseNode *pn, JSTreeContext *tc)
+{
+ jsdouble d, d2;
+ int32 i, j;
+
+ JS_ASSERT(pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER);
+ d = pn1->pn_dval;
+ d2 = pn2->pn_dval;
+ switch (op) {
+ case JSOP_LSH:
+ case JSOP_RSH:
+ i = js_DoubleToECMAInt32(d);
+ j = js_DoubleToECMAInt32(d2);
+ j &= 31;
+ d = (op == JSOP_LSH) ? i << j : i >> j;
+ break;
+
+ case JSOP_URSH:
+ j = js_DoubleToECMAInt32(d2);
+ j &= 31;
+ d = js_DoubleToECMAUint32(d) >> j;
+ break;
+
+ case JSOP_ADD:
+ d += d2;
+ break;
+
+ case JSOP_SUB:
+ d -= d2;
+ break;
+
+ case JSOP_MUL:
+ d *= d2;
+ break;
+
+ case JSOP_DIV:
+ if (d2 == 0) {
+#if defined(XP_WIN)
+ /* XXX MSVC miscompiles such that (NaN == 0) */
+ if (JSDOUBLE_IS_NaN(d2))
+ d = *cx->runtime->jsNaN;
+ else
+#endif
+ if (d == 0 || JSDOUBLE_IS_NaN(d))
+ d = *cx->runtime->jsNaN;
+ else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
+ d = *cx->runtime->jsNegativeInfinity;
+ else
+ d = *cx->runtime->jsPositiveInfinity;
+ } else {
+ d /= d2;
+ }
+ break;
+
+ case JSOP_MOD:
+ if (d2 == 0) {
+ d = *cx->runtime->jsNaN;
+ } else {
+#if defined(XP_WIN)
+ /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
+ if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
+#endif
+ d = fmod(d, d2);
+ }
+ break;
+
+ default:;
+ }
+
+ /* Take care to allow pn1 or pn2 to alias pn. */
+ if (pn1 != pn)
+ RecycleTree(pn1, tc);
+ if (pn2 != pn)
+ RecycleTree(pn2, tc);
+ pn->pn_type = TOK_NUMBER;
+ pn->pn_op = JSOP_DOUBLE;
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_dval = d;
+ return JS_TRUE;
+}
+
+#if JS_HAS_XML_SUPPORT
+
+static JSBool
+FoldXMLConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc)
+{
+ JSTokenType tt;
+ JSParseNode **pnp, *pn1, *pn2;
+ JSString *accum, *str;
+ uint32 i, j;
+ JSTempValueRooter tvr;
+
+ JS_ASSERT(pn->pn_arity == PN_LIST);
+ tt = PN_TYPE(pn);
+ pnp = &pn->pn_head;
+ pn1 = *pnp;
+ accum = NULL;
+ if ((pn->pn_extra & PNX_CANTFOLD) == 0) {
+ if (tt == TOK_XMLETAGO)
+ accum = ATOM_TO_STRING(cx->runtime->atomState.etagoAtom);
+ else if (tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC)
+ accum = ATOM_TO_STRING(cx->runtime->atomState.stagoAtom);
+ }
+
+ /*
+ * GC Rooting here is tricky: for most of the loop, |accum| is safe via
+ * the newborn string root. However, when |pn2->pn_type| is TOK_XMLCDATA,
+ * TOK_XMLCOMMENT, or TOK_XMLPI it is knocked out of the newborn root.
+ * Therefore, we have to add additonal protection from GC nesting under
+ * js_ConcatStrings.
+ */
+ for (pn2 = pn1, i = j = 0; pn2; pn2 = pn2->pn_next, i++) {
+ /* The parser already rejected end-tags with attributes. */
+ JS_ASSERT(tt != TOK_XMLETAGO || i == 0);
+ switch (pn2->pn_type) {
+ case TOK_XMLATTR:
+ if (!accum)
+ goto cantfold;
+ /* FALL THROUGH */
+ case TOK_XMLNAME:
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_STRING:
+ if (pn2->pn_arity == PN_LIST)
+ goto cantfold;
+ str = ATOM_TO_STRING(pn2->pn_atom);
+ break;
+
+ case TOK_XMLCDATA:
+ str = js_MakeXMLCDATAString(cx, ATOM_TO_STRING(pn2->pn_atom));
+ if (!str)
+ return JS_FALSE;
+ break;
+
+ case TOK_XMLCOMMENT:
+ str = js_MakeXMLCommentString(cx, ATOM_TO_STRING(pn2->pn_atom));
+ if (!str)
+ return JS_FALSE;
+ break;
+
+ case TOK_XMLPI:
+ str = js_MakeXMLPIString(cx, ATOM_TO_STRING(pn2->pn_atom),
+ ATOM_TO_STRING(pn2->pn_atom2));
+ if (!str)
+ return JS_FALSE;
+ break;
+
+ cantfold:
+ default:
+ JS_ASSERT(*pnp == pn1);
+ if ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) &&
+ (i & 1) ^ (j & 1)) {
+#ifdef DEBUG_brendanXXX
+ printf("1: %d, %d => ", i, j);
+ if (accum)
+ js_FileEscapedString(stdout, accum, 0);
+ else
+ fputs("NULL", stdout);
+ fputc('\n', stdout);
+#endif
+ } else if (accum && pn1 != pn2) {
+ while (pn1->pn_next != pn2) {
+ pn1 = RecycleTree(pn1, tc);
+ --pn->pn_count;
+ }
+ pn1->pn_type = TOK_XMLTEXT;
+ pn1->pn_op = JSOP_STRING;
+ pn1->pn_arity = PN_NULLARY;
+ pn1->pn_atom = js_AtomizeString(cx, accum, 0);
+ if (!pn1->pn_atom)
+ return JS_FALSE;
+ JS_ASSERT(pnp != &pn1->pn_next);
+ *pnp = pn1;
+ }
+ pnp = &pn2->pn_next;
+ pn1 = *pnp;
+ accum = NULL;
+ continue;
+ }
+
+ if (accum) {
+ JS_PUSH_TEMP_ROOT_STRING(cx, accum, &tvr);
+ str = ((tt == TOK_XMLSTAGO || tt == TOK_XMLPTAGC) && i != 0)
+ ? js_AddAttributePart(cx, i & 1, accum, str)
+ : js_ConcatStrings(cx, accum, str);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!str)
+ return JS_FALSE;
+#ifdef DEBUG_brendanXXX
+ printf("2: %d, %d => ", i, j);
+ js_FileEscapedString(stdout, str, 0);
+ printf(" (%u)\n", JSSTRING_LENGTH(str));
+#endif
+ ++j;
+ }
+ accum = str;
+ }
+
+ if (accum) {
+ str = NULL;
+ if ((pn->pn_extra & PNX_CANTFOLD) == 0) {
+ if (tt == TOK_XMLPTAGC)
+ str = ATOM_TO_STRING(cx->runtime->atomState.ptagcAtom);
+ else if (tt == TOK_XMLSTAGO || tt == TOK_XMLETAGO)
+ str = ATOM_TO_STRING(cx->runtime->atomState.tagcAtom);
+ }
+ if (str) {
+ accum = js_ConcatStrings(cx, accum, str);
+ if (!accum)
+ return JS_FALSE;
+ }
+
+ JS_ASSERT(*pnp == pn1);
+ while (pn1->pn_next) {
+ pn1 = RecycleTree(pn1, tc);
+ --pn->pn_count;
+ }
+ pn1->pn_type = TOK_XMLTEXT;
+ pn1->pn_op = JSOP_STRING;
+ pn1->pn_arity = PN_NULLARY;
+ pn1->pn_atom = js_AtomizeString(cx, accum, 0);
+ if (!pn1->pn_atom)
+ return JS_FALSE;
+ JS_ASSERT(pnp != &pn1->pn_next);
+ *pnp = pn1;
+ }
+
+ if (pn1 && pn->pn_count == 1) {
+ /*
+ * Only one node under pn, and it has been folded: move pn1 onto pn
+ * unless pn is an XML root (in which case we need it to tell the code
+ * generator to emit a JSOP_TOXML or JSOP_TOXMLLIST op). If pn is an
+ * XML root *and* it's a point-tag, rewrite it to TOK_XMLELEM to avoid
+ * extra "<" and "/>" bracketing at runtime.
+ */
+ if (!(pn->pn_extra & PNX_XMLROOT)) {
+ PN_MOVE_NODE(pn, pn1);
+ } else if (tt == TOK_XMLPTAGC) {
+ pn->pn_type = TOK_XMLELEM;
+ pn->pn_op = JSOP_TOXML;
+ }
+ }
+ return JS_TRUE;
+}
+
+#endif /* JS_HAS_XML_SUPPORT */
+
+static JSBool
+StartsWith(JSParseNode *pn, JSTokenType tt)
+{
+#define TAIL_RECURSE(pn2) JS_BEGIN_MACRO pn = (pn2); goto recur; JS_END_MACRO
+
+recur:
+ if (pn->pn_type == tt)
+ return JS_TRUE;
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ return tt == TOK_FUNCTION;
+ case PN_LIST:
+ if (pn->pn_head)
+ TAIL_RECURSE(pn->pn_head);
+ break;
+ case PN_TERNARY:
+ if (pn->pn_kid1)
+ TAIL_RECURSE(pn->pn_kid1);
+ break;
+ case PN_BINARY:
+ if (pn->pn_left)
+ TAIL_RECURSE(pn->pn_left);
+ break;
+ case PN_UNARY:
+ /* A parenthesized expression starts with a left parenthesis. */
+ if (pn->pn_type == TOK_RP)
+ return tt == TOK_LP;
+ if (pn->pn_kid)
+ TAIL_RECURSE(pn->pn_kid);
+ break;
+ case PN_NAME:
+ if (pn->pn_type == TOK_DOT || pn->pn_type == TOK_DBLDOT)
+ TAIL_RECURSE(pn->pn_expr);
+ /* FALL THROUGH */
+ }
+ return JS_FALSE;
+#undef TAIL_RECURSE
+}
+
+static int
+Boolish(JSParseNode *pn)
+{
+ switch (pn->pn_op) {
+ case JSOP_DOUBLE:
+ return pn->pn_dval != 0 && !JSDOUBLE_IS_NaN(pn->pn_dval);
+
+ case JSOP_STRING:
+ return JSSTRING_LENGTH(ATOM_TO_STRING(pn->pn_atom)) != 0;
+
+#if JS_HAS_GENERATOR_EXPRS
+ case JSOP_CALL:
+ {
+ /*
+ * A generator expression as an if or loop condition has no effects, it
+ * simply results in a truthy object reference. This condition folding
+ * is needed for the decompiler. See bug 442342 and bug 443074.
+ */
+ if (pn->pn_count != 1)
+ break;
+ JSParseNode *pn2 = pn->pn_head;
+ if (pn2->pn_type != TOK_FUNCTION)
+ break;
+ if (!(pn2->pn_flags & TCF_GENEXP_LAMBDA))
+ break;
+ /* FALL THROUGH */
+ }
+#endif
+
+ case JSOP_DEFFUN:
+ case JSOP_NAMEDFUNOBJ:
+ case JSOP_ANONFUNOBJ:
+ case JSOP_THIS:
+ case JSOP_TRUE:
+ return 1;
+
+ case JSOP_NULL:
+ case JSOP_FALSE:
+ return 0;
+
+ default:;
+ }
+ return -1;
+}
+
+JSBool
+js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc, bool inCond)
+{
+ JSParseNode *pn1 = NULL, *pn2 = NULL, *pn3 = NULL;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ switch (pn->pn_arity) {
+ case PN_FUNC:
+ {
+ uint16 oldflags = tc->flags;
+
+ tc->flags = (uint16) pn->pn_flags;
+ if (!js_FoldConstants(cx, pn->pn_body, tc))
+ return JS_FALSE;
+ tc->flags = oldflags;
+ break;
+ }
+
+ case PN_LIST:
+ {
+ /* Propagate inCond through logical connectives. */
+ bool cond = inCond && (pn->pn_type == TOK_OR || pn->pn_type == TOK_AND);
+
+ /* Save the list head in pn1 for later use. */
+ for (pn1 = pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ if (!js_FoldConstants(cx, pn2, tc, cond))
+ return JS_FALSE;
+ }
+ break;
+ }
+
+ case PN_TERNARY:
+ /* Any kid may be null (e.g. for (;;)). */
+ pn1 = pn->pn_kid1;
+ pn2 = pn->pn_kid2;
+ pn3 = pn->pn_kid3;
+ if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->pn_type == TOK_IF))
+ return JS_FALSE;
+ if (pn2) {
+ if (!js_FoldConstants(cx, pn2, tc, pn->pn_type == TOK_FORHEAD))
+ return JS_FALSE;
+ if (pn->pn_type == TOK_FORHEAD && pn2->pn_op == JSOP_TRUE) {
+ RecycleTree(pn2, tc);
+ pn->pn_kid2 = NULL;
+ }
+ }
+ if (pn3 && !js_FoldConstants(cx, pn3, tc))
+ return JS_FALSE;
+ break;
+
+ case PN_BINARY:
+ pn1 = pn->pn_left;
+ pn2 = pn->pn_right;
+
+ /* Propagate inCond through logical connectives. */
+ if (pn->pn_type == TOK_OR || pn->pn_type == TOK_AND) {
+ if (!js_FoldConstants(cx, pn1, tc, inCond))
+ return JS_FALSE;
+ if (!js_FoldConstants(cx, pn2, tc, inCond))
+ return JS_FALSE;
+ break;
+ }
+
+ /* First kid may be null (for default case in switch). */
+ if (pn1 && !js_FoldConstants(cx, pn1, tc, pn->pn_type == TOK_WHILE))
+ return JS_FALSE;
+ if (!js_FoldConstants(cx, pn2, tc, pn->pn_type == TOK_DO))
+ return JS_FALSE;
+ break;
+
+ case PN_UNARY:
+ /* Our kid may be null (e.g. return; vs. return e;). */
+ pn1 = pn->pn_kid;
+ if (pn1 &&
+ !js_FoldConstants(cx, pn1, tc,
+ (inCond && pn->pn_type == TOK_RP) ||
+ pn->pn_op == JSOP_NOT)) {
+ return JS_FALSE;
+ }
+ break;
+
+ case PN_NAME:
+ /*
+ * Skip pn1 down along a chain of dotted member expressions to avoid
+ * excessive recursion. Our only goal here is to fold constants (if
+ * any) in the primary expression operand to the left of the first
+ * dot in the chain.
+ */
+ pn1 = pn->pn_expr;
+ while (pn1 && pn1->pn_arity == PN_NAME)
+ pn1 = pn1->pn_expr;
+ if (pn1 && !js_FoldConstants(cx, pn1, tc))
+ return JS_FALSE;
+ break;
+
+ case PN_NULLARY:
+ break;
+ }
+
+ switch (pn->pn_type) {
+ case TOK_IF:
+ if (ContainsStmt(pn2, TOK_VAR) || ContainsStmt(pn3, TOK_VAR))
+ break;
+ /* FALL THROUGH */
+
+ case TOK_HOOK:
+ /* Reduce 'if (C) T; else E' into T for true C, E for false. */
+ while (pn1->pn_type == TOK_RP)
+ pn1 = pn1->pn_kid;
+ switch (pn1->pn_type) {
+ case TOK_NUMBER:
+ if (pn1->pn_dval == 0 || JSDOUBLE_IS_NaN(pn1->pn_dval))
+ pn2 = pn3;
+ break;
+ case TOK_STRING:
+ if (JSSTRING_LENGTH(ATOM_TO_STRING(pn1->pn_atom)) == 0)
+ pn2 = pn3;
+ break;
+ case TOK_PRIMARY:
+ if (pn1->pn_op == JSOP_TRUE)
+ break;
+ if (pn1->pn_op == JSOP_FALSE || pn1->pn_op == JSOP_NULL) {
+ pn2 = pn3;
+ break;
+ }
+ /* FALL THROUGH */
+ default:
+ /* Early return to dodge common code that copies pn2 to pn. */
+ return JS_TRUE;
+ }
+
+#if JS_HAS_GENERATOR_EXPRS
+ /* Don't fold a trailing |if (0)| in a generator expression. */
+ if (!pn2 && (tc->flags & TCF_GENEXP_LAMBDA))
+ break;
+#endif
+
+ if (pn2) {
+ /*
+ * pn2 is the then- or else-statement subtree to compile. Take
+ * care not to expose an object initialiser, which would be parsed
+ * as a block, to the Statement parser via eval(uneval(e)) where e
+ * is '1 ? {p:2, q:3}[i] : r;' or the like.
+ */
+ if (pn->pn_type == TOK_HOOK && StartsWith(pn2, TOK_RC)) {
+ pn->pn_type = TOK_RP;
+ pn->pn_arity = PN_UNARY;
+ pn->pn_kid = pn2;
+ if (pn3 && pn3 != pn2)
+ RecycleTree(pn3, tc);
+ break;
+ }
+ PN_MOVE_NODE(pn, pn2);
+ }
+ if (!pn2 || (pn->pn_type == TOK_SEMI && !pn->pn_kid)) {
+ /*
+ * False condition and no else, or an empty then-statement was
+ * moved up over pn. Either way, make pn an empty block (not an
+ * empty statement, which does not decompile, even when labeled).
+ * NB: pn must be a TOK_IF as TOK_HOOK can never have a null kid
+ * or an empty statement for a child.
+ */
+ pn->pn_type = TOK_LC;
+ pn->pn_arity = PN_LIST;
+ PN_INIT_LIST(pn);
+ }
+ RecycleTree(pn2, tc);
+ if (pn3 && pn3 != pn2)
+ RecycleTree(pn3, tc);
+ break;
+
+ case TOK_OR:
+ case TOK_AND:
+ if (inCond) {
+ if (pn->pn_arity == PN_LIST) {
+ JSParseNode **pnp = &pn->pn_head;
+ JS_ASSERT(*pnp == pn1);
+ do {
+ int cond = Boolish(pn1);
+ if (cond == (pn->pn_type == TOK_OR)) {
+ for (pn2 = pn1->pn_next; pn2; pn2 = pn3) {
+ pn3 = pn2->pn_next;
+ RecycleTree(pn2, tc);
+ --pn->pn_count;
+ }
+ pn1->pn_next = NULL;
+ break;
+ }
+ if (cond != -1) {
+ JS_ASSERT(cond == (pn->pn_type == TOK_AND));
+ if (pn->pn_count == 1)
+ break;
+ *pnp = pn1->pn_next;
+ RecycleTree(pn1, tc);
+ --pn->pn_count;
+ } else {
+ pnp = &pn1->pn_next;
+ }
+ } while ((pn1 = *pnp) != NULL);
+
+ // We may have to change arity from LIST to BINARY.
+ pn1 = pn->pn_head;
+ if (pn->pn_count == 2) {
+ pn2 = pn1->pn_next;
+ pn1->pn_next = NULL;
+ JS_ASSERT(!pn2->pn_next);
+ pn->pn_arity = PN_BINARY;
+ pn->pn_left = pn1;
+ pn->pn_right = pn2;
+ } else if (pn->pn_count == 1) {
+ PN_MOVE_NODE(pn, pn1);
+ RecycleTree(pn1, tc);
+ }
+ } else {
+ int cond = Boolish(pn1);
+ if (cond == (pn->pn_type == TOK_OR)) {
+ RecycleTree(pn2, tc);
+ PN_MOVE_NODE(pn, pn1);
+ } else if (cond != -1) {
+ JS_ASSERT(cond == (pn->pn_type == TOK_AND));
+ RecycleTree(pn1, tc);
+ PN_MOVE_NODE(pn, pn2);
+ }
+ }
+ }
+ break;
+
+ case TOK_ASSIGN:
+ /*
+ * Compound operators such as *= should be subject to folding, in case
+ * the left-hand side is constant, and so that the decompiler produces
+ * the same string that you get from decompiling a script or function
+ * compiled from that same string. As with +, += is special.
+ */
+ if (pn->pn_op == JSOP_NOP)
+ break;
+ if (pn->pn_op != JSOP_ADD)
+ goto do_binary_op;
+ /* FALL THROUGH */
+
+ case TOK_PLUS:
+ if (pn->pn_arity == PN_LIST) {
+ size_t length, length2;
+ jschar *chars;
+ JSString *str, *str2;
+
+ /*
+ * Any string literal term with all others number or string means
+ * this is a concatenation. If any term is not a string or number
+ * literal, we can't fold.
+ */
+ JS_ASSERT(pn->pn_count > 2);
+ if (pn->pn_extra & PNX_CANTFOLD)
+ return JS_TRUE;
+ if (pn->pn_extra != PNX_STRCAT)
+ goto do_binary_op;
+
+ /* Ok, we're concatenating: convert non-string constant operands. */
+ length = 0;
+ for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
+ if (!FoldType(cx, pn2, TOK_STRING))
+ return JS_FALSE;
+ /* XXX fold only if all operands convert to string */
+ if (pn2->pn_type != TOK_STRING)
+ return JS_TRUE;
+ length += JSFLATSTR_LENGTH(ATOM_TO_STRING(pn2->pn_atom));
+ }
+
+ /* Allocate a new buffer and string descriptor for the result. */
+ chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+
+ /* Fill the buffer, advancing chars and recycling kids as we go. */
+ for (pn2 = pn1; pn2; pn2 = RecycleTree(pn2, tc)) {
+ str2 = ATOM_TO_STRING(pn2->pn_atom);
+ length2 = JSFLATSTR_LENGTH(str2);
+ js_strncpy(chars, JSFLATSTR_CHARS(str2), length2);
+ chars += length2;
+ }
+ *chars = 0;
+
+ /* Atomize the result string and mutate pn to refer to it. */
+ pn->pn_atom = js_AtomizeString(cx, str, 0);
+ if (!pn->pn_atom)
+ return JS_FALSE;
+ pn->pn_type = TOK_STRING;
+ pn->pn_op = JSOP_STRING;
+ pn->pn_arity = PN_NULLARY;
+ break;
+ }
+
+ /* Handle a binary string concatenation. */
+ JS_ASSERT(pn->pn_arity == PN_BINARY);
+ if (pn1->pn_type == TOK_STRING || pn2->pn_type == TOK_STRING) {
+ JSString *left, *right, *str;
+
+ if (!FoldType(cx, (pn1->pn_type != TOK_STRING) ? pn1 : pn2,
+ TOK_STRING)) {
+ return JS_FALSE;
+ }
+ if (pn1->pn_type != TOK_STRING || pn2->pn_type != TOK_STRING)
+ return JS_TRUE;
+ left = ATOM_TO_STRING(pn1->pn_atom);
+ right = ATOM_TO_STRING(pn2->pn_atom);
+ str = js_ConcatStrings(cx, left, right);
+ if (!str)
+ return JS_FALSE;
+ pn->pn_atom = js_AtomizeString(cx, str, 0);
+ if (!pn->pn_atom)
+ return JS_FALSE;
+ pn->pn_type = TOK_STRING;
+ pn->pn_op = JSOP_STRING;
+ pn->pn_arity = PN_NULLARY;
+ RecycleTree(pn1, tc);
+ RecycleTree(pn2, tc);
+ break;
+ }
+
+ /* Can't concatenate string literals, let's try numbers. */
+ goto do_binary_op;
+
+ case TOK_STAR:
+ case TOK_SHOP:
+ case TOK_MINUS:
+ case TOK_DIVOP:
+ do_binary_op:
+ if (pn->pn_arity == PN_LIST) {
+ JS_ASSERT(pn->pn_count > 2);
+ for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
+ if (!FoldType(cx, pn2, TOK_NUMBER))
+ return JS_FALSE;
+ }
+ for (pn2 = pn1; pn2; pn2 = pn2->pn_next) {
+ /* XXX fold only if all operands convert to number */
+ if (pn2->pn_type != TOK_NUMBER)
+ break;
+ }
+ if (!pn2) {
+ JSOp op = PN_OP(pn);
+
+ pn2 = pn1->pn_next;
+ pn3 = pn2->pn_next;
+ if (!FoldBinaryNumeric(cx, op, pn1, pn2, pn, tc))
+ return JS_FALSE;
+ while ((pn2 = pn3) != NULL) {
+ pn3 = pn2->pn_next;
+ if (!FoldBinaryNumeric(cx, op, pn, pn2, pn, tc))
+ return JS_FALSE;
+ }
+ }
+ } else {
+ JS_ASSERT(pn->pn_arity == PN_BINARY);
+ if (!FoldType(cx, pn1, TOK_NUMBER) ||
+ !FoldType(cx, pn2, TOK_NUMBER)) {
+ return JS_FALSE;
+ }
+ if (pn1->pn_type == TOK_NUMBER && pn2->pn_type == TOK_NUMBER) {
+ if (!FoldBinaryNumeric(cx, PN_OP(pn), pn1, pn2, pn, tc))
+ return JS_FALSE;
+ }
+ }
+ break;
+
+ case TOK_UNARYOP:
+ while (pn1->pn_type == TOK_RP)
+ pn1 = pn1->pn_kid;
+ if (pn1->pn_type == TOK_NUMBER) {
+ jsdouble d;
+
+ /* Operate on one numeric constant. */
+ d = pn1->pn_dval;
+ switch (pn->pn_op) {
+ case JSOP_BITNOT:
+ d = ~js_DoubleToECMAInt32(d);
+ break;
+
+ case JSOP_NEG:
+#ifdef HPUX
+ /*
+ * Negation of a zero doesn't produce a negative
+ * zero on HPUX. Perform the operation by bit
+ * twiddling.
+ */
+ JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;
+#else
+ d = -d;
+#endif
+ break;
+
+ case JSOP_POS:
+ break;
+
+ case JSOP_NOT:
+ pn->pn_type = TOK_PRIMARY;
+ pn->pn_op = (d == 0 || JSDOUBLE_IS_NaN(d)) ? JSOP_TRUE : JSOP_FALSE;
+ pn->pn_arity = PN_NULLARY;
+ /* FALL THROUGH */
+
+ default:
+ /* Return early to dodge the common TOK_NUMBER code. */
+ return JS_TRUE;
+ }
+ pn->pn_type = TOK_NUMBER;
+ pn->pn_op = JSOP_DOUBLE;
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_dval = d;
+ RecycleTree(pn1, tc);
+ } else if (pn1->pn_type == TOK_PRIMARY) {
+ if (pn->pn_op == JSOP_NOT &&
+ (pn1->pn_op == JSOP_TRUE ||
+ pn1->pn_op == JSOP_FALSE)) {
+ PN_MOVE_NODE(pn, pn1);
+ pn->pn_op = (pn->pn_op == JSOP_TRUE) ? JSOP_FALSE : JSOP_TRUE;
+ RecycleTree(pn1, tc);
+ }
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case TOK_XMLELEM:
+ case TOK_XMLLIST:
+ case TOK_XMLPTAGC:
+ case TOK_XMLSTAGO:
+ case TOK_XMLETAGO:
+ case TOK_XMLNAME:
+ if (pn->pn_arity == PN_LIST) {
+ JS_ASSERT(pn->pn_type == TOK_XMLLIST || pn->pn_count != 0);
+ if (!FoldXMLConstants(cx, pn, tc))
+ return JS_FALSE;
+ }
+ break;
+
+ case TOK_AT:
+ if (pn1->pn_type == TOK_XMLNAME) {
+ jsval v;
+ JSParsedObjectBox *xmlpob;
+
+ v = ATOM_KEY(pn1->pn_atom);
+ if (!js_ToAttributeName(cx, &v))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+
+ xmlpob = js_NewParsedObjectBox(cx, tc->parseContext,
+ JSVAL_TO_OBJECT(v));
+ if (!xmlpob)
+ return JS_FALSE;
+
+ pn->pn_type = TOK_XMLNAME;
+ pn->pn_op = JSOP_OBJECT;
+ pn->pn_arity = PN_NULLARY;
+ pn->pn_pob = xmlpob;
+ RecycleTree(pn1, tc);
+ }
+ break;
+#endif /* JS_HAS_XML_SUPPORT */
+
+ default:;
+ }
+
+ if (inCond) {
+ int cond = Boolish(pn);
+ if (cond >= 0) {
+ if (pn->pn_arity == PN_LIST) {
+ pn2 = pn->pn_head;
+ do {
+ pn3 = pn2->pn_next;
+ RecycleTree(pn2, tc);
+ } while ((pn2 = pn3) != NULL);
+ }
+ pn->pn_type = TOK_PRIMARY;
+ pn->pn_op = cond ? JSOP_TRUE : JSOP_FALSE;
+ pn->pn_arity = PN_NULLARY;
+ }
+ }
+
+ return JS_TRUE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsparse.h b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.h
new file mode 100644
index 0000000..90499db
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsparse.h
@@ -0,0 +1,508 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsparse_h___
+#define jsparse_h___
+/*
+ * JS parser definitions.
+ */
+#include "jsversion.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+#include "jsscan.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Parsing builds a tree of nodes that directs code generation. This tree is
+ * not a concrete syntax tree in all respects (for example, || and && are left
+ * associative, but (A && B && C) translates into the right-associated tree
+ * <A && <B && C>> so that code generation can emit a left-associative branch
+ * around <B && C> when A is false). Nodes are labeled by token type, with a
+ * JSOp secondary label when needed:
+ *
+ * Label Variant Members
+ * ----- ------- -------
+ * <Definitions>
+ * TOK_FUNCTION func pn_funpob: JSParsedObjectBox holding function
+ * object containing arg and var properties. We
+ * create the function object at parse (not emit)
+ * time to specialize arg and var bytecodes early.
+ * pn_body: TOK_LC node for function body statements
+ * pn_flags: TCF_FUN_* flags (see jsemit.h) collected
+ * while parsing the function's body
+ *
+ * <Statements>
+ * TOK_LC list pn_head: list of pn_count statements
+ * TOK_IF ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else or null
+ * TOK_SWITCH binary pn_left: discriminant
+ * pn_right: list of TOK_CASE nodes, with at most one
+ * TOK_DEFAULT node, or if there are let bindings
+ * in the top level of the switch body's cases, a
+ * TOK_LEXICALSCOPE node that contains the list of
+ * TOK_CASE nodes.
+ * TOK_CASE, binary pn_left: case expr or null if TOK_DEFAULT
+ * TOK_DEFAULT pn_right: TOK_LC node for this case's statements
+ * pn_val: constant value if lookup or table switch
+ * TOK_WHILE binary pn_left: cond, pn_right: body
+ * TOK_DO binary pn_left: body, pn_right: cond
+ * TOK_FOR binary pn_left: either
+ * for/in loop: a binary TOK_IN node with
+ * pn_left: TOK_VAR or TOK_NAME to left of 'in'
+ * if TOK_VAR, its pn_extra may have PNX_POPVAR
+ * and PNX_FORINVAR bits set
+ * pn_right: object expr to right of 'in'
+ * for(;;) loop: a ternary TOK_RESERVED node with
+ * pn_kid1: init expr before first ';'
+ * pn_kid2: cond expr before second ';'
+ * pn_kid3: update expr after second ';'
+ * any kid may be null
+ * pn_right: body
+ * TOK_THROW unary pn_op: JSOP_THROW, pn_kid: exception
+ * TOK_TRY ternary pn_kid1: try block
+ * pn_kid2: null or TOK_RESERVED list of
+ * TOK_LEXICALSCOPE nodes, each with pn_expr pointing
+ * to a TOK_CATCH node
+ * pn_kid3: null or finally block
+ * TOK_CATCH ternary pn_kid1: TOK_NAME, TOK_RB, or TOK_RC catch var node
+ * (TOK_RB or TOK_RC if destructuring)
+ * pn_kid2: null or the catch guard expression
+ * pn_kid3: catch block statements
+ * TOK_BREAK name pn_atom: label or null
+ * TOK_CONTINUE name pn_atom: label or null
+ * TOK_WITH binary pn_left: head expr, pn_right: body
+ * TOK_VAR list pn_head: list of pn_count TOK_NAME nodes
+ * each name node has
+ * pn_atom: variable name
+ * pn_expr: initializer or null
+ * TOK_RETURN unary pn_kid: return expr or null
+ * TOK_SEMI unary pn_kid: expr or null statement
+ * TOK_COLON name pn_atom: label, pn_expr: labeled statement
+ *
+ * <Expressions>
+ * All left-associated binary trees of the same type are optimized into lists
+ * to avoid recursion when processing expression chains.
+ * TOK_COMMA list pn_head: list of pn_count comma-separated exprs
+ * TOK_ASSIGN binary pn_left: lvalue, pn_right: rvalue
+ * pn_op: JSOP_ADD for +=, etc.
+ * TOK_HOOK ternary pn_kid1: cond, pn_kid2: then, pn_kid3: else
+ * TOK_OR binary pn_left: first in || chain, pn_right: rest of chain
+ * TOK_AND binary pn_left: first in && chain, pn_right: rest of chain
+ * TOK_BITOR binary pn_left: left-assoc | expr, pn_right: ^ expr
+ * TOK_BITXOR binary pn_left: left-assoc ^ expr, pn_right: & expr
+ * TOK_BITAND binary pn_left: left-assoc & expr, pn_right: EQ expr
+ * TOK_EQOP binary pn_left: left-assoc EQ expr, pn_right: REL expr
+ * pn_op: JSOP_EQ, JSOP_NE,
+ * JSOP_STRICTEQ, JSOP_STRICTNE
+ * TOK_RELOP binary pn_left: left-assoc REL expr, pn_right: SH expr
+ * pn_op: JSOP_LT, JSOP_LE, JSOP_GT, JSOP_GE
+ * TOK_SHOP binary pn_left: left-assoc SH expr, pn_right: ADD expr
+ * pn_op: JSOP_LSH, JSOP_RSH, JSOP_URSH
+ * TOK_PLUS, binary pn_left: left-assoc ADD expr, pn_right: MUL expr
+ * pn_extra: if a left-associated binary TOK_PLUS
+ * tree has been flattened into a list (see above
+ * under <Expressions>), pn_extra will contain
+ * PNX_STRCAT if at least one list element is a
+ * string literal (TOK_STRING); if such a list has
+ * any non-string, non-number term, pn_extra will
+ * contain PNX_CANTFOLD.
+ * pn_
+ * TOK_MINUS pn_op: JSOP_ADD, JSOP_SUB
+ * TOK_STAR, binary pn_left: left-assoc MUL expr, pn_right: UNARY expr
+ * TOK_DIVOP pn_op: JSOP_MUL, JSOP_DIV, JSOP_MOD
+ * TOK_UNARYOP unary pn_kid: UNARY expr, pn_op: JSOP_NEG, JSOP_POS,
+ * JSOP_NOT, JSOP_BITNOT, JSOP_TYPEOF, JSOP_VOID
+ * TOK_INC, unary pn_kid: MEMBER expr
+ * TOK_DEC
+ * TOK_NEW list pn_head: list of ctor, arg1, arg2, ... argN
+ * pn_count: 1 + N (where N is number of args)
+ * ctor is a MEMBER expr
+ * TOK_DELETE unary pn_kid: MEMBER expr
+ * TOK_DOT, name pn_expr: MEMBER expr to left of .
+ * TOK_DBLDOT pn_atom: name to right of .
+ * TOK_LB binary pn_left: MEMBER expr to left of [
+ * pn_right: expr between [ and ]
+ * TOK_LP list pn_head: list of call, arg1, arg2, ... argN
+ * pn_count: 1 + N (where N is number of args)
+ * call is a MEMBER expr naming a callable object
+ * TOK_RB list pn_head: list of pn_count array element exprs
+ * [,,] holes are represented by TOK_COMMA nodes
+ * #n=[...] produces TOK_DEFSHARP at head of list
+ * pn_extra: PN_ENDCOMMA if extra comma at end
+ * TOK_RC list pn_head: list of pn_count TOK_COLON nodes where
+ * each has pn_left: property id, pn_right: value
+ * #n={...} produces TOK_DEFSHARP at head of list
+ * var {x} = object destructuring shorthand shares
+ * PN_NAME node for x on left and right of TOK_COLON
+ * node in TOK_RC's list, has PNX_SHORTHAND flag
+ * TOK_DEFSHARP unary pn_num: jsint value of n in #n=
+ * pn_kid: null for #n=[...] and #n={...}, primary
+ * if #n=primary for function, paren, name, object
+ * literal expressions
+ * TOK_USESHARP nullary pn_num: jsint value of n in #n#
+ * TOK_RP unary pn_kid: parenthesized expression
+ * TOK_NAME, name pn_atom: name, string, or object atom
+ * TOK_STRING, pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT, or
+ * JSOP_REGEXP
+ * TOK_REGEXP If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
+ * with pn_slot >= 0 and pn_const telling const-ness
+ * TOK_NUMBER dval pn_dval: double value of numeric literal
+ * TOK_PRIMARY nullary pn_op: JSOp bytecode
+ *
+ * <E4X node descriptions>
+ * TOK_ANYNAME nullary pn_op: JSOP_ANYNAME
+ * pn_atom: cx->runtime->atomState.starAtom
+ * TOK_AT unary pn_op: JSOP_TOATTRNAME; pn_kid attribute id/expr
+ * TOK_DBLCOLON binary pn_op: JSOP_QNAME
+ * pn_left: TOK_ANYNAME or TOK_NAME node
+ * pn_right: TOK_STRING "*" node, or expr within []
+ * name pn_op: JSOP_QNAMECONST
+ * pn_expr: TOK_ANYNAME or TOK_NAME left operand
+ * pn_atom: name on right of ::
+ * TOK_XMLELEM list XML element node
+ * pn_head: start tag, content1, ... contentN, end tag
+ * pn_count: 2 + N where N is number of content nodes
+ * N may be > x.length() if {expr} embedded
+ * TOK_XMLLIST list XML list node
+ * pn_head: content1, ... contentN
+ * TOK_XMLSTAGO, list XML start, end, and point tag contents
+ * TOK_XMLETAGC, pn_head: tag name or {expr}, ... XML attrs ...
+ * TOK_XMLPTAGO
+ * TOK_XMLNAME nullary pn_atom: XML name, with no {expr} embedded
+ * TOK_XMLNAME list pn_head: tag name or {expr}, ... name or {expr}
+ * TOK_XMLATTR, nullary pn_atom: attribute value string; pn_op: JSOP_STRING
+ * TOK_XMLCDATA,
+ * TOK_XMLCOMMENT
+ * TOK_XMLPI nullary pn_atom: XML processing instruction target
+ * pn_atom2: XML PI content, or null if no content
+ * TOK_XMLTEXT nullary pn_atom: marked-up text, or null if empty string
+ * TOK_LC unary {expr} in XML tag or content; pn_kid is expr
+ *
+ * So an XML tag with no {expr} and three attributes is a list with the form:
+ *
+ * (tagname attrname1 attrvalue1 attrname2 attrvalue2 attrname2 attrvalue3)
+ *
+ * An XML tag with embedded expressions like so:
+ *
+ * <name1{expr1} name2{expr2}name3={expr3}>
+ *
+ * would have the form:
+ *
+ * ((name1 {expr1}) (name2 {expr2} name3) {expr3})
+ *
+ * where () bracket a list with elements separated by spaces, and {expr} is a
+ * TOK_LC unary node with expr as its kid.
+ *
+ * Thus, the attribute name/value pairs occupy successive odd and even list
+ * locations, where pn_head is the TOK_XMLNAME node at list location 0. The
+ * parser builds the same sort of structures for elements:
+ *
+ * <a x={x}>Hi there!<b y={y}>How are you?</b><answer>{x + y}</answer></a>
+ *
+ * translates to:
+ *
+ * ((a x {x}) 'Hi there!' ((b y {y}) 'How are you?') ((answer) {x + y}))
+ *
+ * <Non-E4X node descriptions, continued>
+ *
+ * Label Variant Members
+ * ----- ------- -------
+ * TOK_LEXICALSCOPE name pn_op: JSOP_LEAVEBLOCK or JSOP_LEAVEBLOCKEXPR
+ * pn_pob: block object
+ * pn_expr: block body
+ * TOK_ARRAYCOMP list pn_head: list of pn_count (1 or 2) elements
+ * if pn_count is 2, first element is #n=[...]
+ * last element is block enclosing for loop(s)
+ * and optionally if-guarded TOK_ARRAYPUSH
+ * pn_extra: stack slot, used during code gen
+ * TOK_ARRAYPUSH unary pn_op: JSOP_ARRAYCOMP
+ * pn_kid: array comprehension expression
+ */
+typedef enum JSParseNodeArity {
+ PN_FUNC = -3,
+ PN_LIST = -2,
+ PN_TERNARY = 3,
+ PN_BINARY = 2,
+ PN_UNARY = 1,
+ PN_NAME = -1,
+ PN_NULLARY = 0
+} JSParseNodeArity;
+
+struct JSParseNode {
+ uint16 pn_type;
+ uint8 pn_op;
+ int8 pn_arity;
+ JSTokenPos pn_pos;
+ ptrdiff_t pn_offset; /* first generated bytecode offset */
+ union {
+ struct { /* TOK_FUNCTION node */
+ JSParsedObjectBox *funpob; /* function object */
+ JSParseNode *body; /* TOK_LC list of statements */
+ uint16 flags; /* accumulated tree context flags */
+ uint32 index; /* emitter's index */
+ } func;
+ struct { /* list of next-linked nodes */
+ JSParseNode *head; /* first node in list */
+ JSParseNode **tail; /* ptr to ptr to last node in list */
+ uint32 count; /* number of nodes in list */
+ uint32 extra; /* extra flags, see below */
+ } list;
+ struct { /* ternary: if, for(;;), ?: */
+ JSParseNode *kid1; /* condition, discriminant, etc. */
+ JSParseNode *kid2; /* then-part, case list, etc. */
+ JSParseNode *kid3; /* else-part, default case, etc. */
+ } ternary;
+ struct { /* two kids if binary */
+ JSParseNode *left;
+ JSParseNode *right;
+ jsval val; /* switch case value */
+ uintN iflags; /* JSITER_* flags for TOK_FOR node */
+ } binary;
+ struct { /* one kid if unary */
+ JSParseNode *kid;
+ jsint num; /* -1 or sharp variable number */
+ JSBool hidden; /* hidden genexp-induced JSOP_YIELD */
+ } unary;
+ struct { /* name, labeled statement, etc. */
+ JSAtom *atom; /* name or label atom, null if slot */
+ JSParseNode *expr; /* object or initializer */
+ jsint slot; /* -1 or arg or local var slot */
+ JSBool isconst; /* true for const names */
+ } name;
+ struct { /* lexical scope. */
+ JSParsedObjectBox *pob; /* block object */
+ JSParseNode *expr; /* object or initializer */
+ jsint slot; /* -1 or arg or local var slot */
+ } lexical;
+ struct {
+ JSAtom *atom; /* first atom in pair */
+ JSAtom *atom2; /* second atom in pair or null */
+ } apair;
+ struct { /* object literal */
+ JSParsedObjectBox *pob;
+ } object;
+ jsdouble dval; /* aligned numeric literal value */
+ } pn_u;
+ JSParseNode *pn_next; /* to align dval and pn_u on RISCs */
+};
+
+#define pn_funpob pn_u.func.funpob
+#define pn_body pn_u.func.body
+#define pn_flags pn_u.func.flags
+#define pn_index pn_u.func.index
+#define pn_head pn_u.list.head
+#define pn_tail pn_u.list.tail
+#define pn_count pn_u.list.count
+#define pn_extra pn_u.list.extra
+#define pn_kid1 pn_u.ternary.kid1
+#define pn_kid2 pn_u.ternary.kid2
+#define pn_kid3 pn_u.ternary.kid3
+#define pn_left pn_u.binary.left
+#define pn_right pn_u.binary.right
+#define pn_val pn_u.binary.val
+#define pn_iflags pn_u.binary.iflags
+#define pn_kid pn_u.unary.kid
+#define pn_num pn_u.unary.num
+#define pn_hidden pn_u.unary.hidden
+#define pn_atom pn_u.name.atom
+#define pn_expr pn_u.name.expr
+#define pn_slot pn_u.name.slot
+#define pn_const pn_u.name.isconst
+#define pn_dval pn_u.dval
+#define pn_atom2 pn_u.apair.atom2
+#define pn_pob pn_u.object.pob
+
+/* PN_LIST pn_extra flags. */
+#define PNX_STRCAT 0x01 /* TOK_PLUS list has string term */
+#define PNX_CANTFOLD 0x02 /* TOK_PLUS list has unfoldable term */
+#define PNX_POPVAR 0x04 /* TOK_VAR last result needs popping */
+#define PNX_FORINVAR 0x08 /* TOK_VAR is left kid of TOK_IN node,
+ which is left kid of TOK_FOR */
+#define PNX_ENDCOMMA 0x10 /* array literal has comma at end */
+#define PNX_XMLROOT 0x20 /* top-most node in XML literal tree */
+#define PNX_GROUPINIT 0x40 /* var [a, b] = [c, d]; unit list */
+#define PNX_NEEDBRACES 0x80 /* braces necessary due to closure */
+#define PNX_FUNCDEFS 0x100 /* contains top-level function
+ statements */
+#define PNX_SHORTHAND 0x200 /* shorthand syntax used, at present
+ object destructuring ({x,y}) only */
+
+/*
+ * Move pn2 into pn, preserving pn->pn_pos and pn->pn_offset and handing off
+ * any kids in pn2->pn_u, by clearing pn2.
+ */
+#define PN_MOVE_NODE(pn, pn2) \
+ JS_BEGIN_MACRO \
+ (pn)->pn_type = (pn2)->pn_type; \
+ (pn)->pn_op = (pn2)->pn_op; \
+ (pn)->pn_arity = (pn2)->pn_arity; \
+ (pn)->pn_u = (pn2)->pn_u; \
+ PN_CLEAR_NODE(pn2); \
+ JS_END_MACRO
+
+#define PN_CLEAR_NODE(pn) \
+ JS_BEGIN_MACRO \
+ (pn)->pn_type = TOK_EOF; \
+ (pn)->pn_op = JSOP_NOP; \
+ (pn)->pn_arity = PN_NULLARY; \
+ JS_END_MACRO
+
+/* True if pn is a parsenode representing a literal constant. */
+#define PN_IS_CONSTANT(pn) \
+ ((pn)->pn_type == TOK_NUMBER || \
+ (pn)->pn_type == TOK_STRING || \
+ ((pn)->pn_type == TOK_PRIMARY && (pn)->pn_op != JSOP_THIS))
+
+#define PN_OP(pn) ((JSOp)(pn)->pn_op)
+#define PN_TYPE(pn) ((JSTokenType)(pn)->pn_type)
+
+/*
+ * Compute a pointer to the last JSParseNode element in a singly-linked list.
+ * NB: list must be non-empty for correct PN_LAST usage!
+ */
+#define PN_LAST(list) \
+ ((JSParseNode *)((char *)(list)->pn_tail - offsetof(JSParseNode, pn_next)))
+
+#define PN_INIT_LIST(list) \
+ JS_BEGIN_MACRO \
+ (list)->pn_head = NULL; \
+ (list)->pn_tail = &(list)->pn_head; \
+ (list)->pn_count = (list)->pn_extra = 0; \
+ JS_END_MACRO
+
+#define PN_INIT_LIST_1(list, pn) \
+ JS_BEGIN_MACRO \
+ (list)->pn_head = (pn); \
+ (list)->pn_tail = &(pn)->pn_next; \
+ (list)->pn_count = 1; \
+ (list)->pn_extra = 0; \
+ JS_END_MACRO
+
+#define PN_APPEND(list, pn) \
+ JS_BEGIN_MACRO \
+ *(list)->pn_tail = (pn); \
+ (list)->pn_tail = &(pn)->pn_next; \
+ (list)->pn_count++; \
+ JS_END_MACRO
+
+struct JSParsedObjectBox {
+ JSParsedObjectBox *traceLink;
+ JSParsedObjectBox *emitLink;
+ JSObject *object;
+};
+
+struct JSParseContext {
+ JSTokenStream tokenStream;
+ void *tempPoolMark; /* initial JSContext.tempPool mark */
+ JSPrincipals *principals; /* principals associated with source */
+ JSStackFrame *callerFrame; /* scripted caller frame for eval and
+ debug scripts */
+ JSParseNode *nodeList; /* list of recyclable parse-node
+ structs */
+ JSParsedObjectBox *traceListHead; /* list of parsed object for GC
+ tracing */
+ JSTempValueRooter tempRoot; /* root to trace traceListHead */
+};
+
+/*
+ * Convenience macro to access JSParseContext.tokenStream as a pointer.
+ */
+#define TS(pc) (&(pc)->tokenStream)
+
+/*
+ * Parse a top-level JS script.
+ */
+extern JSParseNode *
+js_ParseScript(JSContext *cx, JSObject *chain, JSParseContext *pc);
+
+extern JSScript *
+js_CompileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *callerFrame,
+ JSPrincipals *principals, uint32 tcflags,
+ const jschar *chars, size_t length,
+ FILE *file, const char *filename, uintN lineno);
+
+extern JSBool
+js_CompileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *principals,
+ const jschar *chars, size_t length,
+ const char *filename, uintN lineno);
+
+extern JSBool
+js_FoldConstants(JSContext *cx, JSParseNode *pn, JSTreeContext *tc,
+ bool inCond = false);
+
+#if JS_HAS_XML_SUPPORT
+JS_FRIEND_API(JSParseNode *)
+js_ParseXMLText(JSContext *cx, JSObject *chain, JSParseContext *pc,
+ JSBool allowList);
+#endif
+
+/*
+ * Initialize a parse context. All parameters after pc are passed to
+ * js_InitTokenStream.
+ *
+ * The parse context owns the arena pool "tops-of-stack" space above the
+ * current JSContext.tempPool mark. This means you cannot allocate from
+ * tempPool and save the pointer beyond the next js_FinishParseContext.
+ */
+extern JSBool
+js_InitParseContext(JSContext *cx, JSParseContext *pc, JSPrincipals *principals,
+ JSStackFrame *callerFrame,
+ const jschar *base, size_t length, FILE *fp,
+ const char *filename, uintN lineno);
+
+extern void
+js_FinishParseContext(JSContext *cx, JSParseContext *pc);
+
+extern void
+js_InitCompilePrincipals(JSContext *cx, JSParseContext *pc,
+ JSPrincipals *principals);
+
+/*
+ * Allocate a new parseed object node from cx->tempPool.
+ */
+extern JSParsedObjectBox *
+js_NewParsedObjectBox(JSContext *cx, JSParseContext *pc, JSObject *obj);
+
+extern void
+js_TraceParseContext(JSTracer *trc, JSParseContext *pc);
+
+JS_END_EXTERN_C
+
+#endif /* jsparse_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp
new file mode 100644
index 0000000..4285737
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.cpp
@@ -0,0 +1,1262 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+** Portable safe sprintf code.
+**
+** Author: Kipp E.B. Hickman
+*/
+#include "jsstddef.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "jsprf.h"
+#include "jslong.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jspubtd.h"
+#include "jsstr.h"
+
+/*
+** Note: on some platforms va_list is defined as an array,
+** and requires array notation.
+*/
+#ifdef HAVE_VA_COPY
+#define VARARGS_ASSIGN(foo, bar) VA_COPY(foo,bar)
+#elif defined(HAVE_VA_LIST_AS_ARRAY)
+#define VARARGS_ASSIGN(foo, bar) foo[0] = bar[0]
+#else
+#define VARARGS_ASSIGN(foo, bar) (foo) = (bar)
+#endif
+
+/*
+** WARNING: This code may *NOT* call JS_LOG (because JS_LOG calls it)
+*/
+
+/*
+** XXX This needs to be internationalized!
+*/
+
+typedef struct SprintfStateStr SprintfState;
+
+struct SprintfStateStr {
+ int (*stuff)(SprintfState *ss, const char *sp, JSUint32 len);
+
+ char *base;
+ char *cur;
+ JSUint32 maxlen;
+
+ int (*func)(void *arg, const char *sp, JSUint32 len);
+ void *arg;
+};
+
+/*
+** Numbered Arguement State
+*/
+struct NumArgState{
+ int type; /* type of the current ap */
+ va_list ap; /* point to the corresponding position on ap */
+};
+
+#define NAS_DEFAULT_NUM 20 /* default number of NumberedArgumentState array */
+
+
+#define TYPE_INT16 0
+#define TYPE_UINT16 1
+#define TYPE_INTN 2
+#define TYPE_UINTN 3
+#define TYPE_INT32 4
+#define TYPE_UINT32 5
+#define TYPE_INT64 6
+#define TYPE_UINT64 7
+#define TYPE_STRING 8
+#define TYPE_DOUBLE 9
+#define TYPE_INTSTR 10
+#define TYPE_WSTRING 11
+#define TYPE_UNKNOWN 20
+
+#define FLAG_LEFT 0x1
+#define FLAG_SIGNED 0x2
+#define FLAG_SPACED 0x4
+#define FLAG_ZEROS 0x8
+#define FLAG_NEG 0x10
+
+/*
+** Fill into the buffer using the data in src
+*/
+static int fill2(SprintfState *ss, const char *src, int srclen, int width,
+ int flags)
+{
+ char space = ' ';
+ int rv;
+
+ width -= srclen;
+ if ((width > 0) && ((flags & FLAG_LEFT) == 0)) { /* Right adjusting */
+ if (flags & FLAG_ZEROS) {
+ space = '0';
+ }
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Copy out the source data */
+ rv = (*ss->stuff)(ss, src, (JSUint32)srclen);
+ if (rv < 0) {
+ return rv;
+ }
+
+ if ((width > 0) && ((flags & FLAG_LEFT) != 0)) { /* Left adjusting */
+ while (--width >= 0) {
+ rv = (*ss->stuff)(ss, &space, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Fill a number. The order is: optional-sign zero-filling conversion-digits
+*/
+static int fill_n(SprintfState *ss, const char *src, int srclen, int width,
+ int prec, int type, int flags)
+{
+ int zerowidth = 0;
+ int precwidth = 0;
+ int signwidth = 0;
+ int leftspaces = 0;
+ int rightspaces = 0;
+ int cvtwidth;
+ int rv;
+ char sign;
+
+ if ((type & 1) == 0) {
+ if (flags & FLAG_NEG) {
+ sign = '-';
+ signwidth = 1;
+ } else if (flags & FLAG_SIGNED) {
+ sign = '+';
+ signwidth = 1;
+ } else if (flags & FLAG_SPACED) {
+ sign = ' ';
+ signwidth = 1;
+ }
+ }
+ cvtwidth = signwidth + srclen;
+
+ if (prec > 0) {
+ if (prec > srclen) {
+ precwidth = prec - srclen; /* Need zero filling */
+ cvtwidth += precwidth;
+ }
+ }
+
+ if ((flags & FLAG_ZEROS) && (prec < 0)) {
+ if (width > cvtwidth) {
+ zerowidth = width - cvtwidth; /* Zero filling */
+ cvtwidth += zerowidth;
+ }
+ }
+
+ if (flags & FLAG_LEFT) {
+ if (width > cvtwidth) {
+ /* Space filling on the right (i.e. left adjusting) */
+ rightspaces = width - cvtwidth;
+ }
+ } else {
+ if (width > cvtwidth) {
+ /* Space filling on the left (i.e. right adjusting) */
+ leftspaces = width - cvtwidth;
+ }
+ }
+ while (--leftspaces >= 0) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ if (signwidth) {
+ rv = (*ss->stuff)(ss, &sign, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--precwidth >= 0) {
+ rv = (*ss->stuff)(ss, "0", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ while (--zerowidth >= 0) {
+ rv = (*ss->stuff)(ss, "0", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ rv = (*ss->stuff)(ss, src, (JSUint32)srclen);
+ if (rv < 0) {
+ return rv;
+ }
+ while (--rightspaces >= 0) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*
+** Convert a long into its printable form
+*/
+static int cvt_l(SprintfState *ss, long num, int width, int prec, int radix,
+ int type, int flags, const char *hexp)
+{
+ char cvtbuf[100];
+ char *cvt;
+ int digits;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (num == 0)) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ cvt = cvtbuf + sizeof(cvtbuf);
+ digits = 0;
+ while (num) {
+ int digit = (((unsigned long)num) % radix) & 0xF;
+ *--cvt = hexp[digit];
+ digits++;
+ num = (long)(((unsigned long)num) / radix);
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a 64-bit integer into its printable form
+*/
+static int cvt_ll(SprintfState *ss, JSInt64 num, int width, int prec, int radix,
+ int type, int flags, const char *hexp)
+{
+ char cvtbuf[100];
+ char *cvt;
+ int digits;
+ JSInt64 rad;
+
+ /* according to the man page this needs to happen */
+ if ((prec == 0) && (JSLL_IS_ZERO(num))) {
+ return 0;
+ }
+
+ /*
+ ** Converting decimal is a little tricky. In the unsigned case we
+ ** need to stop when we hit 10 digits. In the signed case, we can
+ ** stop when the number is zero.
+ */
+ JSLL_I2L(rad, radix);
+ cvt = cvtbuf + sizeof(cvtbuf);
+ digits = 0;
+ while (!JSLL_IS_ZERO(num)) {
+ JSInt32 digit;
+ JSInt64 quot, rem;
+ JSLL_UDIVMOD(&quot, &rem, num, rad);
+ JSLL_L2I(digit, rem);
+ *--cvt = hexp[digit & 0xf];
+ digits++;
+ num = quot;
+ }
+ if (digits == 0) {
+ *--cvt = '0';
+ digits++;
+ }
+
+ /*
+ ** Now that we have the number converted without its sign, deal with
+ ** the sign and zero padding.
+ */
+ return fill_n(ss, cvt, digits, width, prec, type, flags);
+}
+
+/*
+** Convert a double precision floating point number into its printable
+** form.
+**
+** XXX stop using sprintf to convert floating point
+*/
+static int cvt_f(SprintfState *ss, double d, const char *fmt0, const char *fmt1)
+{
+ char fin[20];
+ char fout[300];
+ int amount = fmt1 - fmt0;
+
+ JS_ASSERT((amount > 0) && (amount < (int)sizeof(fin)));
+ if (amount >= (int)sizeof(fin)) {
+ /* Totally bogus % command to sprintf. Just ignore it */
+ return 0;
+ }
+ memcpy(fin, fmt0, (size_t)amount);
+ fin[amount] = 0;
+
+ /* Convert floating point using the native sprintf code */
+#ifdef DEBUG
+ {
+ const char *p = fin;
+ while (*p) {
+ JS_ASSERT(*p != 'L');
+ p++;
+ }
+ }
+#endif
+ sprintf(fout, fin, d);
+
+ /*
+ ** This assert will catch overflow's of fout, when building with
+ ** debugging on. At least this way we can track down the evil piece
+ ** of calling code and fix it!
+ */
+ JS_ASSERT(strlen(fout) < sizeof(fout));
+
+ return (*ss->stuff)(ss, fout, strlen(fout));
+}
+
+/*
+** Convert a string into its printable form. "width" is the output
+** width. "prec" is the maximum number of characters of "s" to output,
+** where -1 means until NUL.
+*/
+static int cvt_s(SprintfState *ss, const char *s, int width, int prec,
+ int flags)
+{
+ int slen;
+
+ if (prec == 0)
+ return 0;
+
+ /* Limit string length by precision value */
+ slen = s ? strlen(s) : 6;
+ if (prec > 0) {
+ if (prec < slen) {
+ slen = prec;
+ }
+ }
+
+ /* and away we go */
+ return fill2(ss, s ? s : "(null)", slen, width, flags);
+}
+
+static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
+ int flags)
+{
+ int result;
+ /*
+ * Supply NULL as the JSContext; errors are not reported,
+ * and malloc() is used to allocate the buffer buffer.
+ */
+ if (ws) {
+ int slen = js_strlen(ws);
+ char *s = js_DeflateString(NULL, ws, slen);
+ if (!s)
+ return -1; /* JSStuffFunc error indicator. */
+ result = cvt_s(ss, s, width, prec, flags);
+ free(s);
+ } else {
+ result = cvt_s(ss, NULL, width, prec, flags);
+ }
+ return result;
+}
+
+/*
+** BuildArgArray stands for Numbered Argument list Sprintf
+** for example,
+** fmp = "%4$i, %2$d, %3s, %1d";
+** the number must start from 1, and no gap among them
+*/
+
+static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArgState* nasArray )
+{
+ int number = 0, cn = 0, i;
+ const char *p;
+ char c;
+ struct NumArgState *nas;
+
+
+ /*
+ ** first pass:
+ ** detemine how many legal % I have got, then allocate space
+ */
+
+ p = fmt;
+ *rv = 0;
+ i = 0;
+ while( ( c = *p++ ) != 0 ){
+ if( c != '%' )
+ continue;
+ if( ( c = *p++ ) == '%' ) /* skip %% case */
+ continue;
+
+ while( c != 0 ){
+ if( c > '9' || c < '0' ){
+ if( c == '$' ){ /* numbered argument csae */
+ if( i > 0 ){
+ *rv = -1;
+ return NULL;
+ }
+ number++;
+ } else { /* non-numbered argument case */
+ if( number > 0 ){
+ *rv = -1;
+ return NULL;
+ }
+ i = 1;
+ }
+ break;
+ }
+
+ c = *p++;
+ }
+ }
+
+ if( number == 0 ){
+ return NULL;
+ }
+
+
+ if( number > NAS_DEFAULT_NUM ){
+ nas = (struct NumArgState*)malloc( number * sizeof( struct NumArgState ) );
+ if( !nas ){
+ *rv = -1;
+ return NULL;
+ }
+ } else {
+ nas = nasArray;
+ }
+
+ for( i = 0; i < number; i++ ){
+ nas[i].type = TYPE_UNKNOWN;
+ }
+
+
+ /*
+ ** second pass:
+ ** set nas[].type
+ */
+
+ p = fmt;
+ while( ( c = *p++ ) != 0 ){
+ if( c != '%' ) continue;
+ c = *p++;
+ if( c == '%' ) continue;
+
+ cn = 0;
+ while( c && c != '$' ){ /* should improve error check later */
+ cn = cn*10 + c - '0';
+ c = *p++;
+ }
+
+ if( !c || cn < 1 || cn > number ){
+ *rv = -1;
+ break;
+ }
+
+ /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */
+ cn--;
+ if( nas[cn].type != TYPE_UNKNOWN )
+ continue;
+
+ c = *p++;
+
+ /* width */
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ }
+
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ c = *p++;
+ if (c == '*') {
+ /* not supported feature, for the argument is not numbered */
+ *rv = -1;
+ break;
+ }
+
+ while ((c >= '0') && (c <= '9')) {
+ c = *p++;
+ }
+ }
+
+ /* size */
+ nas[cn].type = TYPE_INTN;
+ if (c == 'h') {
+ nas[cn].type = TYPE_INT16;
+ c = *p++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ } else if (c == 'l') {
+ nas[cn].type = TYPE_INT32;
+ c = *p++;
+ if (c == 'l') {
+ nas[cn].type = TYPE_INT64;
+ c = *p++;
+ }
+ }
+
+ /* format */
+ switch (c) {
+ case 'd':
+ case 'c':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ nas[ cn ].type = TYPE_DOUBLE;
+ break;
+
+ case 'p':
+ /* XXX should use cpp */
+ if (sizeof(void *) == sizeof(JSInt32)) {
+ nas[ cn ].type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(JSInt64)) {
+ nas[ cn ].type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(JSIntn)) {
+ nas[ cn ].type = TYPE_UINTN;
+ } else {
+ nas[ cn ].type = TYPE_UNKNOWN;
+ }
+ break;
+
+ case 'C':
+ case 'S':
+ case 'E':
+ case 'G':
+ /* XXX not supported I suppose */
+ JS_ASSERT(0);
+ nas[ cn ].type = TYPE_UNKNOWN;
+ break;
+
+ case 's':
+ nas[ cn ].type = (nas[ cn ].type == TYPE_UINT16) ? TYPE_WSTRING : TYPE_STRING;
+ break;
+
+ case 'n':
+ nas[ cn ].type = TYPE_INTSTR;
+ break;
+
+ default:
+ JS_ASSERT(0);
+ nas[ cn ].type = TYPE_UNKNOWN;
+ break;
+ }
+
+ /* get a legal para. */
+ if( nas[ cn ].type == TYPE_UNKNOWN ){
+ *rv = -1;
+ break;
+ }
+ }
+
+
+ /*
+ ** third pass
+ ** fill the nas[cn].ap
+ */
+
+ if( *rv < 0 ){
+ if( nas != nasArray )
+ free( nas );
+ return NULL;
+ }
+
+ cn = 0;
+ while( cn < number ){
+ if( nas[cn].type == TYPE_UNKNOWN ){
+ cn++;
+ continue;
+ }
+
+ VARARGS_ASSIGN(nas[cn].ap, ap);
+
+ switch( nas[cn].type ){
+ case TYPE_INT16:
+ case TYPE_UINT16:
+ case TYPE_INTN:
+ case TYPE_UINTN: (void)va_arg( ap, JSIntn ); break;
+
+ case TYPE_INT32: (void)va_arg( ap, JSInt32 ); break;
+
+ case TYPE_UINT32: (void)va_arg( ap, JSUint32 ); break;
+
+ case TYPE_INT64: (void)va_arg( ap, JSInt64 ); break;
+
+ case TYPE_UINT64: (void)va_arg( ap, JSUint64 ); break;
+
+ case TYPE_STRING: (void)va_arg( ap, char* ); break;
+
+ case TYPE_WSTRING: (void)va_arg( ap, jschar* ); break;
+
+ case TYPE_INTSTR: (void)va_arg( ap, JSIntn* ); break;
+
+ case TYPE_DOUBLE: (void)va_arg( ap, double ); break;
+
+ default:
+ if( nas != nasArray )
+ free( nas );
+ *rv = -1;
+ return NULL;
+ }
+
+ cn++;
+ }
+
+
+ return nas;
+}
+
+/*
+** The workhorse sprintf code.
+*/
+static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
+{
+ char c;
+ int flags, width, prec, radix, type;
+ union {
+ char ch;
+ jschar wch;
+ int i;
+ long l;
+ JSInt64 ll;
+ double d;
+ const char *s;
+ const jschar* ws;
+ int *ip;
+ } u;
+ const char *fmt0;
+ static const char hex[] = "0123456789abcdef";
+ static const char HEX[] = "0123456789ABCDEF";
+ const char *hexp;
+ int rv, i;
+ struct NumArgState *nas = NULL;
+ struct NumArgState nasArray[ NAS_DEFAULT_NUM ];
+ char pattern[20];
+ const char *dolPt = NULL; /* in "%4$.2f", dolPt will poiont to . */
+ uint8 utf8buf[6];
+ int utf8len;
+
+ /*
+ ** build an argument array, IF the fmt is numbered argument
+ ** list style, to contain the Numbered Argument list pointers
+ */
+
+ nas = BuildArgArray( fmt, ap, &rv, nasArray );
+ if( rv < 0 ){
+ /* the fmt contains error Numbered Argument format, jliu@netscape.com */
+ JS_ASSERT(0);
+ return rv;
+ }
+
+ while ((c = *fmt++) != 0) {
+ if (c != '%') {
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+ fmt0 = fmt - 1;
+
+ /*
+ ** Gobble up the % format string. Hopefully we have handled all
+ ** of the strange cases!
+ */
+ flags = 0;
+ c = *fmt++;
+ if (c == '%') {
+ /* quoting a % with %% */
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ if( nas != NULL ){
+ /* the fmt contains the Numbered Arguments feature */
+ i = 0;
+ while( c && c != '$' ){ /* should imporve error check later */
+ i = ( i * 10 ) + ( c - '0' );
+ c = *fmt++;
+ }
+
+ if( nas[i-1].type == TYPE_UNKNOWN ){
+ if( nas && ( nas != nasArray ) )
+ free( nas );
+ return -1;
+ }
+
+ ap = nas[i-1].ap;
+ dolPt = fmt;
+ c = *fmt++;
+ }
+
+ /*
+ * Examine optional flags. Note that we do not implement the
+ * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is
+ * somewhat ambiguous and not ideal, which is perhaps why
+ * the various sprintf() implementations are inconsistent
+ * on this feature.
+ */
+ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) {
+ if (c == '-') flags |= FLAG_LEFT;
+ if (c == '+') flags |= FLAG_SIGNED;
+ if (c == ' ') flags |= FLAG_SPACED;
+ if (c == '0') flags |= FLAG_ZEROS;
+ c = *fmt++;
+ }
+ if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED;
+ if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS;
+
+ /* width */
+ if (c == '*') {
+ c = *fmt++;
+ width = va_arg(ap, int);
+ } else {
+ width = 0;
+ while ((c >= '0') && (c <= '9')) {
+ width = (width * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+
+ /* precision */
+ prec = -1;
+ if (c == '.') {
+ c = *fmt++;
+ if (c == '*') {
+ c = *fmt++;
+ prec = va_arg(ap, int);
+ } else {
+ prec = 0;
+ while ((c >= '0') && (c <= '9')) {
+ prec = (prec * 10) + (c - '0');
+ c = *fmt++;
+ }
+ }
+ }
+
+ /* size */
+ type = TYPE_INTN;
+ if (c == 'h') {
+ type = TYPE_INT16;
+ c = *fmt++;
+ } else if (c == 'L') {
+ /* XXX not quite sure here */
+ type = TYPE_INT64;
+ c = *fmt++;
+ } else if (c == 'l') {
+ type = TYPE_INT32;
+ c = *fmt++;
+ if (c == 'l') {
+ type = TYPE_INT64;
+ c = *fmt++;
+ }
+ }
+
+ /* format */
+ hexp = hex;
+ switch (c) {
+ case 'd': case 'i': /* decimal/integer */
+ radix = 10;
+ goto fetch_and_convert;
+
+ case 'o': /* octal */
+ radix = 8;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'u': /* unsigned decimal */
+ radix = 10;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'x': /* unsigned hex */
+ radix = 16;
+ type |= 1;
+ goto fetch_and_convert;
+
+ case 'X': /* unsigned HEX */
+ radix = 16;
+ hexp = HEX;
+ type |= 1;
+ goto fetch_and_convert;
+
+ fetch_and_convert:
+ switch (type) {
+ case TYPE_INT16:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINT16:
+ u.l = va_arg(ap, int) & 0xffff;
+ goto do_long;
+ case TYPE_INTN:
+ u.l = va_arg(ap, int);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINTN:
+ u.l = (long)va_arg(ap, unsigned int);
+ goto do_long;
+
+ case TYPE_INT32:
+ u.l = va_arg(ap, JSInt32);
+ if (u.l < 0) {
+ u.l = -u.l;
+ flags |= FLAG_NEG;
+ }
+ goto do_long;
+ case TYPE_UINT32:
+ u.l = (long)va_arg(ap, JSUint32);
+ do_long:
+ rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case TYPE_INT64:
+ u.ll = va_arg(ap, JSInt64);
+ if (!JSLL_GE_ZERO(u.ll)) {
+ JSLL_NEG(u.ll, u.ll);
+ flags |= FLAG_NEG;
+ }
+ goto do_longlong;
+ case TYPE_UINT64:
+ u.ll = va_arg(ap, JSUint64);
+ do_longlong:
+ rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp);
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+ }
+ break;
+
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ u.d = va_arg(ap, double);
+ if( nas != NULL ){
+ i = fmt - dolPt;
+ if( i < (int)sizeof( pattern ) ){
+ pattern[0] = '%';
+ memcpy( &pattern[1], dolPt, (size_t)i );
+ rv = cvt_f(ss, u.d, pattern, &pattern[i+1] );
+ }
+ } else
+ rv = cvt_f(ss, u.d, fmt0, fmt);
+
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'c':
+ if ((flags & FLAG_LEFT) == 0) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ switch (type) {
+ case TYPE_INT16:
+ /* Treat %hc as %c unless js_CStringsAreUTF8. */
+ if (js_CStringsAreUTF8) {
+ u.wch = va_arg(ap, int);
+ utf8len = js_OneUcs4ToUtf8Char (utf8buf, u.wch);
+ rv = (*ss->stuff)(ss, (char *)utf8buf, utf8len);
+ break;
+ }
+ case TYPE_INTN:
+ u.ch = va_arg(ap, int);
+ rv = (*ss->stuff)(ss, &u.ch, 1);
+ break;
+ }
+ if (rv < 0) {
+ return rv;
+ }
+ if (flags & FLAG_LEFT) {
+ while (width-- > 1) {
+ rv = (*ss->stuff)(ss, " ", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+ break;
+
+ case 'p':
+ if (sizeof(void *) == sizeof(JSInt32)) {
+ type = TYPE_UINT32;
+ } else if (sizeof(void *) == sizeof(JSInt64)) {
+ type = TYPE_UINT64;
+ } else if (sizeof(void *) == sizeof(int)) {
+ type = TYPE_UINTN;
+ } else {
+ JS_ASSERT(0);
+ break;
+ }
+ radix = 16;
+ goto fetch_and_convert;
+
+#if 0
+ case 'C':
+ case 'S':
+ case 'E':
+ case 'G':
+ /* XXX not supported I suppose */
+ JS_ASSERT(0);
+ break;
+#endif
+
+ case 's':
+ if(type == TYPE_INT16) {
+ /*
+ * This would do a simple string/byte conversion
+ * unless js_CStringsAreUTF8.
+ */
+ u.ws = va_arg(ap, const jschar*);
+ rv = cvt_ws(ss, u.ws, width, prec, flags);
+ } else {
+ u.s = va_arg(ap, const char*);
+ rv = cvt_s(ss, u.s, width, prec, flags);
+ }
+ if (rv < 0) {
+ return rv;
+ }
+ break;
+
+ case 'n':
+ u.ip = va_arg(ap, int*);
+ if (u.ip) {
+ *u.ip = ss->cur - ss->base;
+ }
+ break;
+
+ default:
+ /* Not a % token after all... skip it */
+#if 0
+ JS_ASSERT(0);
+#endif
+ rv = (*ss->stuff)(ss, "%", 1);
+ if (rv < 0) {
+ return rv;
+ }
+ rv = (*ss->stuff)(ss, fmt - 1, 1);
+ if (rv < 0) {
+ return rv;
+ }
+ }
+ }
+
+ /* Stuff trailing NUL */
+ rv = (*ss->stuff)(ss, "\0", 1);
+
+ if( nas && ( nas != nasArray ) ){
+ free( nas );
+ }
+
+ return rv;
+}
+
+/************************************************************************/
+
+static int FuncStuff(SprintfState *ss, const char *sp, JSUint32 len)
+{
+ int rv;
+
+ rv = (*ss->func)(ss->arg, sp, len);
+ if (rv < 0) {
+ return rv;
+ }
+ ss->maxlen += len;
+ return 0;
+}
+
+JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc func, void *arg,
+ const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ va_start(ap, fmt);
+ rv = JS_vsxprintf(func, arg, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc func, void *arg,
+ const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = FuncStuff;
+ ss.func = func;
+ ss.arg = arg;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ return (rv < 0) ? (JSUint32)-1 : ss.maxlen;
+}
+
+/*
+** Stuff routine that automatically grows the malloc'd output buffer
+** before it overflows.
+*/
+static int GrowStuff(SprintfState *ss, const char *sp, JSUint32 len)
+{
+ ptrdiff_t off;
+ char *newbase;
+ JSUint32 newlen;
+
+ off = ss->cur - ss->base;
+ if (off + len >= ss->maxlen) {
+ /* Grow the buffer */
+ newlen = ss->maxlen + ((len > 32) ? len : 32);
+ if (ss->base) {
+ newbase = (char*) realloc(ss->base, newlen);
+ } else {
+ newbase = (char*) malloc(newlen);
+ }
+ if (!newbase) {
+ /* Ran out of memory */
+ return -1;
+ }
+ ss->base = newbase;
+ ss->maxlen = newlen;
+ ss->cur = ss->base + off;
+ }
+
+ /* Copy data */
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ JS_ASSERT((JSUint32)(ss->cur - ss->base) <= ss->maxlen);
+ return 0;
+}
+
+/*
+** sprintf into a malloc'd buffer
+*/
+JS_PUBLIC_API(char *) JS_smprintf(const char *fmt, ...)
+{
+ va_list ap;
+ char *rv;
+
+ va_start(ap, fmt);
+ rv = JS_vsmprintf(fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+/*
+** Free memory allocated, for the caller, by JS_smprintf
+*/
+JS_PUBLIC_API(void) JS_smprintf_free(char *mem)
+{
+ free(mem);
+}
+
+JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ free(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
+/*
+** Stuff routine that discards overflow data
+*/
+static int LimitStuff(SprintfState *ss, const char *sp, JSUint32 len)
+{
+ JSUint32 limit = ss->maxlen - (ss->cur - ss->base);
+
+ if (len > limit) {
+ len = limit;
+ }
+ while (len) {
+ --len;
+ *ss->cur++ = *sp++;
+ }
+ return 0;
+}
+
+/*
+** sprintf into a fixed size buffer. Make sure there is a NUL at the end
+** when finished.
+*/
+JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...)
+{
+ va_list ap;
+ int rv;
+
+ JS_ASSERT((JSInt32)outlen > 0);
+ if ((JSInt32)outlen <= 0) {
+ return 0;
+ }
+
+ va_start(ap, fmt);
+ rv = JS_vsnprintf(out, outlen, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen,const char *fmt,
+ va_list ap)
+{
+ SprintfState ss;
+ JSUint32 n;
+
+ JS_ASSERT((JSInt32)outlen > 0);
+ if ((JSInt32)outlen <= 0) {
+ return 0;
+ }
+
+ ss.stuff = LimitStuff;
+ ss.base = out;
+ ss.cur = out;
+ ss.maxlen = outlen;
+ (void) dosprintf(&ss, fmt, ap);
+
+ /* If we added chars, and we didn't append a null, do it now. */
+ if( (ss.cur != ss.base) && (ss.cur[-1] != '\0') )
+ ss.cur[-1] = '\0';
+
+ n = ss.cur - ss.base;
+ return n ? n - 1 : n;
+}
+
+JS_PUBLIC_API(char *) JS_sprintf_append(char *last, const char *fmt, ...)
+{
+ va_list ap;
+ char *rv;
+
+ va_start(ap, fmt);
+ rv = JS_vsprintf_append(last, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+JS_PUBLIC_API(char *) JS_vsprintf_append(char *last, const char *fmt, va_list ap)
+{
+ SprintfState ss;
+ int rv;
+
+ ss.stuff = GrowStuff;
+ if (last) {
+ int lastlen = strlen(last);
+ ss.base = last;
+ ss.cur = last + lastlen;
+ ss.maxlen = lastlen;
+ } else {
+ ss.base = 0;
+ ss.cur = 0;
+ ss.maxlen = 0;
+ }
+ rv = dosprintf(&ss, fmt, ap);
+ if (rv < 0) {
+ if (ss.base) {
+ free(ss.base);
+ }
+ return 0;
+ }
+ return ss.base;
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsprf.h b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.h
new file mode 100644
index 0000000..1f3200d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsprf.h
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsprf_h___
+#define jsprf_h___
+
+/*
+** API for PR printf like routines. Supports the following formats
+** %d - decimal
+** %u - unsigned decimal
+** %x - unsigned hex
+** %X - unsigned uppercase hex
+** %o - unsigned octal
+** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
+** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
+** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
+** %s - string
+** %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
+** %c - character
+** %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
+** %p - pointer (deals with machine dependent pointer size)
+** %f - float
+** %g - float
+*/
+#include "jstypes.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+JS_BEGIN_EXTERN_C
+
+/*
+** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
+** of the buffer. Returns the length of the written output, NOT including
+** the NUL, or (JSUint32)-1 if an error occurs.
+*/
+extern JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...);
+
+/*
+** sprintf into a malloc'd buffer. Return a pointer to the malloc'd
+** buffer on success, NULL on failure. Call "JS_smprintf_free" to release
+** the memory returned.
+*/
+extern JS_PUBLIC_API(char*) JS_smprintf(const char *fmt, ...);
+
+/*
+** Free the memory allocated, for the caller, by JS_smprintf
+*/
+extern JS_PUBLIC_API(void) JS_smprintf_free(char *mem);
+
+/*
+** "append" sprintf into a malloc'd buffer. "last" is the last value of
+** the malloc'd buffer. sprintf will append data to the end of last,
+** growing it as necessary using realloc. If last is NULL, JS_sprintf_append
+** will allocate the initial string. The return value is the new value of
+** last for subsequent calls, or NULL if there is a malloc failure.
+*/
+extern JS_PUBLIC_API(char*) JS_sprintf_append(char *last, const char *fmt, ...);
+
+/*
+** sprintf into a function. The function "f" is called with a string to
+** place into the output. "arg" is an opaque pointer used by the stuff
+** function to hold any state needed to do the storage of the output
+** data. The return value is a count of the number of characters fed to
+** the stuff function, or (JSUint32)-1 if an error occurs.
+*/
+typedef JSIntn (*JSStuffFunc)(void *arg, const char *s, JSUint32 slen);
+
+extern JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc f, void *arg, const char *fmt, ...);
+
+/*
+** va_list forms of the above.
+*/
+extern JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen, const char *fmt, va_list ap);
+extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap);
+extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap);
+extern JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap);
+
+/*
+***************************************************************************
+** FUNCTION: JS_sscanf
+** DESCRIPTION:
+** JS_sscanf() scans the input character string, performs data
+** conversions, and stores the converted values in the data objects
+** pointed to by its arguments according to the format control
+** string.
+**
+** JS_sscanf() behaves the same way as the sscanf() function in the
+** Standard C Library (stdio.h), with the following exceptions:
+** - JS_sscanf() handles the NSPR integer and floating point types,
+** such as JSInt16, JSInt32, JSInt64, and JSFloat64, whereas
+** sscanf() handles the standard C types like short, int, long,
+** and double.
+** - JS_sscanf() has no multibyte character support, while sscanf()
+** does.
+** INPUTS:
+** const char *buf
+** a character string holding the input to scan
+** const char *fmt
+** the format control string for the conversions
+** ...
+** variable number of arguments, each of them is a pointer to
+** a data object in which the converted value will be stored
+** OUTPUTS: none
+** RETURNS: JSInt32
+** The number of values converted and stored.
+** RESTRICTIONS:
+** Multibyte characters in 'buf' or 'fmt' are not allowed.
+***************************************************************************
+*/
+
+extern JS_PUBLIC_API(JSInt32) JS_sscanf(const char *buf, const char *fmt, ...);
+
+JS_END_EXTERN_C
+
+#endif /* jsprf_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl
new file mode 100644
index 0000000..e713d6f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsproto.tbl
@@ -0,0 +1,129 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=80 ft=c:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey 1.7 work in progress, released
+ * February 14, 2006.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsversion.h"
+
+#if JS_HAS_SCRIPT_OBJECT
+# define SCRIPT_INIT js_InitScriptClass
+#else
+# define SCRIPT_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_XML_SUPPORT
+# define XML_INIT js_InitXMLClass
+# define NAMESPACE_INIT js_InitNamespaceClass
+# define QNAME_INIT js_InitQNameClass
+# define ANYNAME_INIT js_InitAnyNameClass
+# define ATTRIBUTE_INIT js_InitAttributeNameClass
+# define XMLFILTER_INIT js_InitXMLFilterClass
+#else
+# define XML_INIT js_InitNullClass
+# define NAMESPACE_INIT js_InitNullClass
+# define QNAME_INIT js_InitNullClass
+# define ANYNAME_INIT js_InitNullClass
+# define ATTRIBUTE_INIT js_InitNullClass
+# define XMLFILTER_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_GENERATORS
+# define GENERATOR_INIT js_InitIteratorClasses
+#else
+# define GENERATOR_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_NO_SUCH_METHOD
+# define NO_SUCH_METHOD_INIT js_InitNoSuchMethodClass
+#else
+# define NO_SUCH_METHOD_INIT js_InitNullClass
+#endif
+
+#if JS_HAS_FILE_OBJECT
+# define FILE_INIT js_InitFileClass
+#else
+# define FILE_INIT js_InitNullClass
+#endif
+
+/*
+ * Enumerator codes in the second column must not change -- they are part of
+ * the JS XDR API. Client modules including jsproto.tbl should consider
+ * wrapping the inclusion with JS_BEGIN_EXTERN_C and JS_END_EXTERN_C.
+ */
+JS_PROTO(Null, 0, js_InitNullClass)
+JS_PROTO(Object, 1, js_InitFunctionAndObjectClasses)
+JS_PROTO(Function, 2, js_InitFunctionAndObjectClasses)
+JS_PROTO(Array, 3, js_InitArrayClass)
+JS_PROTO(Boolean, 4, js_InitBooleanClass)
+JS_PROTO(Call, 5, js_InitCallClass)
+JS_PROTO(Date, 6, js_InitDateClass)
+JS_PROTO(Math, 7, js_InitMathClass)
+JS_PROTO(Number, 8, js_InitNumberClass)
+JS_PROTO(String, 9, js_InitStringClass)
+JS_PROTO(RegExp, 10, js_InitRegExpClass)
+JS_PROTO(Script, 11, SCRIPT_INIT)
+JS_PROTO(XML, 12, XML_INIT)
+JS_PROTO(Namespace, 13, NAMESPACE_INIT)
+JS_PROTO(QName, 14, QNAME_INIT)
+JS_PROTO(AnyName, 15, ANYNAME_INIT)
+JS_PROTO(AttributeName, 16, ATTRIBUTE_INIT)
+JS_PROTO(Error, 17, js_InitExceptionClasses)
+JS_PROTO(InternalError, 18, js_InitExceptionClasses)
+JS_PROTO(EvalError, 19, js_InitExceptionClasses)
+JS_PROTO(RangeError, 20, js_InitExceptionClasses)
+JS_PROTO(ReferenceError, 21, js_InitExceptionClasses)
+JS_PROTO(SyntaxError, 22, js_InitExceptionClasses)
+JS_PROTO(TypeError, 23, js_InitExceptionClasses)
+JS_PROTO(URIError, 24, js_InitExceptionClasses)
+JS_PROTO(Generator, 25, GENERATOR_INIT)
+JS_PROTO(Iterator, 26, js_InitIteratorClasses)
+JS_PROTO(StopIteration, 27, js_InitIteratorClasses)
+JS_PROTO(UnusedProto28, 28, js_InitNullClass)
+JS_PROTO(File, 29, FILE_INIT)
+JS_PROTO(Block, 30, js_InitBlockClass)
+JS_PROTO(XMLFilter, 31, XMLFILTER_INIT)
+JS_PROTO(NoSuchMethod, 32, NO_SUCH_METHOD_INIT)
+JS_PROTO(JSON, 33, js_InitJSONClass)
+
+#undef SCRIPT_INIT
+#undef XML_INIT
+#undef NAMESPACE_INIT
+#undef QNAME_INIT
+#undef ANYNAME_INIT
+#undef ATTRIBUTE_INIT
+#undef GENERATOR_INIT
+#undef FILE_INIT
+#undef NO_SUCH_METHOD_INIT
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h b/tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h
new file mode 100644
index 0000000..710fa99
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsprvtd.h
@@ -0,0 +1,263 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsprvtd_h___
+#define jsprvtd_h___
+/*
+ * JS private typename definitions.
+ *
+ * This header is included only in other .h files, for convenience and for
+ * simplicity of type naming. The alternative for structures is to use tags,
+ * which are named the same as their typedef names (legal in C/C++, and less
+ * noisy than suffixing the typedef name with "Struct" or "Str"). Instead,
+ * all .h files that include this file may use the same typedef name, whether
+ * declaring a pointer to struct type, or defining a member of struct type.
+ *
+ * A few fundamental scalar types are defined here too. Neither the scalar
+ * nor the struct typedefs should change much, therefore the nearly-global
+ * make dependency induced by this file should not prove painful.
+ */
+
+#include "jspubtd.h"
+
+/* Internal identifier (jsid) macros. */
+
+#define JSID_IS_ATOM(id) JSVAL_IS_STRING((jsval)(id))
+#define JSID_TO_ATOM(id) ((JSAtom *)(id))
+#define ATOM_TO_JSID(atom) (JS_ASSERT(ATOM_IS_STRING(atom)), \
+ (jsid)(atom))
+
+#define JSID_IS_INT(id) JSVAL_IS_INT((jsval)(id))
+#define JSID_TO_INT(id) JSVAL_TO_INT((jsval)(id))
+#define INT_TO_JSID(i) ((jsid)INT_TO_JSVAL(i))
+#define INT_JSVAL_TO_JSID(v) ((jsid)(v))
+#define INT_JSID_TO_JSVAL(id) ((jsval)(id))
+
+#define JSID_IS_OBJECT(id) JSVAL_IS_OBJECT((jsval)(id))
+#define JSID_TO_OBJECT(id) JSVAL_TO_OBJECT((jsval)(id))
+#define OBJECT_TO_JSID(obj) ((jsid)OBJECT_TO_JSVAL(obj))
+#define OBJECT_JSVAL_TO_JSID(v) ((jsid)v)
+
+#define ID_TO_VALUE(id) ((jsval)(id))
+
+/*
+ * Convenience constants.
+ */
+#define JS_BITS_PER_UINT32_LOG2 5
+#define JS_BITS_PER_UINT32 32
+
+/* Scalar typedefs. */
+typedef uint8 jsbytecode;
+typedef uint8 jssrcnote;
+typedef uint32 jsatomid;
+
+/* Struct typedefs. */
+typedef struct JSArgumentFormatMap JSArgumentFormatMap;
+typedef struct JSCodeGenerator JSCodeGenerator;
+typedef struct JSGCThing JSGCThing;
+typedef struct JSGenerator JSGenerator;
+typedef struct JSNativeEnumerator JSNativeEnumerator;
+typedef struct JSParseContext JSParseContext;
+typedef struct JSParsedObjectBox JSParsedObjectBox;
+typedef struct JSParseNode JSParseNode;
+typedef struct JSPropCacheEntry JSPropCacheEntry;
+typedef struct JSSharpObjectMap JSSharpObjectMap;
+typedef struct JSTempValueRooter JSTempValueRooter;
+typedef struct JSThread JSThread;
+typedef struct JSToken JSToken;
+typedef struct JSTokenPos JSTokenPos;
+typedef struct JSTokenPtr JSTokenPtr;
+typedef struct JSTokenStream JSTokenStream;
+typedef struct JSTreeContext JSTreeContext;
+typedef struct JSTryNote JSTryNote;
+typedef struct JSWeakRoots JSWeakRoots;
+
+/* Friend "Advanced API" typedefs. */
+typedef struct JSAtom JSAtom;
+typedef struct JSAtomList JSAtomList;
+typedef struct JSAtomListElement JSAtomListElement;
+typedef struct JSAtomMap JSAtomMap;
+typedef struct JSAtomState JSAtomState;
+typedef struct JSCodeSpec JSCodeSpec;
+typedef struct JSPrinter JSPrinter;
+typedef struct JSRegExp JSRegExp;
+typedef struct JSRegExpStatics JSRegExpStatics;
+typedef struct JSScope JSScope;
+typedef struct JSScopeOps JSScopeOps;
+typedef struct JSScopeProperty JSScopeProperty;
+typedef struct JSStackHeader JSStackHeader;
+typedef struct JSStringBuffer JSStringBuffer;
+typedef struct JSSubString JSSubString;
+typedef struct JSTraceableNative JSTraceableNative;
+typedef struct JSXML JSXML;
+typedef struct JSXMLArray JSXMLArray;
+typedef struct JSXMLArrayCursor JSXMLArrayCursor;
+
+/* "Friend" types used by jscntxt.h and jsdbgapi.h. */
+typedef enum JSTrapStatus {
+ JSTRAP_ERROR,
+ JSTRAP_CONTINUE,
+ JSTRAP_RETURN,
+ JSTRAP_THROW,
+ JSTRAP_LIMIT
+} JSTrapStatus;
+
+typedef JSTrapStatus
+(* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
+ void *closure);
+
+typedef JSBool
+(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsval id, jsval old,
+ jsval *newp, void *closure);
+
+/* called just after script creation */
+typedef void
+(* JSNewScriptHook)(JSContext *cx,
+ const char *filename, /* URL of script */
+ uintN lineno, /* first line */
+ JSScript *script,
+ JSFunction *fun,
+ void *callerdata);
+
+/* called just before script destruction */
+typedef void
+(* JSDestroyScriptHook)(JSContext *cx,
+ JSScript *script,
+ void *callerdata);
+
+typedef void
+(* JSSourceHandler)(const char *filename, uintN lineno, jschar *str,
+ size_t length, void **listenerTSData, void *closure);
+
+/*
+ * This hook captures high level script execution and function calls (JS or
+ * native). It is used by JS_SetExecuteHook to hook top level scripts and by
+ * JS_SetCallHook to hook function calls. It will get called twice per script
+ * or function call: just before execution begins and just after it finishes.
+ * In both cases the 'current' frame is that of the executing code.
+ *
+ * The 'before' param is JS_TRUE for the hook invocation before the execution
+ * and JS_FALSE for the invocation after the code has run.
+ *
+ * The 'ok' param is significant only on the post execution invocation to
+ * signify whether or not the code completed 'normally'.
+ *
+ * The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
+ * for the 'before'invocation, but is whatever value is returned from that
+ * invocation for the 'after' invocation. Thus, the hook implementor *could*
+ * allocate a structure in the 'before' invocation and return a pointer to that
+ * structure. The pointer would then be handed to the hook for the 'after'
+ * invocation. Alternately, the 'before' could just return the same value as
+ * in 'closure' to cause the 'after' invocation to be called with the same
+ * 'closure' value as the 'before'.
+ *
+ * Returning NULL in the 'before' hook will cause the 'after' hook *not* to
+ * be called.
+ */
+typedef void *
+(* JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before,
+ JSBool *ok, void *closure);
+
+typedef void
+(* JSObjectHook)(JSContext *cx, JSObject *obj, JSBool isNew, void *closure);
+
+typedef JSBool
+(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
+ void *closure);
+
+typedef struct JSDebugHooks {
+ JSTrapHandler interruptHandler;
+ void *interruptHandlerData;
+ JSNewScriptHook newScriptHook;
+ void *newScriptHookData;
+ JSDestroyScriptHook destroyScriptHook;
+ void *destroyScriptHookData;
+ JSTrapHandler debuggerHandler;
+ void *debuggerHandlerData;
+ JSSourceHandler sourceHandler;
+ void *sourceHandlerData;
+ JSInterpreterHook executeHook;
+ void *executeHookData;
+ JSInterpreterHook callHook;
+ void *callHookData;
+ JSObjectHook objectHook;
+ void *objectHookData;
+ JSTrapHandler throwHook;
+ void *throwHookData;
+ JSDebugErrorHook debugErrorHook;
+ void *debugErrorHookData;
+} JSDebugHooks;
+
+/*
+ * Type definitions for temporary GC roots that register with GC local C
+ * variables. See jscntxt.h for details.
+ */
+typedef void
+(* JSTempValueTrace)(JSTracer *trc, JSTempValueRooter *tvr);
+
+typedef union JSTempValueUnion {
+ jsval value;
+ JSObject *object;
+ JSString *string;
+ JSXML *xml;
+ JSTempValueTrace trace;
+ JSScopeProperty *sprop;
+ JSWeakRoots *weakRoots;
+ JSParseContext *parseContext;
+ JSScript *script;
+ jsval *array;
+} JSTempValueUnion;
+
+struct JSTempValueRooter {
+ JSTempValueRooter *down;
+ ptrdiff_t count;
+ JSTempValueUnion u;
+};
+
+/*
+ * The following determines whether JS_EncodeCharacters and JS_DecodeBytes
+ * treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
+ */
+#ifdef JS_C_STRINGS_ARE_UTF8
+# define js_CStringsAreUTF8 JS_TRUE
+#else
+extern JSBool js_CStringsAreUTF8;
+#endif
+
+#endif /* jsprvtd_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h b/tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h
new file mode 100644
index 0000000..1e3f33a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jspubtd.h
@@ -0,0 +1,727 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jspubtd_h___
+#define jspubtd_h___
+/*
+ * JS public API typedefs.
+ */
+#include "jstypes.h"
+#include "jscompat.h"
+
+JS_BEGIN_EXTERN_C
+
+/* Scalar typedefs. */
+typedef uint16 jschar;
+typedef int32 jsint;
+typedef uint32 jsuint;
+typedef float64 jsdouble;
+typedef jsword jsval;
+typedef jsword jsid;
+typedef int32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */
+
+/*
+ * Run-time version enumeration. See jsversion.h for compile-time counterparts
+ * to these values that may be selected by the JS_VERSION macro, and tested by
+ * #if expressions.
+ */
+typedef enum JSVersion {
+ JSVERSION_1_0 = 100,
+ JSVERSION_1_1 = 110,
+ JSVERSION_1_2 = 120,
+ JSVERSION_1_3 = 130,
+ JSVERSION_1_4 = 140,
+ JSVERSION_ECMA_3 = 148,
+ JSVERSION_1_5 = 150,
+ JSVERSION_1_6 = 160,
+ JSVERSION_1_7 = 170,
+ JSVERSION_1_8 = 180,
+ JSVERSION_DEFAULT = 0,
+ JSVERSION_UNKNOWN = -1,
+ JSVERSION_LATEST = JSVERSION_1_8
+} JSVersion;
+
+#define JSVERSION_IS_ECMA(version) \
+ ((version) == JSVERSION_DEFAULT || (version) >= JSVERSION_1_3)
+
+/* Result of typeof operator enumeration. */
+typedef enum JSType {
+ JSTYPE_VOID, /* undefined */
+ JSTYPE_OBJECT, /* object */
+ JSTYPE_FUNCTION, /* function */
+ JSTYPE_STRING, /* string */
+ JSTYPE_NUMBER, /* number */
+ JSTYPE_BOOLEAN, /* boolean */
+ JSTYPE_NULL, /* null */
+ JSTYPE_XML, /* xml object */
+ JSTYPE_LIMIT
+} JSType;
+
+/* Dense index into cached prototypes and class atoms for standard objects. */
+typedef enum JSProtoKey {
+#define JS_PROTO(name,code,init) JSProto_##name = code,
+#include "jsproto.tbl"
+#undef JS_PROTO
+ JSProto_LIMIT
+} JSProtoKey;
+
+/* JSObjectOps.checkAccess mode enumeration. */
+typedef enum JSAccessMode {
+ JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */
+ JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */
+
+ /*
+ * enum value #2 formerly called JSACC_IMPORT,
+ * gap preserved for liveconnect ABI compatibility.
+ */
+
+ JSACC_WATCH = 3, /* a watchpoint on object foo for id 'bar' */
+ JSACC_READ = 4, /* a "get" of foo.bar */
+ JSACC_WRITE = 8, /* a "set" of foo.bar = baz */
+ JSACC_LIMIT
+} JSAccessMode;
+
+#define JSACC_TYPEMASK (JSACC_WRITE - 1)
+
+/*
+ * This enum type is used to control the behavior of a JSObject property
+ * iterator function that has type JSNewEnumerate.
+ */
+typedef enum JSIterateOp {
+ JSENUMERATE_INIT, /* Create new iterator state */
+ JSENUMERATE_NEXT, /* Iterate once */
+ JSENUMERATE_DESTROY /* Destroy iterator state */
+} JSIterateOp;
+
+/* Struct typedefs. */
+typedef struct JSClass JSClass;
+typedef struct JSExtendedClass JSExtendedClass;
+typedef struct JSConstDoubleSpec JSConstDoubleSpec;
+typedef struct JSContext JSContext;
+typedef struct JSErrorReport JSErrorReport;
+typedef struct JSFunction JSFunction;
+typedef struct JSFunctionSpec JSFunctionSpec;
+typedef struct JSTracer JSTracer;
+typedef struct JSIdArray JSIdArray;
+typedef struct JSProperty JSProperty;
+typedef struct JSPropertySpec JSPropertySpec;
+typedef struct JSObject JSObject;
+typedef struct JSObjectMap JSObjectMap;
+typedef struct JSObjectOps JSObjectOps;
+typedef struct JSXMLObjectOps JSXMLObjectOps;
+typedef struct JSRuntime JSRuntime;
+typedef struct JSRuntime JSTaskState; /* XXX deprecated name */
+typedef struct JSScript JSScript;
+typedef struct JSStackFrame JSStackFrame;
+typedef struct JSString JSString;
+typedef struct JSXDRState JSXDRState;
+typedef struct JSExceptionState JSExceptionState;
+typedef struct JSLocaleCallbacks JSLocaleCallbacks;
+typedef struct JSSecurityCallbacks JSSecurityCallbacks;
+typedef struct JSONParser JSONParser;
+
+/* JSClass (and JSObjectOps where appropriate) function pointer typedefs. */
+
+/*
+ * Add, delete, get or set a property named by id in obj. Note the jsval id
+ * type -- id may be a string (Unicode property identifier) or an int (element
+ * index). The *vp out parameter, on success, is the new property value after
+ * an add, get, or set. After a successful delete, *vp is JSVAL_FALSE iff
+ * obj[id] can't be deleted (because it's permanent).
+ */
+typedef JSBool
+(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+/*
+ * This function type is used for callbacks that enumerate the properties of
+ * a JSObject. The behavior depends on the value of enum_op:
+ *
+ * JSENUMERATE_INIT
+ * A new, opaque iterator state should be allocated and stored in *statep.
+ * (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
+ *
+ * The number of properties that will be enumerated should be returned as
+ * an integer jsval in *idp, if idp is non-null, and provided the number of
+ * enumerable properties is known. If idp is non-null and the number of
+ * enumerable properties can't be computed in advance, *idp should be set
+ * to JSVAL_ZERO.
+ *
+ * JSENUMERATE_NEXT
+ * A previously allocated opaque iterator state is passed in via statep.
+ * Return the next jsid in the iteration using *idp. The opaque iterator
+ * state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
+ * if there are no properties left to enumerate.
+ *
+ * JSENUMERATE_DESTROY
+ * Destroy the opaque iterator state previously allocated in *statep by a
+ * call to this function when enum_op was JSENUMERATE_INIT.
+ *
+ * The return value is used to indicate success, with a value of JS_FALSE
+ * indicating failure.
+ */
+typedef JSBool
+(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp);
+
+/*
+ * The old-style JSClass.enumerate op should define all lazy properties not
+ * yet reflected in obj.
+ */
+typedef JSBool
+(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Resolve a lazy property named by id in obj by defining it directly in obj.
+ * Lazy properties are those reflected from some peer native property space
+ * (e.g., the DOM attributes for a given node reflected as obj) on demand.
+ *
+ * JS looks for a property in an object, and if not found, tries to resolve
+ * the given id. If resolve succeeds, the engine looks again in case resolve
+ * defined obj[id]. If no such property exists directly in obj, the process
+ * is repeated with obj's prototype, etc.
+ *
+ * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
+ */
+typedef JSBool
+(* JSResolveOp)(JSContext *cx, JSObject *obj, jsval id);
+
+/*
+ * Like JSResolveOp, but flags provide contextual information as follows:
+ *
+ * JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id
+ * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
+ * JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
+ * JSRESOLVE_DECLARING var, const, or function prolog declaration opcode
+ * JSRESOLVE_CLASSNAME class name used when constructing
+ *
+ * The *objp out parameter, on success, should be null to indicate that id
+ * was not resolved; and non-null, referring to obj or one of its prototypes,
+ * if id was resolved.
+ *
+ * This hook instead of JSResolveOp is called via the JSClass.resolve member
+ * if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
+ *
+ * Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
+ * extends this hook by passing in the starting object on the prototype chain
+ * via *objp. Thus a resolve hook implementation may define the property id
+ * being resolved in the object in which the id was first sought, rather than
+ * in a prototype object whose class led to the resolve hook being called.
+ *
+ * When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
+ * null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no
+ * JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
+ * This is not good practice, but enough existing hook implementations count
+ * on it that we can't break compatibility by passing the starting object in
+ * *objp without a new JSClass flag.
+ */
+typedef JSBool
+(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp);
+
+/*
+ * Convert obj to the given type, returning true with the resulting value in
+ * *vp on success, and returning false on error or exception.
+ */
+typedef JSBool
+(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
+
+/*
+ * Finalize obj, which the garbage collector has determined to be unreachable
+ * from other live objects or from GC roots. Obviously, finalizers must never
+ * store a reference to obj.
+ */
+typedef void
+(* JSFinalizeOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
+ * to extend and reduce the set of string types finalized by the GC.
+ */
+typedef void
+(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
+
+/*
+ * The signature for JSClass.getObjectOps, used by JS_NewObject's internals
+ * to discover the set of high-level object operations to use for new objects
+ * of the given class. All native objects have a JSClass, which is stored as
+ * a private (int-tagged) pointer in obj slots. In contrast, all native and
+ * host objects have a JSObjectMap at obj->map, which may be shared among a
+ * number of objects, and which contains the JSObjectOps *ops pointer used to
+ * dispatch object operations from API calls.
+ *
+ * Thus JSClass (which pre-dates JSObjectOps in the API) provides a low-level
+ * interface to class-specific code and data, while JSObjectOps allows for a
+ * higher level of operation, which does not use the object's class except to
+ * find the class's JSObjectOps struct, by calling clasp->getObjectOps, and to
+ * finalize the object.
+ *
+ * If this seems backwards, that's because it is! API compatibility requires
+ * a JSClass *clasp parameter to JS_NewObject, etc. Most host objects do not
+ * need to implement the larger JSObjectOps, and can share the common JSScope
+ * code and data used by the native (js_ObjectOps, see jsobj.c) ops.
+ *
+ * Further extension to preserve API compatibility: if this function returns
+ * a pointer to JSXMLObjectOps.base, not to JSObjectOps, then the engine calls
+ * extended hooks needed for E4X.
+ */
+typedef JSObjectOps *
+(* JSGetObjectOps)(JSContext *cx, JSClass *clasp);
+
+/*
+ * JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
+ * returning false on error/exception, true on success with obj[id]'s last-got
+ * value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
+ * is either a string or an int jsval.
+ *
+ * See JSCheckAccessIdOp, below, for the JSObjectOps counterpart, which takes
+ * a jsid (a tagged int or aligned, unique identifier pointer) rather than a
+ * jsval. The native js_ObjectOps.checkAccess simply forwards to the object's
+ * clasp->checkAccess, so that both JSClass and JSObjectOps implementors may
+ * specialize access checks.
+ */
+typedef JSBool
+(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsval id, JSAccessMode mode,
+ jsval *vp);
+
+/*
+ * Encode or decode an object, given an XDR state record representing external
+ * data. See jsxdrapi.h.
+ */
+typedef JSBool
+(* JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
+
+/*
+ * Check whether v is an instance of obj. Return false on error or exception,
+ * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
+ * *bp otherwise.
+ */
+typedef JSBool
+(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+/*
+ * Deprecated function type for JSClass.mark. All new code should define
+ * JSTraceOp instead to ensure the traversal of traceable things stored in
+ * the native structures.
+ */
+typedef uint32
+(* JSMarkOp)(JSContext *cx, JSObject *obj, void *arg);
+
+/*
+ * Function type for trace operation of the class called to enumerate all
+ * traceable things reachable from obj's private data structure. For each such
+ * thing, a trace implementation must call
+ *
+ * JS_CallTracer(trc, thing, kind);
+ *
+ * or one of its convenience macros as described in jsapi.h.
+ *
+ * JSTraceOp implementation can assume that no other threads mutates object
+ * state. It must not change state of the object or corresponding native
+ * structures. The only exception for this rule is the case when the embedding
+ * needs a tight integration with GC. In that case the embedding can check if
+ * the traversal is a part of the marking phase through calling
+ * JS_IsGCMarkingTracer and apply a special code like emptying caches or
+ * marking its native structures.
+ *
+ * To define the tracer for a JSClass, the implementation must add
+ * JSCLASS_MARK_IS_TRACE to class flags and use JS_CLASS_TRACE(method)
+ * macro below to convert JSTraceOp to JSMarkOp when initializing or
+ * assigning JSClass.mark field.
+ */
+typedef void
+(* JSTraceOp)(JSTracer *trc, JSObject *obj);
+
+#if defined __GNUC__ && __GNUC__ >= 4 && !defined __cplusplus
+# define JS_CLASS_TRACE(method) \
+ (__builtin_types_compatible_p(JSTraceOp, __typeof(&(method))) \
+ ? (JSMarkOp)(method) \
+ : js_WrongTypeForClassTracer)
+
+extern JSMarkOp js_WrongTypeForClassTracer;
+
+#else
+# define JS_CLASS_TRACE(method) ((JSMarkOp)(method))
+#endif
+
+/*
+ * Tracer callback, called for each traceable thing directly refrenced by a
+ * particular object or runtime structure. It is the callback responsibility
+ * to ensure the traversal of the full object graph via calling eventually
+ * JS_TraceChildren on the passed thing. In this case the callback must be
+ * prepared to deal with cycles in the traversal graph.
+ *
+ * kind argument is one of JSTRACE_OBJECT, JSTRACE_DOUBLE, JSTRACE_STRING or
+ * a tag denoting internal implementation-specific traversal kind. In the
+ * latter case the only operations on thing that the callback can do is to call
+ * JS_TraceChildren or DEBUG-only JS_PrintTraceThingInfo.
+ */
+typedef void
+(* JSTraceCallback)(JSTracer *trc, void *thing, uint32 kind);
+
+/*
+ * DEBUG only callback that JSTraceOp implementation can provide to return
+ * a string describing the reference traced with JS_CallTracer.
+ */
+#ifdef DEBUG
+typedef void
+(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
+#endif
+
+/*
+ * The optional JSClass.reserveSlots hook allows a class to make computed
+ * per-instance object slots reservations, in addition to or instead of using
+ * JSCLASS_HAS_RESERVED_SLOTS(n) in the JSClass.flags initializer to reserve
+ * a constant-per-class number of slots. Implementations of this hook should
+ * return the number of slots to reserve, not including any reserved by using
+ * JSCLASS_HAS_RESERVED_SLOTS(n) in JSClass.flags.
+ *
+ * NB: called with obj locked by the JSObjectOps-specific mutual exclusion
+ * mechanism appropriate for obj, so don't nest other operations that might
+ * also lock obj.
+ */
+typedef uint32
+(* JSReserveSlotsOp)(JSContext *cx, JSObject *obj);
+
+/* JSObjectOps function pointer typedefs. */
+
+/*
+ * Create a new subclass of JSObjectMap (see jsobj.h), with the nrefs and ops
+ * members initialized from the same-named parameters, and with the nslots and
+ * freeslot members initialized according to ops and clasp. Return null on
+ * error, non-null on success.
+ *
+ * JSObjectMaps are reference-counted by generic code in the engine. Usually,
+ * the nrefs parameter to JSObjectOps.newObjectMap will be 1, to count the ref
+ * returned to the caller on success. After a successful construction, some
+ * number of js_HoldObjectMap and js_DropObjectMap calls ensue. When nrefs
+ * reaches 0 due to a js_DropObjectMap call, JSObjectOps.destroyObjectMap will
+ * be called to dispose of the map.
+ */
+typedef JSObjectMap *
+(* JSNewObjectMapOp)(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops,
+ JSClass *clasp, JSObject *obj);
+
+/*
+ * Generic type for an infallible JSObjectMap operation, used currently by
+ * JSObjectOps.destroyObjectMap.
+ */
+typedef void
+(* JSObjectMapOp)(JSContext *cx, JSObjectMap *map);
+
+/*
+ * Look for id in obj and its prototype chain, returning false on error or
+ * exception, true on success. On success, return null in *propp if id was
+ * not found. If id was found, return the first object searching from obj
+ * along its prototype chain in which id names a direct property in *objp, and
+ * return a non-null, opaque property pointer in *propp.
+ *
+ * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
+ * may be passed as the prop parameter to a JSAttributesOp, as a short-cut
+ * that bypasses id re-lookup. In any case, a non-null *propp result after a
+ * successful lookup must be dropped via JSObjectOps.dropProperty.
+ *
+ * NB: successful return with non-null *propp means the implementation may
+ * have locked *objp and added a reference count associated with *propp, so
+ * callers should not risk deadlock by nesting or interleaving other lookups
+ * or any obj-bearing ops before dropping *propp.
+ */
+typedef JSBool
+(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp);
+
+/*
+ * Define obj[id], a direct property of obj named id, having the given initial
+ * value, with the specified getter, setter, and attributes. If the propp out
+ * param is non-null, *propp on successful return contains an opaque property
+ * pointer usable as a speedup hint with JSAttributesOp. But note that propp
+ * may be null, indicating that the caller is not interested in recovering an
+ * opaque pointer to the newly-defined property.
+ *
+ * If propp is non-null and JSDefinePropOp succeeds, its caller must be sure
+ * to drop *propp using JSObjectOps.dropProperty in short order, just as with
+ * JSLookupPropOp.
+ */
+typedef JSBool
+(* JSDefinePropOp)(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp);
+
+/*
+ * Get, set, or delete obj[id], returning false on error or exception, true
+ * on success. If getting or setting, the new value is returned in *vp on
+ * success. If deleting without error, *vp will be JSVAL_FALSE if obj[id] is
+ * permanent, and JSVAL_TRUE if id named a direct property of obj that was in
+ * fact deleted, or if id names no direct property of obj (id could name a
+ * prototype property, or no property in obj or its prototype chain).
+ */
+typedef JSBool
+(* JSPropertyIdOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+/*
+ * Get or set attributes of the property obj[id]. Return false on error or
+ * exception, true with current attributes in *attrsp. If prop is non-null,
+ * it must come from the *propp out parameter of a prior JSDefinePropOp or
+ * JSLookupPropOp call.
+ */
+typedef JSBool
+(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp);
+
+/*
+ * JSObjectOps.checkAccess type: check whether obj[id] may be accessed per
+ * mode, returning false on error/exception, true on success with obj[id]'s
+ * last-got value in *vp, and its attributes in *attrsp.
+ */
+typedef JSBool
+(* JSCheckAccessIdOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
+ jsval *vp, uintN *attrsp);
+
+/*
+ * A generic type for functions mapping an object to another object, or null
+ * if an error or exception was thrown on cx. Used by JSObjectOps.thisObject
+ * at present.
+ */
+typedef JSObject *
+(* JSObjectOp)(JSContext *cx, JSObject *obj);
+
+/*
+ * Hook that creates an iterator object for a given object. Returns the
+ * iterator object or null if an error or exception was thrown on cx.
+ */
+typedef JSObject *
+(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
+
+/*
+ * A generic type for functions taking a context, object, and property, with
+ * no return value. Used by JSObjectOps.dropProperty currently (see above,
+ * JSDefinePropOp and JSLookupPropOp, for the object-locking protocol in which
+ * dropProperty participates).
+ */
+typedef void
+(* JSPropertyRefOp)(JSContext *cx, JSObject *obj, JSProperty *prop);
+
+/*
+ * Function pointer type for JSObjectOps.setProto and JSObjectOps.setParent.
+ * These hooks must check for cycles without deadlocking, and otherwise take
+ * special steps. See jsobj.c and jsgc.c for details.
+ */
+typedef JSBool
+(* JSSetObjectSlotOp)(JSContext *cx, JSObject *obj, uint32 slot,
+ JSObject *pobj);
+
+/*
+ * Get and set a required slot, one that should already have been allocated.
+ * These operations are infallible, so required slots must be pre-allocated,
+ * or implementations must suppress out-of-memory errors. The native ops
+ * (js_ObjectOps, see jsobj.c) access slots reserved by including a call to
+ * the JSCLASS_HAS_RESERVED_SLOTS(n) macro in the JSClass.flags initializer.
+ *
+ * NB: the slot parameter is a zero-based index into obj slots, unlike the
+ * index parameter to the JS_GetReservedSlot and JS_SetReservedSlot API entry
+ * points, which is a zero-based index into the JSCLASS_RESERVED_SLOTS(clasp)
+ * reserved slots that come after the initial well-known slots: proto, parent,
+ * class, and optionally, the private data slot.
+ */
+typedef jsval
+(* JSGetRequiredSlotOp)(JSContext *cx, JSObject *obj, uint32 slot);
+
+typedef JSBool
+(* JSSetRequiredSlotOp)(JSContext *cx, JSObject *obj, uint32 slot, jsval v);
+
+typedef JSObject *
+(* JSGetMethodOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+typedef JSBool
+(* JSSetMethodOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+typedef JSBool
+(* JSEnumerateValuesOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp, jsval *vp);
+
+typedef JSBool
+(* JSEqualityOp)(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+typedef JSBool
+(* JSConcatenateOp)(JSContext *cx, JSObject *obj, jsval v, jsval *vp);
+
+/* Typedef for native functions called by the JS VM. */
+
+typedef JSBool
+(* JSNative)(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+/* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros. */
+typedef JSBool
+(* JSFastNative)(JSContext *cx, uintN argc, jsval *vp);
+
+/* Callbacks and their arguments. */
+
+typedef enum JSContextOp {
+ JSCONTEXT_NEW,
+ JSCONTEXT_DESTROY
+} JSContextOp;
+
+/*
+ * The possible values for contextOp when the runtime calls the callback are:
+ * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
+ * instance. The callback can initialize the instance as
+ * required. If the callback returns false, the instance
+ * will be destroyed and JS_NewContext returns null. In
+ * this case the callback is not called again.
+ * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
+ * callback may perform its own cleanup and must always
+ * return true.
+ * Any other value For future compatibility the callback must do nothing
+ * and return true in this case.
+ */
+typedef JSBool
+(* JSContextCallback)(JSContext *cx, uintN contextOp);
+
+typedef enum JSGCStatus {
+ JSGC_BEGIN,
+ JSGC_END,
+ JSGC_MARK_END,
+ JSGC_FINALIZE_END
+} JSGCStatus;
+
+typedef JSBool
+(* JSGCCallback)(JSContext *cx, JSGCStatus status);
+
+/*
+ * Generic trace operation that calls JS_CallTracer on each traceable thing
+ * stored in data.
+ */
+typedef void
+(* JSTraceDataOp)(JSTracer *trc, void *data);
+
+typedef JSBool
+(* JSOperationCallback)(JSContext *cx);
+
+/*
+ * Deprecated form of JSOperationCallback.
+ */
+typedef JSBool
+(* JSBranchCallback)(JSContext *cx, JSScript *script);
+
+typedef void
+(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
+
+/*
+ * Possible exception types. These types are part of a JSErrorFormatString
+ * structure. They define which error to throw in case of a runtime error.
+ * JSEXN_NONE marks an unthrowable error.
+ */
+typedef enum JSExnType {
+ JSEXN_NONE = -1,
+ JSEXN_ERR,
+ JSEXN_INTERNALERR,
+ JSEXN_EVALERR,
+ JSEXN_RANGEERR,
+ JSEXN_REFERENCEERR,
+ JSEXN_SYNTAXERR,
+ JSEXN_TYPEERR,
+ JSEXN_URIERR,
+ JSEXN_LIMIT
+} JSExnType;
+
+typedef struct JSErrorFormatString {
+ /* The error format string (UTF-8 if js_CStringsAreUTF8). */
+ const char *format;
+
+ /* The number of arguments to expand in the formatted error message. */
+ uint16 argCount;
+
+ /* One of the JSExnType constants above. */
+ int16 exnType;
+} JSErrorFormatString;
+
+typedef const JSErrorFormatString *
+(* JSErrorCallback)(void *userRef, const char *locale,
+ const uintN errorNumber);
+
+#ifdef va_start
+#define JS_ARGUMENT_FORMATTER_DEFINED 1
+
+typedef JSBool
+(* JSArgumentFormatter)(JSContext *cx, const char *format, JSBool fromJS,
+ jsval **vpp, va_list *app);
+#endif
+
+typedef JSBool
+(* JSLocaleToUpperCase)(JSContext *cx, JSString *src, jsval *rval);
+
+typedef JSBool
+(* JSLocaleToLowerCase)(JSContext *cx, JSString *src, jsval *rval);
+
+typedef JSBool
+(* JSLocaleCompare)(JSContext *cx, JSString *src1, JSString *src2,
+ jsval *rval);
+
+typedef JSBool
+(* JSLocaleToUnicode)(JSContext *cx, char *src, jsval *rval);
+
+/*
+ * Security protocol types.
+ */
+typedef struct JSPrincipals JSPrincipals;
+
+/*
+ * XDR-encode or -decode a principals instance, based on whether xdr->mode is
+ * JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
+ * in which case implementations must return a held (via JSPRINCIPALS_HOLD),
+ * non-null *principalsp out parameter. Return true on success, false on any
+ * error, which the implementation must have reported.
+ */
+typedef JSBool
+(* JSPrincipalsTranscoder)(JSXDRState *xdr, JSPrincipals **principalsp);
+
+/*
+ * Return a weak reference to the principals associated with obj, possibly via
+ * the immutable parent chain leading from obj to a top-level container (e.g.,
+ * a window object in the DOM level 0). If there are no principals associated
+ * with obj, return null. Therefore null does not mean an error was reported;
+ * in no event should an error be reported or an exception be thrown by this
+ * callback's implementation.
+ */
+typedef JSPrincipals *
+(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
+
+JS_END_EXTERN_C
+
+#endif /* jspubtd_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp
new file mode 100644
index 0000000..778f342
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.cpp
@@ -0,0 +1,4772 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS regular expressions, after Perl.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+#ifdef JS_TRACER
+#include "jstracer.h"
+using namespace avmplus;
+using namespace nanojit;
+
+/*
+ * FIXME Duplicated with jstracer.cpp, doing it this way for now
+ * to keep it private to files that need it.
+ */
+#ifdef JS_JIT_SPEW
+static bool verbose_debug = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "verbose");
+#define debug_only_v(x) if (verbose_debug) { x; }
+#else
+#define debug_only_v(x)
+#endif
+#endif
+
+typedef enum REOp {
+#define REOP_DEF(opcode, name) opcode,
+#include "jsreops.tbl"
+#undef REOP_DEF
+ REOP_LIMIT /* META: no operator >= to this */
+} REOp;
+
+#define REOP_IS_SIMPLE(op) ((op) <= REOP_NCLASS)
+
+#ifdef REGEXP_DEBUG
+const char *reop_names[] = {
+#define REOP_DEF(opcode, name) name,
+#include "jsreops.tbl"
+#undef REOP_DEF
+ NULL
+};
+#endif
+
+#ifdef __GNUC__
+static int
+re_debug(const char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
+#endif
+
+#ifdef REGEXP_DEBUG
+static int
+re_debug(const char *fmt, ...)
+{
+ va_list ap;
+ int retval;
+
+ va_start(ap, fmt);
+ retval = vprintf(fmt, ap);
+ va_end(ap);
+ return retval;
+}
+
+static void
+re_debug_chars(const jschar *chrs, size_t length)
+{
+ int i = 0;
+
+ printf(" \"");
+ while (*chrs && i++ < length) {
+ putchar((char)*chrs++);
+ }
+ printf("\"");
+}
+#else /* !REGEXP_DEBUG */
+/* This should be optimized to a no-op by our tier-1 compilers. */
+static int
+re_debug(const char *fmt, ...)
+{
+ return 0;
+}
+
+static void
+re_debug_chars(const jschar *chrs, size_t length)
+{
+}
+#endif /* !REGEXP_DEBUG */
+
+struct RENode {
+ REOp op; /* r.e. op bytecode */
+ RENode *next; /* next in concatenation order */
+ void *kid; /* first operand */
+ union {
+ void *kid2; /* second operand */
+ jsint num; /* could be a number */
+ size_t parenIndex; /* or a parenthesis index */
+ struct { /* or a quantifier range */
+ uintN min;
+ uintN max;
+ JSPackedBool greedy;
+ } range;
+ struct { /* or a character class */
+ size_t startIndex;
+ size_t kidlen; /* length of string at kid, in jschars */
+ size_t index; /* index into class list */
+ uint16 bmsize; /* bitmap size, based on max char code */
+ JSPackedBool sense;
+ } ucclass;
+ struct { /* or a literal sequence */
+ jschar chr; /* of one character */
+ size_t length; /* or many (via the kid) */
+ } flat;
+ struct {
+ RENode *kid2; /* second operand from ALT */
+ jschar ch1; /* match char for ALTPREREQ */
+ jschar ch2; /* ditto, or class index for ALTPREREQ2 */
+ } altprereq;
+ } u;
+};
+
+#define RE_IS_LETTER(c) (((c >= 'A') && (c <= 'Z')) || \
+ ((c >= 'a') && (c <= 'z')) )
+#define RE_IS_LINE_TERM(c) ((c == '\n') || (c == '\r') || \
+ (c == LINE_SEPARATOR) || (c == PARA_SEPARATOR))
+
+#define CLASS_CACHE_SIZE 4
+
+typedef struct CompilerState {
+ JSContext *context;
+ JSTokenStream *tokenStream; /* For reporting errors */
+ const jschar *cpbegin;
+ const jschar *cpend;
+ const jschar *cp;
+ size_t parenCount;
+ size_t classCount; /* number of [] encountered */
+ size_t treeDepth; /* maximum depth of parse tree */
+ size_t progLength; /* estimated bytecode length */
+ RENode *result;
+ size_t classBitmapsMem; /* memory to hold all class bitmaps */
+ struct {
+ const jschar *start; /* small cache of class strings */
+ size_t length; /* since they're often the same */
+ size_t index;
+ } classCache[CLASS_CACHE_SIZE];
+ uint16 flags;
+} CompilerState;
+
+typedef struct EmitStateStackEntry {
+ jsbytecode *altHead; /* start of REOP_ALT* opcode */
+ jsbytecode *nextAltFixup; /* fixup pointer to next-alt offset */
+ jsbytecode *nextTermFixup; /* fixup ptr. to REOP_JUMP offset */
+ jsbytecode *endTermFixup; /* fixup ptr. to REOPT_ALTPREREQ* offset */
+ RENode *continueNode; /* original REOP_ALT* node being stacked */
+ jsbytecode continueOp; /* REOP_JUMP or REOP_ENDALT continuation */
+ JSPackedBool jumpToJumpFlag; /* true if we've patched jump-to-jump to
+ avoid 16-bit unsigned offset overflow */
+} EmitStateStackEntry;
+
+/*
+ * Immediate operand sizes and getter/setters. Unlike the ones in jsopcode.h,
+ * the getters and setters take the pc of the offset, not of the opcode before
+ * the offset.
+ */
+#define ARG_LEN 2
+#define GET_ARG(pc) ((uint16)(((pc)[0] << 8) | (pc)[1]))
+#define SET_ARG(pc, arg) ((pc)[0] = (jsbytecode) ((arg) >> 8), \
+ (pc)[1] = (jsbytecode) (arg))
+
+#define OFFSET_LEN ARG_LEN
+#define OFFSET_MAX (JS_BIT(ARG_LEN * 8) - 1)
+#define GET_OFFSET(pc) GET_ARG(pc)
+
+/*
+ * Maximum supported tree depth is maximum size of EmitStateStackEntry stack.
+ * For sanity, we limit it to 2^24 bytes.
+ */
+#define TREE_DEPTH_MAX (JS_BIT(24) / sizeof(EmitStateStackEntry))
+
+/*
+ * The maximum memory that can be allocated for class bitmaps.
+ * For sanity, we limit it to 2^24 bytes.
+ */
+#define CLASS_BITMAPS_MEM_LIMIT JS_BIT(24)
+
+/*
+ * Functions to get size and write/read bytecode that represent small indexes
+ * compactly.
+ * Each byte in the code represent 7-bit chunk of the index. 8th bit when set
+ * indicates that the following byte brings more bits to the index. Otherwise
+ * this is the last byte in the index bytecode representing highest index bits.
+ */
+static size_t
+GetCompactIndexWidth(size_t index)
+{
+ size_t width;
+
+ for (width = 1; (index >>= 7) != 0; ++width) { }
+ return width;
+}
+
+static JS_ALWAYS_INLINE jsbytecode *
+WriteCompactIndex(jsbytecode *pc, size_t index)
+{
+ size_t next;
+
+ while ((next = index >> 7) != 0) {
+ *pc++ = (jsbytecode)(index | 0x80);
+ index = next;
+ }
+ *pc++ = (jsbytecode)index;
+ return pc;
+}
+
+static JS_ALWAYS_INLINE jsbytecode *
+ReadCompactIndex(jsbytecode *pc, size_t *result)
+{
+ size_t nextByte;
+
+ nextByte = *pc++;
+ if ((nextByte & 0x80) == 0) {
+ /*
+ * Short-circuit the most common case when compact index <= 127.
+ */
+ *result = nextByte;
+ } else {
+ size_t shift = 7;
+ *result = 0x7F & nextByte;
+ do {
+ nextByte = *pc++;
+ *result |= (nextByte & 0x7F) << shift;
+ shift += 7;
+ } while ((nextByte & 0x80) != 0);
+ }
+ return pc;
+}
+
+typedef struct RECapture {
+ ptrdiff_t index; /* start of contents, -1 for empty */
+ size_t length; /* length of capture */
+} RECapture;
+
+typedef struct REMatchState {
+ const jschar *cp;
+ RECapture parens[1]; /* first of 're->parenCount' captures,
+ allocated at end of this struct */
+} REMatchState;
+
+struct REBackTrackData;
+
+typedef struct REProgState {
+ jsbytecode *continue_pc; /* current continuation data */
+ jsbytecode continue_op;
+ ptrdiff_t index; /* progress in text */
+ size_t parenSoFar; /* highest indexed paren started */
+ union {
+ struct {
+ uintN min; /* current quantifier limits */
+ uintN max;
+ } quantifier;
+ struct {
+ size_t top; /* backtrack stack state */
+ size_t sz;
+ } assertion;
+ } u;
+} REProgState;
+
+typedef struct REBackTrackData {
+ size_t sz; /* size of previous stack entry */
+ jsbytecode *backtrack_pc; /* where to backtrack to */
+ jsbytecode backtrack_op;
+ const jschar *cp; /* index in text of match at backtrack */
+ size_t parenIndex; /* start index of saved paren contents */
+ size_t parenCount; /* # of saved paren contents */
+ size_t saveStateStackTop; /* number of parent states */
+ /* saved parent states follow */
+ /* saved paren contents follow */
+} REBackTrackData;
+
+#define INITIAL_STATESTACK 100
+#define INITIAL_BACKTRACK 8000
+
+typedef struct REGlobalData {
+ JSContext *cx;
+ JSRegExp *regexp; /* the RE in execution */
+ JSBool ok; /* runtime error (out_of_memory only?) */
+ size_t start; /* offset to start at */
+ ptrdiff_t skipped; /* chars skipped anchoring this r.e. */
+ const jschar *cpbegin; /* text base address */
+ const jschar *cpend; /* text limit address */
+
+ REProgState *stateStack; /* stack of state of current parents */
+ size_t stateStackTop;
+ size_t stateStackLimit;
+
+ REBackTrackData *backTrackStack;/* stack of matched-so-far positions */
+ REBackTrackData *backTrackSP;
+ size_t backTrackStackSize;
+ size_t cursz; /* size of current stack entry */
+ size_t backTrackCount; /* how many times we've backtracked */
+ size_t backTrackLimit; /* upper limit on backtrack states */
+} REGlobalData;
+
+/*
+ * 1. If IgnoreCase is false, return ch.
+ * 2. Let u be ch converted to upper case as if by calling
+ * String.prototype.toUpperCase on the one-character string ch.
+ * 3. If u does not consist of a single character, return ch.
+ * 4. Let cu be u's character.
+ * 5. If ch's code point value is greater than or equal to decimal 128 and cu's
+ * code point value is less than decimal 128, then return ch.
+ * 6. Return cu.
+ */
+static JS_ALWAYS_INLINE uintN
+upcase(uintN ch)
+{
+ uintN cu;
+
+ JS_ASSERT((uintN) (jschar) ch == ch);
+ if (ch < 128) {
+ if (ch - (uintN) 'a' <= (uintN) ('z' - 'a'))
+ ch -= (uintN) ('a' - 'A');
+ return ch;
+ }
+
+ cu = JS_TOUPPER(ch);
+ return (cu < 128) ? ch : cu;
+}
+
+static JS_ALWAYS_INLINE uintN
+downcase(uintN ch)
+{
+ JS_ASSERT((uintN) (jschar) ch == ch);
+ if (ch < 128) {
+ if (ch - (uintN) 'A' <= (uintN) ('Z' - 'A'))
+ ch += (uintN) ('a' - 'A');
+ return ch;
+ }
+
+ return JS_TOLOWER(ch);
+}
+
+/* Construct and initialize an RENode, returning NULL for out-of-memory */
+static RENode *
+NewRENode(CompilerState *state, REOp op)
+{
+ JSContext *cx;
+ RENode *ren;
+
+ cx = state->context;
+ JS_ARENA_ALLOCATE_CAST(ren, RENode *, &cx->tempPool, sizeof *ren);
+ if (!ren) {
+ js_ReportOutOfScriptQuota(cx);
+ return NULL;
+ }
+ ren->op = op;
+ ren->next = NULL;
+ ren->kid = NULL;
+ return ren;
+}
+
+/*
+ * Validates and converts hex ascii value.
+ */
+static JSBool
+isASCIIHexDigit(jschar c, uintN *digit)
+{
+ uintN cv = c;
+
+ if (cv < '0')
+ return JS_FALSE;
+ if (cv <= '9') {
+ *digit = cv - '0';
+ return JS_TRUE;
+ }
+ cv |= 0x20;
+ if (cv >= 'a' && cv <= 'f') {
+ *digit = cv - 'a' + 10;
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+
+typedef struct {
+ REOp op;
+ const jschar *errPos;
+ size_t parenIndex;
+} REOpData;
+
+static JSBool
+ReportRegExpErrorHelper(CompilerState *state, uintN flags, uintN errorNumber,
+ const jschar *arg)
+{
+ if (state->tokenStream) {
+ return js_ReportCompileErrorNumber(state->context, state->tokenStream,
+ NULL, JSREPORT_UC | flags,
+ errorNumber, arg);
+ }
+ return JS_ReportErrorFlagsAndNumberUC(state->context, flags,
+ js_GetErrorMessage, NULL,
+ errorNumber, arg);
+}
+
+static JSBool
+ReportRegExpError(CompilerState *state, uintN flags, uintN errorNumber)
+{
+ return ReportRegExpErrorHelper(state, flags, errorNumber, NULL);
+}
+
+/*
+ * Process the op against the two top operands, reducing them to a single
+ * operand in the penultimate slot. Update progLength and treeDepth.
+ */
+static JSBool
+ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack,
+ intN operandSP)
+{
+ RENode *result;
+
+ switch (opData->op) {
+ case REOP_ALT:
+ result = NewRENode(state, REOP_ALT);
+ if (!result)
+ return JS_FALSE;
+ result->kid = operandStack[operandSP - 2];
+ result->u.kid2 = operandStack[operandSP - 1];
+ operandStack[operandSP - 2] = result;
+
+ if (state->treeDepth == TREE_DEPTH_MAX) {
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ return JS_FALSE;
+ }
+ ++state->treeDepth;
+
+ /*
+ * Look at both alternates to see if there's a FLAT or a CLASS at
+ * the start of each. If so, use a prerequisite match.
+ */
+ if (((RENode *) result->kid)->op == REOP_FLAT &&
+ ((RENode *) result->u.kid2)->op == REOP_FLAT &&
+ (state->flags & JSREG_FOLD) == 0) {
+ result->op = REOP_ALTPREREQ;
+ result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;
+ result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr;
+ /* ALTPREREQ, <end>, uch1, uch2, <next>, ...,
+ JUMP, <end> ... ENDALT */
+ state->progLength += 13;
+ }
+ else
+ if (((RENode *) result->kid)->op == REOP_CLASS &&
+ ((RENode *) result->kid)->u.ucclass.index < 256 &&
+ ((RENode *) result->u.kid2)->op == REOP_FLAT &&
+ (state->flags & JSREG_FOLD) == 0) {
+ result->op = REOP_ALTPREREQ2;
+ result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr;
+ result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index;
+ /* ALTPREREQ2, <end>, uch1, uch2, <next>, ...,
+ JUMP, <end> ... ENDALT */
+ state->progLength += 13;
+ }
+ else
+ if (((RENode *) result->kid)->op == REOP_FLAT &&
+ ((RENode *) result->u.kid2)->op == REOP_CLASS &&
+ ((RENode *) result->u.kid2)->u.ucclass.index < 256 &&
+ (state->flags & JSREG_FOLD) == 0) {
+ result->op = REOP_ALTPREREQ2;
+ result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr;
+ result->u.altprereq.ch2 =
+ ((RENode *) result->u.kid2)->u.ucclass.index;
+ /* ALTPREREQ2, <end>, uch1, uch2, <next>, ...,
+ JUMP, <end> ... ENDALT */
+ state->progLength += 13;
+ }
+ else {
+ /* ALT, <next>, ..., JUMP, <end> ... ENDALT */
+ state->progLength += 7;
+ }
+ break;
+
+ case REOP_CONCAT:
+ result = operandStack[operandSP - 2];
+ while (result->next)
+ result = result->next;
+ result->next = operandStack[operandSP - 1];
+ break;
+
+ case REOP_ASSERT:
+ case REOP_ASSERT_NOT:
+ case REOP_LPARENNON:
+ case REOP_LPAREN:
+ /* These should have been processed by a close paren. */
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR, JSMSG_MISSING_PAREN,
+ opData->errPos);
+ return JS_FALSE;
+
+ default:;
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Parser forward declarations.
+ */
+static JSBool ParseTerm(CompilerState *state);
+static JSBool ParseQuantifier(CompilerState *state);
+static intN ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues);
+
+/*
+ * Top-down regular expression grammar, based closely on Perl4.
+ *
+ * regexp: altern A regular expression is one or more
+ * altern '|' regexp alternatives separated by vertical bar.
+ */
+#define INITIAL_STACK_SIZE 128
+
+static JSBool
+ParseRegExp(CompilerState *state)
+{
+ size_t parenIndex;
+ RENode *operand;
+ REOpData *operatorStack;
+ RENode **operandStack;
+ REOp op;
+ intN i;
+ JSBool result = JS_FALSE;
+
+ intN operatorSP = 0, operatorStackSize = INITIAL_STACK_SIZE;
+ intN operandSP = 0, operandStackSize = INITIAL_STACK_SIZE;
+
+ /* Watch out for empty regexp */
+ if (state->cp == state->cpend) {
+ state->result = NewRENode(state, REOP_EMPTY);
+ return (state->result != NULL);
+ }
+
+ operatorStack = (REOpData *)
+ JS_malloc(state->context, sizeof(REOpData) * operatorStackSize);
+ if (!operatorStack)
+ return JS_FALSE;
+
+ operandStack = (RENode **)
+ JS_malloc(state->context, sizeof(RENode *) * operandStackSize);
+ if (!operandStack)
+ goto out;
+
+ for (;;) {
+ parenIndex = state->parenCount;
+ if (state->cp == state->cpend) {
+ /*
+ * If we are at the end of the regexp and we're short one or more
+ * operands, the regexp must have the form /x|/ or some such, with
+ * left parentheses making us short more than one operand.
+ */
+ if (operatorSP >= operandSP) {
+ operand = NewRENode(state, REOP_EMPTY);
+ if (!operand)
+ goto out;
+ goto pushOperand;
+ }
+ } else {
+ switch (*state->cp) {
+ case '(':
+ ++state->cp;
+ if (state->cp + 1 < state->cpend &&
+ *state->cp == '?' &&
+ (state->cp[1] == '=' ||
+ state->cp[1] == '!' ||
+ state->cp[1] == ':')) {
+ switch (state->cp[1]) {
+ case '=':
+ op = REOP_ASSERT;
+ /* ASSERT, <next>, ... ASSERTTEST */
+ state->progLength += 4;
+ break;
+ case '!':
+ op = REOP_ASSERT_NOT;
+ /* ASSERTNOT, <next>, ... ASSERTNOTTEST */
+ state->progLength += 4;
+ break;
+ default:
+ op = REOP_LPARENNON;
+ break;
+ }
+ state->cp += 2;
+ } else {
+ op = REOP_LPAREN;
+ /* LPAREN, <index>, ... RPAREN, <index> */
+ state->progLength
+ += 2 * (1 + GetCompactIndexWidth(parenIndex));
+ state->parenCount++;
+ if (state->parenCount == 65535) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_TOO_MANY_PARENS);
+ goto out;
+ }
+ }
+ goto pushOperator;
+
+ case ')':
+ /*
+ * If there's no stacked open parenthesis, throw syntax error.
+ */
+ for (i = operatorSP - 1; ; i--) {
+ if (i < 0) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_UNMATCHED_RIGHT_PAREN);
+ goto out;
+ }
+ if (operatorStack[i].op == REOP_ASSERT ||
+ operatorStack[i].op == REOP_ASSERT_NOT ||
+ operatorStack[i].op == REOP_LPARENNON ||
+ operatorStack[i].op == REOP_LPAREN) {
+ break;
+ }
+ }
+ /* FALL THROUGH */
+
+ case '|':
+ /* Expected an operand before these, so make an empty one */
+ operand = NewRENode(state, REOP_EMPTY);
+ if (!operand)
+ goto out;
+ goto pushOperand;
+
+ default:
+ if (!ParseTerm(state))
+ goto out;
+ operand = state->result;
+pushOperand:
+ if (operandSP == operandStackSize) {
+ RENode **tmp;
+ operandStackSize += operandStackSize;
+ tmp = (RENode **)
+ JS_realloc(state->context, operandStack,
+ sizeof(RENode *) * operandStackSize);
+ if (!tmp)
+ goto out;
+ operandStack = tmp;
+ }
+ operandStack[operandSP++] = operand;
+ break;
+ }
+ }
+
+ /* At the end; process remaining operators. */
+restartOperator:
+ if (state->cp == state->cpend) {
+ while (operatorSP) {
+ --operatorSP;
+ if (!ProcessOp(state, &operatorStack[operatorSP],
+ operandStack, operandSP))
+ goto out;
+ --operandSP;
+ }
+ JS_ASSERT(operandSP == 1);
+ state->result = operandStack[0];
+ result = JS_TRUE;
+ goto out;
+ }
+
+ switch (*state->cp) {
+ case '|':
+ /* Process any stacked 'concat' operators */
+ ++state->cp;
+ while (operatorSP &&
+ operatorStack[operatorSP - 1].op == REOP_CONCAT) {
+ --operatorSP;
+ if (!ProcessOp(state, &operatorStack[operatorSP],
+ operandStack, operandSP)) {
+ goto out;
+ }
+ --operandSP;
+ }
+ op = REOP_ALT;
+ goto pushOperator;
+
+ case ')':
+ /*
+ * If there's no stacked open parenthesis, throw syntax error.
+ */
+ for (i = operatorSP - 1; ; i--) {
+ if (i < 0) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_UNMATCHED_RIGHT_PAREN);
+ goto out;
+ }
+ if (operatorStack[i].op == REOP_ASSERT ||
+ operatorStack[i].op == REOP_ASSERT_NOT ||
+ operatorStack[i].op == REOP_LPARENNON ||
+ operatorStack[i].op == REOP_LPAREN) {
+ break;
+ }
+ }
+ ++state->cp;
+
+ /* Process everything on the stack until the open parenthesis. */
+ for (;;) {
+ JS_ASSERT(operatorSP);
+ --operatorSP;
+ switch (operatorStack[operatorSP].op) {
+ case REOP_ASSERT:
+ case REOP_ASSERT_NOT:
+ case REOP_LPAREN:
+ operand = NewRENode(state, operatorStack[operatorSP].op);
+ if (!operand)
+ goto out;
+ operand->u.parenIndex =
+ operatorStack[operatorSP].parenIndex;
+ JS_ASSERT(operandSP);
+ operand->kid = operandStack[operandSP - 1];
+ operandStack[operandSP - 1] = operand;
+ if (state->treeDepth == TREE_DEPTH_MAX) {
+ ReportRegExpError(state, JSREPORT_ERROR,
+ JSMSG_REGEXP_TOO_COMPLEX);
+ goto out;
+ }
+ ++state->treeDepth;
+ /* FALL THROUGH */
+
+ case REOP_LPARENNON:
+ state->result = operandStack[operandSP - 1];
+ if (!ParseQuantifier(state))
+ goto out;
+ operandStack[operandSP - 1] = state->result;
+ goto restartOperator;
+ default:
+ if (!ProcessOp(state, &operatorStack[operatorSP],
+ operandStack, operandSP))
+ goto out;
+ --operandSP;
+ break;
+ }
+ }
+ break;
+
+ case '{':
+ {
+ const jschar *errp = state->cp;
+
+ if (ParseMinMaxQuantifier(state, JS_TRUE) < 0) {
+ /*
+ * This didn't even scan correctly as a quantifier, so we should
+ * treat it as flat.
+ */
+ op = REOP_CONCAT;
+ goto pushOperator;
+ }
+
+ state->cp = errp;
+ /* FALL THROUGH */
+ }
+
+ case '+':
+ case '*':
+ case '?':
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR, JSMSG_BAD_QUANTIFIER,
+ state->cp);
+ result = JS_FALSE;
+ goto out;
+
+ default:
+ /* Anything else is the start of the next term. */
+ op = REOP_CONCAT;
+pushOperator:
+ if (operatorSP == operatorStackSize) {
+ REOpData *tmp;
+ operatorStackSize += operatorStackSize;
+ tmp = (REOpData *)
+ JS_realloc(state->context, operatorStack,
+ sizeof(REOpData) * operatorStackSize);
+ if (!tmp)
+ goto out;
+ operatorStack = tmp;
+ }
+ operatorStack[operatorSP].op = op;
+ operatorStack[operatorSP].errPos = state->cp;
+ operatorStack[operatorSP++].parenIndex = parenIndex;
+ break;
+ }
+ }
+out:
+ if (operatorStack)
+ JS_free(state->context, operatorStack);
+ if (operandStack)
+ JS_free(state->context, operandStack);
+ return result;
+}
+
+/*
+ * Hack two bits in CompilerState.flags, for use within FindParenCount to flag
+ * its being on the stack, and to propagate errors to its callers.
+ */
+#define JSREG_FIND_PAREN_COUNT 0x8000
+#define JSREG_FIND_PAREN_ERROR 0x4000
+
+/*
+ * Magic return value from FindParenCount and GetDecimalValue, to indicate
+ * overflow beyond GetDecimalValue's max parameter, or a computed maximum if
+ * its findMax parameter is non-null.
+ */
+#define OVERFLOW_VALUE ((uintN)-1)
+
+static uintN
+FindParenCount(CompilerState *state)
+{
+ CompilerState temp;
+ int i;
+
+ if (state->flags & JSREG_FIND_PAREN_COUNT)
+ return OVERFLOW_VALUE;
+
+ /*
+ * Copy state into temp, flag it so we never report an invalid backref,
+ * and reset its members to parse the entire regexp. This is obviously
+ * suboptimal, but GetDecimalValue calls us only if a backref appears to
+ * refer to a forward parenthetical, which is rare.
+ */
+ temp = *state;
+ temp.flags |= JSREG_FIND_PAREN_COUNT;
+ temp.cp = temp.cpbegin;
+ temp.parenCount = 0;
+ temp.classCount = 0;
+ temp.progLength = 0;
+ temp.treeDepth = 0;
+ temp.classBitmapsMem = 0;
+ for (i = 0; i < CLASS_CACHE_SIZE; i++)
+ temp.classCache[i].start = NULL;
+
+ if (!ParseRegExp(&temp)) {
+ state->flags |= JSREG_FIND_PAREN_ERROR;
+ return OVERFLOW_VALUE;
+ }
+ return temp.parenCount;
+}
+
+/*
+ * Extract and return a decimal value at state->cp. The initial character c
+ * has already been read. Return OVERFLOW_VALUE if the result exceeds max.
+ * Callers who pass a non-null findMax should test JSREG_FIND_PAREN_ERROR in
+ * state->flags to discover whether an error occurred under findMax.
+ */
+static uintN
+GetDecimalValue(jschar c, uintN max, uintN (*findMax)(CompilerState *state),
+ CompilerState *state)
+{
+ uintN value = JS7_UNDEC(c);
+ JSBool overflow = (value > max && (!findMax || value > findMax(state)));
+
+ /* The following restriction allows simpler overflow checks. */
+ JS_ASSERT(max <= ((uintN)-1 - 9) / 10);
+ while (state->cp < state->cpend) {
+ c = *state->cp;
+ if (!JS7_ISDEC(c))
+ break;
+ value = 10 * value + JS7_UNDEC(c);
+ if (!overflow && value > max && (!findMax || value > findMax(state)))
+ overflow = JS_TRUE;
+ ++state->cp;
+ }
+ return overflow ? OVERFLOW_VALUE : value;
+}
+
+/*
+ * Calculate the total size of the bitmap required for a class expression.
+ */
+static JSBool
+CalculateBitmapSize(CompilerState *state, RENode *target, const jschar *src,
+ const jschar *end)
+{
+ uintN max = 0;
+ JSBool inRange = JS_FALSE;
+ jschar c, rangeStart = 0;
+ uintN n, digit, nDigits, i;
+
+ target->u.ucclass.bmsize = 0;
+ target->u.ucclass.sense = JS_TRUE;
+
+ if (src == end)
+ return JS_TRUE;
+
+ if (*src == '^') {
+ ++src;
+ target->u.ucclass.sense = JS_FALSE;
+ }
+
+ while (src != end) {
+ JSBool canStartRange = JS_TRUE;
+ uintN localMax = 0;
+
+ switch (*src) {
+ case '\\':
+ ++src;
+ c = *src++;
+ switch (c) {
+ case 'b':
+ localMax = 0x8;
+ break;
+ case 'f':
+ localMax = 0xC;
+ break;
+ case 'n':
+ localMax = 0xA;
+ break;
+ case 'r':
+ localMax = 0xD;
+ break;
+ case 't':
+ localMax = 0x9;
+ break;
+ case 'v':
+ localMax = 0xB;
+ break;
+ case 'c':
+ if (src < end && RE_IS_LETTER(*src)) {
+ localMax = (uintN) (*src++) & 0x1F;
+ } else {
+ --src;
+ localMax = '\\';
+ }
+ break;
+ case 'x':
+ nDigits = 2;
+ goto lexHex;
+ case 'u':
+ nDigits = 4;
+lexHex:
+ n = 0;
+ for (i = 0; (i < nDigits) && (src < end); i++) {
+ c = *src++;
+ if (!isASCIIHexDigit(c, &digit)) {
+ /*
+ * Back off to accepting the original
+ *'\' as a literal.
+ */
+ src -= i + 1;
+ n = '\\';
+ break;
+ }
+ n = (n << 4) | digit;
+ }
+ localMax = n;
+ break;
+ case 'd':
+ canStartRange = JS_FALSE;
+ if (inRange) {
+ JS_ReportErrorNumber(state->context,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_CLASS_RANGE);
+ return JS_FALSE;
+ }
+ localMax = '9';
+ break;
+ case 'D':
+ case 's':
+ case 'S':
+ case 'w':
+ case 'W':
+ canStartRange = JS_FALSE;
+ if (inRange) {
+ JS_ReportErrorNumber(state->context,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_CLASS_RANGE);
+ return JS_FALSE;
+ }
+ max = 65535;
+
+ /*
+ * If this is the start of a range, ensure that it's less than
+ * the end.
+ */
+ localMax = 0;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ /*
+ * This is a non-ECMA extension - decimal escapes (in this
+ * case, octal!) are supposed to be an error inside class
+ * ranges, but supported here for backwards compatibility.
+ *
+ */
+ n = JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ n = 8 * n + JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ i = 8 * n + JS7_UNDEC(c);
+ if (i <= 0377)
+ n = i;
+ else
+ src--;
+ }
+ }
+ localMax = n;
+ break;
+
+ default:
+ localMax = c;
+ break;
+ }
+ break;
+ default:
+ localMax = *src++;
+ break;
+ }
+
+ if (inRange) {
+ /* Throw a SyntaxError here, per ECMA-262, 15.10.2.15. */
+ if (rangeStart > localMax) {
+ JS_ReportErrorNumber(state->context,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_CLASS_RANGE);
+ return JS_FALSE;
+ }
+ inRange = JS_FALSE;
+ } else {
+ if (canStartRange && src < end - 1) {
+ if (*src == '-') {
+ ++src;
+ inRange = JS_TRUE;
+ rangeStart = (jschar)localMax;
+ continue;
+ }
+ }
+ if (state->flags & JSREG_FOLD)
+ rangeStart = localMax; /* one run of the uc/dc loop below */
+ }
+
+ if (state->flags & JSREG_FOLD) {
+ jschar maxch = localMax;
+
+ for (i = rangeStart; i <= localMax; i++) {
+ jschar uch, dch;
+
+ uch = upcase(i);
+ dch = downcase(i);
+ maxch = JS_MAX(maxch, uch);
+ maxch = JS_MAX(maxch, dch);
+ }
+ localMax = maxch;
+ }
+
+ if (localMax > max)
+ max = localMax;
+ }
+ target->u.ucclass.bmsize = max;
+ return JS_TRUE;
+}
+
+/*
+ * item: assertion An item is either an assertion or
+ * quantatom a quantified atom.
+ *
+ * assertion: '^' Assertions match beginning of string
+ * (or line if the class static property
+ * RegExp.multiline is true).
+ * '$' End of string (or line if the class
+ * static property RegExp.multiline is
+ * true).
+ * '\b' Word boundary (between \w and \W).
+ * '\B' Word non-boundary.
+ *
+ * quantatom: atom An unquantified atom.
+ * quantatom '{' n ',' m '}'
+ * Atom must occur between n and m times.
+ * quantatom '{' n ',' '}' Atom must occur at least n times.
+ * quantatom '{' n '}' Atom must occur exactly n times.
+ * quantatom '*' Zero or more times (same as {0,}).
+ * quantatom '+' One or more times (same as {1,}).
+ * quantatom '?' Zero or one time (same as {0,1}).
+ *
+ * any of which can be optionally followed by '?' for ungreedy
+ *
+ * atom: '(' regexp ')' A parenthesized regexp (what matched
+ * can be addressed using a backreference,
+ * see '\' n below).
+ * '.' Matches any char except '\n'.
+ * '[' classlist ']' A character class.
+ * '[' '^' classlist ']' A negated character class.
+ * '\f' Form Feed.
+ * '\n' Newline (Line Feed).
+ * '\r' Carriage Return.
+ * '\t' Horizontal Tab.
+ * '\v' Vertical Tab.
+ * '\d' A digit (same as [0-9]).
+ * '\D' A non-digit.
+ * '\w' A word character, [0-9a-z_A-Z].
+ * '\W' A non-word character.
+ * '\s' A whitespace character, [ \b\f\n\r\t\v].
+ * '\S' A non-whitespace character.
+ * '\' n A backreference to the nth (n decimal
+ * and positive) parenthesized expression.
+ * '\' octal An octal escape sequence (octal must be
+ * two or three digits long, unless it is
+ * 0 for the null character).
+ * '\x' hex A hex escape (hex must be two digits).
+ * '\u' unicode A unicode escape (must be four digits).
+ * '\c' ctrl A control character, ctrl is a letter.
+ * '\' literalatomchar Any character except one of the above
+ * that follow '\' in an atom.
+ * otheratomchar Any character not first among the other
+ * atom right-hand sides.
+ */
+static JSBool
+ParseTerm(CompilerState *state)
+{
+ jschar c = *state->cp++;
+ uintN nDigits;
+ uintN num, tmp, n, i;
+ const jschar *termStart;
+
+ switch (c) {
+ /* assertions and atoms */
+ case '^':
+ state->result = NewRENode(state, REOP_BOL);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ case '$':
+ state->result = NewRENode(state, REOP_EOL);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ case '\\':
+ if (state->cp >= state->cpend) {
+ /* a trailing '\' is an error */
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_TRAILING_SLASH);
+ return JS_FALSE;
+ }
+ c = *state->cp++;
+ switch (c) {
+ /* assertion escapes */
+ case 'b' :
+ state->result = NewRENode(state, REOP_WBDRY);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ case 'B':
+ state->result = NewRENode(state, REOP_WNONBDRY);
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ return JS_TRUE;
+ /* Decimal escape */
+ case '0':
+ /* Give a strict warning. See also the note below. */
+ if (!ReportRegExpError(state, JSREPORT_WARNING | JSREPORT_STRICT,
+ JSMSG_INVALID_BACKREF)) {
+ return JS_FALSE;
+ }
+ doOctal:
+ num = 0;
+ while (state->cp < state->cpend) {
+ c = *state->cp;
+ if (c < '0' || '7' < c)
+ break;
+ state->cp++;
+ tmp = 8 * num + (uintN)JS7_UNDEC(c);
+ if (tmp > 0377)
+ break;
+ num = tmp;
+ }
+ c = (jschar)num;
+ doFlat:
+ state->result = NewRENode(state, REOP_FLAT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.flat.chr = c;
+ state->result->u.flat.length = 1;
+ state->progLength += 3;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ termStart = state->cp - 1;
+ num = GetDecimalValue(c, state->parenCount, FindParenCount, state);
+ if (state->flags & JSREG_FIND_PAREN_ERROR)
+ return JS_FALSE;
+ if (num == OVERFLOW_VALUE) {
+ /* Give a strict mode warning. */
+ if (!ReportRegExpError(state,
+ JSREPORT_WARNING | JSREPORT_STRICT,
+ (c >= '8')
+ ? JSMSG_INVALID_BACKREF
+ : JSMSG_BAD_BACKREF)) {
+ return JS_FALSE;
+ }
+
+ /*
+ * Note: ECMA 262, 15.10.2.9 says that we should throw a syntax
+ * error here. However, for compatibility with IE, we treat the
+ * whole backref as flat if the first character in it is not a
+ * valid octal character, and as an octal escape otherwise.
+ */
+ state->cp = termStart;
+ if (c >= '8') {
+ /* Treat this as flat. termStart - 1 is the \. */
+ c = '\\';
+ goto asFlat;
+ }
+
+ /* Treat this as an octal escape. */
+ goto doOctal;
+ }
+ JS_ASSERT(1 <= num && num <= 0x10000);
+ state->result = NewRENode(state, REOP_BACKREF);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.parenIndex = num - 1;
+ state->progLength
+ += 1 + GetCompactIndexWidth(state->result->u.parenIndex);
+ break;
+ /* Control escape */
+ case 'f':
+ c = 0xC;
+ goto doFlat;
+ case 'n':
+ c = 0xA;
+ goto doFlat;
+ case 'r':
+ c = 0xD;
+ goto doFlat;
+ case 't':
+ c = 0x9;
+ goto doFlat;
+ case 'v':
+ c = 0xB;
+ goto doFlat;
+ /* Control letter */
+ case 'c':
+ if (state->cp < state->cpend && RE_IS_LETTER(*state->cp)) {
+ c = (jschar) (*state->cp++ & 0x1F);
+ } else {
+ /* back off to accepting the original '\' as a literal */
+ --state->cp;
+ c = '\\';
+ }
+ goto doFlat;
+ /* HexEscapeSequence */
+ case 'x':
+ nDigits = 2;
+ goto lexHex;
+ /* UnicodeEscapeSequence */
+ case 'u':
+ nDigits = 4;
+lexHex:
+ n = 0;
+ for (i = 0; i < nDigits && state->cp < state->cpend; i++) {
+ uintN digit;
+ c = *state->cp++;
+ if (!isASCIIHexDigit(c, &digit)) {
+ /*
+ * Back off to accepting the original 'u' or 'x' as a
+ * literal.
+ */
+ state->cp -= i + 2;
+ n = *state->cp++;
+ break;
+ }
+ n = (n << 4) | digit;
+ }
+ c = (jschar) n;
+ goto doFlat;
+ /* Character class escapes */
+ case 'd':
+ state->result = NewRENode(state, REOP_DIGIT);
+doSimple:
+ if (!state->result)
+ return JS_FALSE;
+ state->progLength++;
+ break;
+ case 'D':
+ state->result = NewRENode(state, REOP_NONDIGIT);
+ goto doSimple;
+ case 's':
+ state->result = NewRENode(state, REOP_SPACE);
+ goto doSimple;
+ case 'S':
+ state->result = NewRENode(state, REOP_NONSPACE);
+ goto doSimple;
+ case 'w':
+ state->result = NewRENode(state, REOP_ALNUM);
+ goto doSimple;
+ case 'W':
+ state->result = NewRENode(state, REOP_NONALNUM);
+ goto doSimple;
+ /* IdentityEscape */
+ default:
+ state->result = NewRENode(state, REOP_FLAT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.flat.chr = c;
+ state->result->u.flat.length = 1;
+ state->result->kid = (void *) (state->cp - 1);
+ state->progLength += 3;
+ break;
+ }
+ break;
+ case '[':
+ state->result = NewRENode(state, REOP_CLASS);
+ if (!state->result)
+ return JS_FALSE;
+ termStart = state->cp;
+ state->result->u.ucclass.startIndex = termStart - state->cpbegin;
+ for (;;) {
+ if (state->cp == state->cpend) {
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR,
+ JSMSG_UNTERM_CLASS, termStart);
+
+ return JS_FALSE;
+ }
+ if (*state->cp == '\\') {
+ state->cp++;
+ if (state->cp != state->cpend)
+ state->cp++;
+ continue;
+ }
+ if (*state->cp == ']') {
+ state->result->u.ucclass.kidlen = state->cp - termStart;
+ break;
+ }
+ state->cp++;
+ }
+ for (i = 0; i < CLASS_CACHE_SIZE; i++) {
+ if (!state->classCache[i].start) {
+ state->classCache[i].start = termStart;
+ state->classCache[i].length = state->result->u.ucclass.kidlen;
+ state->classCache[i].index = state->classCount;
+ break;
+ }
+ if (state->classCache[i].length ==
+ state->result->u.ucclass.kidlen) {
+ for (n = 0; ; n++) {
+ if (n == state->classCache[i].length) {
+ state->result->u.ucclass.index
+ = state->classCache[i].index;
+ goto claim;
+ }
+ if (state->classCache[i].start[n] != termStart[n])
+ break;
+ }
+ }
+ }
+ state->result->u.ucclass.index = state->classCount++;
+
+ claim:
+ /*
+ * Call CalculateBitmapSize now as we want any errors it finds
+ * to be reported during the parse phase, not at execution.
+ */
+ if (!CalculateBitmapSize(state, state->result, termStart, state->cp++))
+ return JS_FALSE;
+ /*
+ * Update classBitmapsMem with number of bytes to hold bmsize bits,
+ * which is (bitsCount + 7) / 8 or (highest_bit + 1 + 7) / 8
+ * or highest_bit / 8 + 1 where highest_bit is u.ucclass.bmsize.
+ */
+ n = (state->result->u.ucclass.bmsize >> 3) + 1;
+ if (n > CLASS_BITMAPS_MEM_LIMIT - state->classBitmapsMem) {
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ return JS_FALSE;
+ }
+ state->classBitmapsMem += n;
+ /* CLASS, <index> */
+ state->progLength
+ += 1 + GetCompactIndexWidth(state->result->u.ucclass.index);
+ break;
+
+ case '.':
+ state->result = NewRENode(state, REOP_DOT);
+ goto doSimple;
+
+ case '{':
+ {
+ const jschar *errp = state->cp--;
+ intN err;
+
+ err = ParseMinMaxQuantifier(state, JS_TRUE);
+ state->cp = errp;
+
+ if (err < 0)
+ goto asFlat;
+
+ /* FALL THROUGH */
+ }
+ case '*':
+ case '+':
+ case '?':
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR,
+ JSMSG_BAD_QUANTIFIER, state->cp - 1);
+ return JS_FALSE;
+ default:
+asFlat:
+ state->result = NewRENode(state, REOP_FLAT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.flat.chr = c;
+ state->result->u.flat.length = 1;
+ state->result->kid = (void *) (state->cp - 1);
+ state->progLength += 3;
+ break;
+ }
+ return ParseQuantifier(state);
+}
+
+static JSBool
+ParseQuantifier(CompilerState *state)
+{
+ RENode *term;
+ term = state->result;
+ if (state->cp < state->cpend) {
+ switch (*state->cp) {
+ case '+':
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.range.min = 1;
+ state->result->u.range.max = (uintN)-1;
+ /* <PLUS>, <next> ... <ENDCHILD> */
+ state->progLength += 4;
+ goto quantifier;
+ case '*':
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.range.min = 0;
+ state->result->u.range.max = (uintN)-1;
+ /* <STAR>, <next> ... <ENDCHILD> */
+ state->progLength += 4;
+ goto quantifier;
+ case '?':
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JS_FALSE;
+ state->result->u.range.min = 0;
+ state->result->u.range.max = 1;
+ /* <OPT>, <next> ... <ENDCHILD> */
+ state->progLength += 4;
+ goto quantifier;
+ case '{': /* balance '}' */
+ {
+ intN err;
+ const jschar *errp = state->cp;
+
+ err = ParseMinMaxQuantifier(state, JS_FALSE);
+ if (err == 0)
+ goto quantifier;
+ if (err == -1)
+ return JS_TRUE;
+
+ ReportRegExpErrorHelper(state, JSREPORT_ERROR, err, errp);
+ return JS_FALSE;
+ }
+ default:;
+ }
+ }
+ return JS_TRUE;
+
+quantifier:
+ if (state->treeDepth == TREE_DEPTH_MAX) {
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ return JS_FALSE;
+ }
+
+ ++state->treeDepth;
+ ++state->cp;
+ state->result->kid = term;
+ if (state->cp < state->cpend && *state->cp == '?') {
+ ++state->cp;
+ state->result->u.range.greedy = JS_FALSE;
+ } else {
+ state->result->u.range.greedy = JS_TRUE;
+ }
+ return JS_TRUE;
+}
+
+static intN
+ParseMinMaxQuantifier(CompilerState *state, JSBool ignoreValues)
+{
+ uintN min, max;
+ jschar c;
+ const jschar *errp = state->cp++;
+
+ c = *state->cp;
+ if (JS7_ISDEC(c)) {
+ ++state->cp;
+ min = GetDecimalValue(c, 0xFFFF, NULL, state);
+ c = *state->cp;
+
+ if (!ignoreValues && min == OVERFLOW_VALUE)
+ return JSMSG_MIN_TOO_BIG;
+
+ if (c == ',') {
+ c = *++state->cp;
+ if (JS7_ISDEC(c)) {
+ ++state->cp;
+ max = GetDecimalValue(c, 0xFFFF, NULL, state);
+ c = *state->cp;
+ if (!ignoreValues && max == OVERFLOW_VALUE)
+ return JSMSG_MAX_TOO_BIG;
+ if (!ignoreValues && min > max)
+ return JSMSG_OUT_OF_ORDER;
+ } else {
+ max = (uintN)-1;
+ }
+ } else {
+ max = min;
+ }
+ if (c == '}') {
+ state->result = NewRENode(state, REOP_QUANT);
+ if (!state->result)
+ return JSMSG_OUT_OF_MEMORY;
+ state->result->u.range.min = min;
+ state->result->u.range.max = max;
+ /*
+ * QUANT, <min>, <max>, <next> ... <ENDCHILD>
+ * where <max> is written as compact(max+1) to make
+ * (uintN)-1 sentinel to occupy 1 byte, not width_of(max)+1.
+ */
+ state->progLength += (1 + GetCompactIndexWidth(min)
+ + GetCompactIndexWidth(max + 1)
+ +3);
+ return 0;
+ }
+ }
+
+ state->cp = errp;
+ return -1;
+}
+
+static JSBool
+SetForwardJumpOffset(jsbytecode *jump, jsbytecode *target)
+{
+ ptrdiff_t offset = target - jump;
+
+ /* Check that target really points forward. */
+ JS_ASSERT(offset >= 2);
+ if ((size_t)offset > OFFSET_MAX)
+ return JS_FALSE;
+
+ jump[0] = JUMP_OFFSET_HI(offset);
+ jump[1] = JUMP_OFFSET_LO(offset);
+ return JS_TRUE;
+}
+
+/* Copy the charset data from a character class node to the charset list
+ * in the regexp object. */
+static JS_ALWAYS_INLINE RECharSet *
+InitNodeCharSet(JSRegExp *re, RENode *node)
+{
+ RECharSet *charSet = &re->classList[node->u.ucclass.index];
+ charSet->converted = JS_FALSE;
+ charSet->length = node->u.ucclass.bmsize;
+ charSet->u.src.startIndex = node->u.ucclass.startIndex;
+ charSet->u.src.length = node->u.ucclass.kidlen;
+ charSet->sense = node->u.ucclass.sense;
+ return charSet;
+}
+
+/*
+ * Generate bytecode for the tree rooted at t using an explicit stack instead
+ * of recursion.
+ */
+static jsbytecode *
+EmitREBytecode(CompilerState *state, JSRegExp *re, size_t treeDepth,
+ jsbytecode *pc, RENode *t)
+{
+ EmitStateStackEntry *emitStateSP, *emitStateStack;
+ REOp op;
+
+ if (treeDepth == 0) {
+ emitStateStack = NULL;
+ } else {
+ emitStateStack =
+ (EmitStateStackEntry *)JS_malloc(state->context,
+ sizeof(EmitStateStackEntry) *
+ treeDepth);
+ if (!emitStateStack)
+ return NULL;
+ }
+ emitStateSP = emitStateStack;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+
+ for (;;) {
+ *pc++ = op;
+ switch (op) {
+ case REOP_EMPTY:
+ --pc;
+ break;
+
+ case REOP_ALTPREREQ2:
+ case REOP_ALTPREREQ:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->altHead = pc - 1;
+ emitStateSP->endTermFixup = pc;
+ pc += OFFSET_LEN;
+ SET_ARG(pc, t->u.altprereq.ch1);
+ pc += ARG_LEN;
+ SET_ARG(pc, t->u.altprereq.ch2);
+ pc += ARG_LEN;
+
+ emitStateSP->nextAltFixup = pc; /* offset to next alternate */
+ pc += OFFSET_LEN;
+
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_JUMP;
+ emitStateSP->jumpToJumpFlag = JS_FALSE;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+
+ case REOP_JUMP:
+ emitStateSP->nextTermFixup = pc; /* offset to following term */
+ pc += OFFSET_LEN;
+ if (!SetForwardJumpOffset(emitStateSP->nextAltFixup, pc))
+ goto jump_too_big;
+ emitStateSP->continueOp = REOP_ENDALT;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->u.kid2;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+
+ case REOP_ENDALT:
+ /*
+ * If we already patched emitStateSP->nextTermFixup to jump to
+ * a nearer jump, to avoid 16-bit immediate offset overflow, we
+ * are done here.
+ */
+ if (emitStateSP->jumpToJumpFlag)
+ break;
+
+ /*
+ * Fix up the REOP_JUMP offset to go to the op after REOP_ENDALT.
+ * REOP_ENDALT is executed only on successful match of the last
+ * alternate in a group.
+ */
+ if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc))
+ goto jump_too_big;
+ if (t->op != REOP_ALT) {
+ if (!SetForwardJumpOffset(emitStateSP->endTermFixup, pc))
+ goto jump_too_big;
+ }
+
+ /*
+ * If the program is bigger than the REOP_JUMP offset range, then
+ * we must check for alternates before this one that are part of
+ * the same group, and fix up their jump offsets to target jumps
+ * close enough to fit in a 16-bit unsigned offset immediate.
+ */
+ if ((size_t)(pc - re->program) > OFFSET_MAX &&
+ emitStateSP > emitStateStack) {
+ EmitStateStackEntry *esp, *esp2;
+ jsbytecode *alt, *jump;
+ ptrdiff_t span, header;
+
+ esp2 = emitStateSP;
+ alt = esp2->altHead;
+ for (esp = esp2 - 1; esp >= emitStateStack; --esp) {
+ if (esp->continueOp == REOP_ENDALT &&
+ !esp->jumpToJumpFlag &&
+ esp->nextTermFixup + OFFSET_LEN == alt &&
+ (size_t)(pc - ((esp->continueNode->op != REOP_ALT)
+ ? esp->endTermFixup
+ : esp->nextTermFixup)) > OFFSET_MAX) {
+ alt = esp->altHead;
+ jump = esp->nextTermFixup;
+
+ /*
+ * The span must be 1 less than the distance from
+ * jump offset to jump offset, so we actually jump
+ * to a REOP_JUMP bytecode, not to its offset!
+ */
+ for (;;) {
+ JS_ASSERT(jump < esp2->nextTermFixup);
+ span = esp2->nextTermFixup - jump - 1;
+ if ((size_t)span <= OFFSET_MAX)
+ break;
+ do {
+ if (--esp2 == esp)
+ goto jump_too_big;
+ } while (esp2->continueOp != REOP_ENDALT);
+ }
+
+ jump[0] = JUMP_OFFSET_HI(span);
+ jump[1] = JUMP_OFFSET_LO(span);
+
+ if (esp->continueNode->op != REOP_ALT) {
+ /*
+ * We must patch the offset at esp->endTermFixup
+ * as well, for the REOP_ALTPREREQ{,2} opcodes.
+ * If we're unlucky and endTermFixup is more than
+ * OFFSET_MAX bytes from its target, we cheat by
+ * jumping 6 bytes to the jump whose offset is at
+ * esp->nextTermFixup, which has the same target.
+ */
+ jump = esp->endTermFixup;
+ header = esp->nextTermFixup - jump;
+ span += header;
+ if ((size_t)span > OFFSET_MAX)
+ span = header;
+
+ jump[0] = JUMP_OFFSET_HI(span);
+ jump[1] = JUMP_OFFSET_LO(span);
+ }
+
+ esp->jumpToJumpFlag = JS_TRUE;
+ }
+ }
+ }
+ break;
+
+ case REOP_ALT:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->altHead = pc - 1;
+ emitStateSP->nextAltFixup = pc; /* offset to next alternate */
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_JUMP;
+ emitStateSP->jumpToJumpFlag = JS_FALSE;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+
+ case REOP_FLAT:
+ /*
+ * Coalesce FLATs if possible and if it would not increase bytecode
+ * beyond preallocated limit. The latter happens only when bytecode
+ * size for coalesced string with offset p and length 2 exceeds 6
+ * bytes preallocated for 2 single char nodes, i.e. when
+ * 1 + GetCompactIndexWidth(p) + GetCompactIndexWidth(2) > 6 or
+ * GetCompactIndexWidth(p) > 4.
+ * Since when GetCompactIndexWidth(p) <= 4 coalescing of 3 or more
+ * nodes strictly decreases bytecode size, the check has to be
+ * done only for the first coalescing.
+ */
+ if (t->kid &&
+ GetCompactIndexWidth((jschar *)t->kid - state->cpbegin) <= 4)
+ {
+ while (t->next &&
+ t->next->op == REOP_FLAT &&
+ (jschar*)t->kid + t->u.flat.length ==
+ (jschar*)t->next->kid) {
+ t->u.flat.length += t->next->u.flat.length;
+ t->next = t->next->next;
+ }
+ }
+ if (t->kid && t->u.flat.length > 1) {
+ pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLATi : REOP_FLAT;
+ pc = WriteCompactIndex(pc, (jschar *)t->kid - state->cpbegin);
+ pc = WriteCompactIndex(pc, t->u.flat.length);
+ } else if (t->u.flat.chr < 256) {
+ pc[-1] = (state->flags & JSREG_FOLD) ? REOP_FLAT1i : REOP_FLAT1;
+ *pc++ = (jsbytecode) t->u.flat.chr;
+ } else {
+ pc[-1] = (state->flags & JSREG_FOLD)
+ ? REOP_UCFLAT1i
+ : REOP_UCFLAT1;
+ SET_ARG(pc, t->u.flat.chr);
+ pc += ARG_LEN;
+ }
+ break;
+
+ case REOP_LPAREN:
+ JS_ASSERT(emitStateSP);
+ pc = WriteCompactIndex(pc, t->u.parenIndex);
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_RPAREN;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_RPAREN:
+ pc = WriteCompactIndex(pc, t->u.parenIndex);
+ break;
+
+ case REOP_BACKREF:
+ pc = WriteCompactIndex(pc, t->u.parenIndex);
+ break;
+
+ case REOP_ASSERT:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->nextTermFixup = pc;
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_ASSERTTEST;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_ASSERTTEST:
+ case REOP_ASSERTNOTTEST:
+ if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc))
+ goto jump_too_big;
+ break;
+
+ case REOP_ASSERT_NOT:
+ JS_ASSERT(emitStateSP);
+ emitStateSP->nextTermFixup = pc;
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_ASSERTNOTTEST;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_QUANT:
+ JS_ASSERT(emitStateSP);
+ if (t->u.range.min == 0 && t->u.range.max == (uintN)-1) {
+ pc[-1] = (t->u.range.greedy) ? REOP_STAR : REOP_MINIMALSTAR;
+ } else if (t->u.range.min == 0 && t->u.range.max == 1) {
+ pc[-1] = (t->u.range.greedy) ? REOP_OPT : REOP_MINIMALOPT;
+ } else if (t->u.range.min == 1 && t->u.range.max == (uintN) -1) {
+ pc[-1] = (t->u.range.greedy) ? REOP_PLUS : REOP_MINIMALPLUS;
+ } else {
+ if (!t->u.range.greedy)
+ pc[-1] = REOP_MINIMALQUANT;
+ pc = WriteCompactIndex(pc, t->u.range.min);
+ /*
+ * Write max + 1 to avoid using size_t(max) + 1 bytes
+ * for (uintN)-1 sentinel.
+ */
+ pc = WriteCompactIndex(pc, t->u.range.max + 1);
+ }
+ emitStateSP->nextTermFixup = pc;
+ pc += OFFSET_LEN;
+ emitStateSP->continueNode = t;
+ emitStateSP->continueOp = REOP_ENDCHILD;
+ ++emitStateSP;
+ JS_ASSERT((size_t)(emitStateSP - emitStateStack) <= treeDepth);
+ t = (RENode *) t->kid;
+ op = t->op;
+ continue;
+
+ case REOP_ENDCHILD:
+ if (!SetForwardJumpOffset(emitStateSP->nextTermFixup, pc))
+ goto jump_too_big;
+ break;
+
+ case REOP_CLASS:
+ if (!t->u.ucclass.sense)
+ pc[-1] = REOP_NCLASS;
+ pc = WriteCompactIndex(pc, t->u.ucclass.index);
+ InitNodeCharSet(re, t);
+ break;
+
+ default:
+ break;
+ }
+
+ t = t->next;
+ if (t) {
+ op = t->op;
+ } else {
+ if (emitStateSP == emitStateStack)
+ break;
+ --emitStateSP;
+ t = emitStateSP->continueNode;
+ op = (REOp) emitStateSP->continueOp;
+ }
+ }
+
+ cleanup:
+ if (emitStateStack)
+ JS_free(state->context, emitStateStack);
+ return pc;
+
+ jump_too_big:
+ ReportRegExpError(state, JSREPORT_ERROR, JSMSG_REGEXP_TOO_COMPLEX);
+ pc = NULL;
+ goto cleanup;
+}
+
+#ifdef JS_TRACER
+typedef List<LIns*, LIST_NonGCObjects> LInsList;
+
+/* Dummy GC for nanojit placement new. */
+static GC gc;
+
+class RegExpNativeCompiler {
+ private:
+ JSRegExp* re; /* Careful: not fully initialized */
+ CompilerState* cs; /* RegExp to compile */
+ Fragment* fragment;
+ LirWriter* lir;
+
+ LIns* state;
+ LIns* gdata;
+ LIns* cpend;
+
+ JSBool isCaseInsensitive() const { return cs->flags & JSREG_FOLD; }
+
+ void targetCurrentPoint(LIns* ins) { ins->target(lir->ins0(LIR_label)); }
+
+ void targetCurrentPoint(LInsList& fails)
+ {
+ LIns* fail = lir->ins0(LIR_label);
+ for (size_t i = 0; i < fails.size(); ++i) {
+ fails[i]->target(fail);
+ }
+ fails.clear();
+ }
+
+ /*
+ * These functions return the new position after their match operation,
+ * or NULL if there was an error.
+ */
+ LIns* compileEmpty(RENode* node, LIns* pos, LInsList& fails)
+ {
+ return pos;
+ }
+
+ LIns* compileFlatSingleChar(RENode* node, LIns* pos, LInsList& fails)
+ {
+ /*
+ * Fast case-insensitive test for ASCII letters: convert text
+ * char to lower case by bit-or-ing in 32 and compare.
+ */
+ JSBool useFastCI = JS_FALSE;
+ jschar ch = node->u.flat.chr; /* char to test for */
+ jschar ch2 = ch; /* 2nd char to test for if ci */
+ if (cs->flags & JSREG_FOLD) {
+ if (L'A' <= ch && ch <= L'Z' || L'a' <= ch || ch <= L'z') {
+ ch |= 32;
+ ch2 = ch;
+ useFastCI = JS_TRUE;
+ } else if (JS_TOLOWER(ch) != ch) {
+ ch2 = JS_TOLOWER(ch);
+ ch = JS_TOUPPER(ch);
+ }
+ }
+
+ LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_lt, pos, cpend), 0);
+ fails.add(to_fail);
+ LIns* text_ch = lir->insLoad(LIR_ldcs, pos, lir->insImm(0));
+ LIns* comp_ch = useFastCI ?
+ lir->ins2(LIR_or, text_ch, lir->insImm(32)) :
+ text_ch;
+ if (ch == ch2) {
+ fails.add(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, comp_ch, lir->insImm(ch)), 0));
+ } else {
+ LIns* to_ok = lir->insBranch(LIR_jt, lir->ins2(LIR_eq, comp_ch, lir->insImm(ch)), 0);
+ fails.add(lir->insBranch(LIR_jf, lir->ins2(LIR_eq, comp_ch, lir->insImm(ch2)), 0));
+ targetCurrentPoint(to_ok);
+ }
+
+ return lir->ins2(LIR_piadd, pos, lir->insImm(2));
+ }
+
+ LIns* compileClass(RENode* node, LIns* pos, LInsList& fails)
+ {
+ if (!node->u.ucclass.sense)
+ return JS_FALSE;
+
+ RECharSet* charSet = InitNodeCharSet(re, node);
+ LIns* to_fail = lir->insBranch(LIR_jf, lir->ins2(LIR_lt, pos, cpend), 0);
+ fails.add(to_fail);
+ LIns* text_ch = lir->insLoad(LIR_ldcs, pos, lir->insImm(0));
+ fails.add(lir->insBranch(LIR_jf, lir->ins2(LIR_le, text_ch, lir->insImm(charSet->length)), 0));
+ LIns* byteIndex = lir->ins2(LIR_rsh, text_ch, lir->insImm(3));
+ LIns* bitmap = lir->insLoad(LIR_ld, lir->insImmPtr(charSet), (int) offsetof(RECharSet, u.bits));
+ LIns* byte = lir->insLoad(LIR_ldcb, lir->ins2(LIR_piadd, bitmap, byteIndex), (int) 0);
+ LIns* bitMask = lir->ins2(LIR_lsh, lir->insImm(1),
+ lir->ins2(LIR_and, text_ch, lir->insImm(0x7)));
+ LIns* test = lir->ins2(LIR_eq, lir->ins2(LIR_and, byte, bitMask), lir->insImm(0));
+
+ LIns* to_next = lir->insBranch(LIR_jt, test, 0);
+ fails.add(to_next);
+ return lir->ins2(LIR_piadd, pos, lir->insImm(2));
+ }
+
+ LIns* compileAlt(RENode* node, LIns* pos, LInsList& fails)
+ {
+ LInsList kidFails(NULL);
+ if (!compileNode((RENode *) node->kid, pos, kidFails))
+ return JS_FALSE;
+ if (!compileNode(node->next, pos, kidFails))
+ return JS_FALSE;
+
+ targetCurrentPoint(kidFails);
+ if (!compileNode(node->u.altprereq.kid2, pos, fails))
+ return JS_FALSE;
+ /*
+ * Disable compilation for any regexp where something follows an
+ * alternation. To make this work, we need to redesign to either
+ * (a) pass around continuations so we know the right place to go
+ * when we logically return, or (b) generate explicit backtracking
+ * code.
+ */
+ if (node->next)
+ return JS_FALSE;
+ return pos;
+ }
+
+ JSBool compileNode(RENode* node, LIns* pos, LInsList& fails)
+ {
+ for (; node; node = node->next) {
+ if (fragment->lirbuf->outOmem())
+ return JS_FALSE;
+
+ switch (node->op) {
+ case REOP_EMPTY:
+ pos = compileEmpty(node, pos, fails);
+ break;
+ case REOP_FLAT:
+ if (node->u.flat.length != 1)
+ return JS_FALSE;
+ pos = compileFlatSingleChar(node, pos, fails);
+ break;
+ case REOP_ALT:
+ case REOP_ALTPREREQ:
+ pos = compileAlt(node, pos, fails);
+ break;
+ case REOP_CLASS:
+ pos = compileClass(node, pos, fails);
+ break;
+ default:
+ return JS_FALSE;
+ }
+ if (!pos)
+ return JS_FALSE;
+ }
+
+ lir->insStorei(pos, state, (int) offsetof(REMatchState, cp));
+ lir->ins1(LIR_ret, state);
+ return JS_TRUE;
+ }
+
+ JSBool compileSticky(RENode* root, LIns* start)
+ {
+ LInsList fails(NULL);
+ if (!compileNode(root, start, fails))
+ return JS_FALSE;
+ targetCurrentPoint(fails);
+ lir->ins1(LIR_ret, lir->insImm(0));
+ return JS_TRUE;
+ }
+
+ JSBool compileAnchoring(RENode* root, LIns* start)
+ {
+ /* Even at the end, the empty regexp would match. */
+ LIns* to_next = lir->insBranch(LIR_jf,
+ lir->ins2(LIR_le, start, cpend), 0);
+ LInsList fails(NULL);
+ if (!compileNode(root, start, fails))
+ return JS_FALSE;
+
+ targetCurrentPoint(to_next);
+ lir->ins1(LIR_ret, lir->insImm(0));
+
+ targetCurrentPoint(fails);
+ lir->insStorei(lir->ins2(LIR_piadd, start, lir->insImm(2)), gdata,
+ (int) offsetof(REGlobalData, skipped));
+
+ return JS_TRUE;
+ }
+
+ inline LIns*
+ addName(LirBuffer* lirbuf, LIns* ins, const char* name)
+ {
+ debug_only_v(lirbuf->names->addName(ins, name);)
+ return ins;
+ }
+
+ public:
+ RegExpNativeCompiler(JSRegExp *re, CompilerState *cs)
+ : re(re), cs(cs), fragment(NULL) { }
+
+ JSBool compile(JSContext* cx)
+ {
+ GuardRecord* guard;
+ LIns* skip;
+ LIns* start;
+ bool oom = false;
+
+ Fragmento* fragmento = JS_TRACE_MONITOR(cx).reFragmento;
+ fragment = fragmento->getLoop(re);
+ if (!fragment) {
+ fragment = fragmento->getAnchor(re);
+ fragment->lirbuf = new (&gc) LirBuffer(fragmento, NULL);
+ /* Scary: required to have the onDestroy method delete the lirbuf. */
+ fragment->root = fragment;
+ }
+ LirBuffer* lirbuf = fragment->lirbuf;
+ LirBufWriter* lirb;
+ if (lirbuf->outOmem()) goto fail2;
+ /* FIXME Use bug 463260 smart pointer when available. */
+ lir = lirb = new (&gc) LirBufWriter(lirbuf);
+
+ /* FIXME Use bug 463260 smart pointer when available. */
+ debug_only_v(fragment->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, fragmento->labels);)
+ /* FIXME Use bug 463260 smart pointer when available. */
+ debug_only_v(lir = new (&gc) VerboseWriter(&gc, lir, lirbuf->names);)
+
+ lir->ins0(LIR_start);
+ lirbuf->state = state = addName(lirbuf, lir->insParam(0, 0), "state");
+ lirbuf->param1 = gdata = addName(lirbuf, lir->insParam(1, 0), "gdata");
+ start = addName(lirbuf, lir->insLoad(LIR_ldp, lirbuf->param1, (int) offsetof(REGlobalData, skipped)), "start");
+ cpend = addName(lirbuf, lir->insLoad(LIR_ldp, lirbuf->param1, offsetof(REGlobalData, cpend)), "cpend");
+
+ if (cs->flags & JSREG_STICKY) {
+ if (!compileSticky(cs->result, start)) goto fail;
+ } else {
+ if (!compileAnchoring(cs->result, start)) goto fail;
+ }
+
+ /* Create fake guard record for loop edge. */
+ skip = lirb->skip(sizeof(GuardRecord) + sizeof(SideExit));
+ guard = (GuardRecord *) skip->payload();
+ memset(guard, 0, sizeof(*guard));
+ guard->exit = (SideExit *) guard+1;
+ guard->exit->target = fragment;
+ fragment->lastIns = lir->insGuard(LIR_loop, lir->insImm(1), skip);
+
+ ::compile(fragmento->assm(), fragment);
+ if (fragmento->assm()->error() != nanojit::None) {
+ oom = fragmento->assm()->error() == nanojit::OutOMem;
+ goto fail;
+ }
+
+ delete lirb;
+ debug_only_v(delete lir;)
+ return JS_TRUE;
+ fail:
+ delete lirb;
+ debug_only_v(delete lir;)
+ fail2:
+ if (lirbuf->outOmem() || oom)
+ fragmento->clearFrags();
+ return JS_FALSE;
+ }
+};
+
+static inline JSBool
+js_CompileRegExpToNative(JSContext *cx, JSRegExp *re, CompilerState *cs)
+{
+ RegExpNativeCompiler rc(re, cs);
+ return rc.compile(cx);
+}
+#endif
+
+JSRegExp *
+js_NewRegExp(JSContext *cx, JSTokenStream *ts,
+ JSString *str, uintN flags, JSBool flat)
+{
+ JSRegExp *re;
+ void *mark;
+ CompilerState state;
+ size_t resize;
+ jsbytecode *endPC;
+ uintN i;
+ size_t len;
+
+ re = NULL;
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ len = JSSTRING_LENGTH(str);
+
+ state.context = cx;
+ state.tokenStream = ts;
+ state.cp = js_UndependString(cx, str);
+ if (!state.cp)
+ goto out;
+ state.cpbegin = state.cp;
+ state.cpend = state.cp + len;
+ state.flags = flags;
+ state.parenCount = 0;
+ state.classCount = 0;
+ state.progLength = 0;
+ state.treeDepth = 0;
+ state.classBitmapsMem = 0;
+ for (i = 0; i < CLASS_CACHE_SIZE; i++)
+ state.classCache[i].start = NULL;
+
+ if (len != 0 && flat) {
+ state.result = NewRENode(&state, REOP_FLAT);
+ if (!state.result)
+ goto out;
+ state.result->u.flat.chr = *state.cpbegin;
+ state.result->u.flat.length = len;
+ state.result->kid = (void *) state.cpbegin;
+ /* Flat bytecode: REOP_FLAT compact(string_offset) compact(len). */
+ state.progLength += 1 + GetCompactIndexWidth(0)
+ + GetCompactIndexWidth(len);
+ } else {
+ if (!ParseRegExp(&state))
+ goto out;
+ }
+
+ resize = offsetof(JSRegExp, program) + state.progLength + 1;
+ re = (JSRegExp *) JS_malloc(cx, resize);
+ if (!re)
+ goto out;
+
+ re->nrefs = 1;
+ JS_ASSERT(state.classBitmapsMem <= CLASS_BITMAPS_MEM_LIMIT);
+ re->classCount = state.classCount;
+ if (re->classCount) {
+ re->classList = (RECharSet *)
+ JS_malloc(cx, re->classCount * sizeof(RECharSet));
+ if (!re->classList) {
+ js_DestroyRegExp(cx, re);
+ re = NULL;
+ goto out;
+ }
+ for (i = 0; i < re->classCount; i++)
+ re->classList[i].converted = JS_FALSE;
+ } else {
+ re->classList = NULL;
+ }
+
+#ifdef JS_TRACER
+ /*
+ * Try compiling the native code version. For the time being we also
+ * compile the bytecode version in case we evict the native code
+ * version from the code cache.
+ */
+ if (TRACING_ENABLED(cx))
+ js_CompileRegExpToNative(cx, re, &state);
+#endif
+ /* Compile the bytecode version. */
+ endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result);
+ if (!endPC) {
+ js_DestroyRegExp(cx, re);
+ re = NULL;
+ goto out;
+ }
+ *endPC++ = REOP_END;
+ /*
+ * Check whether size was overestimated and shrink using realloc.
+ * This is safe since no pointers to newly parsed regexp or its parts
+ * besides re exist here.
+ */
+#if 0
+ /*
+ * FIXME: Until bug 464866 is fixed, we can't move the re object so
+ * don't shrink it for now.
+ */
+ if ((size_t)(endPC - re->program) != state.progLength + 1) {
+ JSRegExp *tmp;
+ JS_ASSERT((size_t)(endPC - re->program) < state.progLength + 1);
+ resize = offsetof(JSRegExp, program) + (endPC - re->program);
+ tmp = (JSRegExp *) JS_realloc(cx, re, resize);
+ if (tmp)
+ re = tmp;
+ }
+#endif
+
+ re->flags = flags;
+ re->parenCount = state.parenCount;
+ re->source = str;
+
+out:
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ return re;
+}
+
+JSRegExp *
+js_NewRegExpOpt(JSContext *cx, JSString *str, JSString *opt, JSBool flat)
+{
+ uintN flags;
+ jschar *s;
+ size_t i, n;
+ char charBuf[2];
+
+ flags = 0;
+ if (opt) {
+ JSSTRING_CHARS_AND_LENGTH(opt, s, n);
+ for (i = 0; i < n; i++) {
+ switch (s[i]) {
+ case 'g':
+ flags |= JSREG_GLOB;
+ break;
+ case 'i':
+ flags |= JSREG_FOLD;
+ break;
+ case 'm':
+ flags |= JSREG_MULTILINE;
+ break;
+ case 'y':
+ flags |= JSREG_STICKY;
+ break;
+ default:
+ charBuf[0] = (char)s[i];
+ charBuf[1] = '\0';
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_BAD_FLAG, charBuf);
+ return NULL;
+ }
+ }
+ }
+ return js_NewRegExp(cx, NULL, str, flags, flat);
+}
+
+/*
+ * Save the current state of the match - the position in the input
+ * text as well as the position in the bytecode. The state of any
+ * parent expressions is also saved (preceding state).
+ * Contents of parenCount parentheses from parenIndex are also saved.
+ */
+static REBackTrackData *
+PushBackTrackState(REGlobalData *gData, REOp op,
+ jsbytecode *target, REMatchState *x, const jschar *cp,
+ size_t parenIndex, size_t parenCount)
+{
+ size_t i;
+ REBackTrackData *result =
+ (REBackTrackData *) ((char *)gData->backTrackSP + gData->cursz);
+
+ size_t sz = sizeof(REBackTrackData) +
+ gData->stateStackTop * sizeof(REProgState) +
+ parenCount * sizeof(RECapture);
+
+ ptrdiff_t btsize = gData->backTrackStackSize;
+ ptrdiff_t btincr = ((char *)result + sz) -
+ ((char *)gData->backTrackStack + btsize);
+
+ re_debug("\tBT_Push: %lu,%lu",
+ (unsigned long) parenIndex, (unsigned long) parenCount);
+
+ JS_COUNT_OPERATION(gData->cx, JSOW_JUMP * (1 + parenCount));
+ if (btincr > 0) {
+ ptrdiff_t offset = (char *)result - (char *)gData->backTrackStack;
+
+ JS_COUNT_OPERATION(gData->cx, JSOW_ALLOCATION);
+ btincr = JS_ROUNDUP(btincr, btsize);
+ JS_ARENA_GROW_CAST(gData->backTrackStack, REBackTrackData *,
+ &gData->cx->regexpPool, btsize, btincr);
+ if (!gData->backTrackStack) {
+ js_ReportOutOfScriptQuota(gData->cx);
+ gData->ok = JS_FALSE;
+ return NULL;
+ }
+ gData->backTrackStackSize = btsize + btincr;
+ result = (REBackTrackData *) ((char *)gData->backTrackStack + offset);
+ }
+ gData->backTrackSP = result;
+ result->sz = gData->cursz;
+ gData->cursz = sz;
+
+ result->backtrack_op = op;
+ result->backtrack_pc = target;
+ result->cp = cp;
+ result->parenCount = parenCount;
+ result->parenIndex = parenIndex;
+
+ result->saveStateStackTop = gData->stateStackTop;
+ JS_ASSERT(gData->stateStackTop);
+ memcpy(result + 1, gData->stateStack,
+ sizeof(REProgState) * result->saveStateStackTop);
+
+ if (parenCount != 0) {
+ memcpy((char *)(result + 1) +
+ sizeof(REProgState) * result->saveStateStackTop,
+ &x->parens[parenIndex],
+ sizeof(RECapture) * parenCount);
+ for (i = 0; i != parenCount; i++)
+ x->parens[parenIndex + i].index = -1;
+ }
+
+ return result;
+}
+
+
+/*
+ * Consecutive literal characters.
+ */
+#if 0
+static REMatchState *
+FlatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars,
+ size_t length)
+{
+ size_t i;
+ if (length > gData->cpend - x->cp)
+ return NULL;
+ for (i = 0; i != length; i++) {
+ if (matchChars[i] != x->cp[i])
+ return NULL;
+ }
+ x->cp += length;
+ return x;
+}
+#endif
+
+static JS_ALWAYS_INLINE REMatchState *
+FlatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars,
+ size_t length)
+{
+ size_t i;
+ JS_ASSERT(gData->cpend >= x->cp);
+ if (length > (size_t)(gData->cpend - x->cp))
+ return NULL;
+ for (i = 0; i != length; i++) {
+ if (upcase(matchChars[i]) != upcase(x->cp[i]))
+ return NULL;
+ }
+ x->cp += length;
+ return x;
+}
+
+/*
+ * 1. Evaluate DecimalEscape to obtain an EscapeValue E.
+ * 2. If E is not a character then go to step 6.
+ * 3. Let ch be E's character.
+ * 4. Let A be a one-element RECharSet containing the character ch.
+ * 5. Call CharacterSetMatcher(A, false) and return its Matcher result.
+ * 6. E must be an integer. Let n be that integer.
+ * 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception.
+ * 8. Return an internal Matcher closure that takes two arguments, a State x
+ * and a Continuation c, and performs the following:
+ * 1. Let cap be x's captures internal array.
+ * 2. Let s be cap[n].
+ * 3. If s is undefined, then call c(x) and return its result.
+ * 4. Let e be x's endIndex.
+ * 5. Let len be s's length.
+ * 6. Let f be e+len.
+ * 7. If f>InputLength, return failure.
+ * 8. If there exists an integer i between 0 (inclusive) and len (exclusive)
+ * such that Canonicalize(s[i]) is not the same character as
+ * Canonicalize(Input [e+i]), then return failure.
+ * 9. Let y be the State (f, cap).
+ * 10. Call c(y) and return its result.
+ */
+static REMatchState *
+BackrefMatcher(REGlobalData *gData, REMatchState *x, size_t parenIndex)
+{
+ size_t len, i;
+ const jschar *parenContent;
+ RECapture *cap = &x->parens[parenIndex];
+
+ if (cap->index == -1)
+ return x;
+
+ len = cap->length;
+ if (x->cp + len > gData->cpend)
+ return NULL;
+
+ parenContent = &gData->cpbegin[cap->index];
+ if (gData->regexp->flags & JSREG_FOLD) {
+ for (i = 0; i < len; i++) {
+ if (upcase(parenContent[i]) != upcase(x->cp[i]))
+ return NULL;
+ }
+ } else {
+ for (i = 0; i < len; i++) {
+ if (parenContent[i] != x->cp[i])
+ return NULL;
+ }
+ }
+ x->cp += len;
+ return x;
+}
+
+
+/* Add a single character to the RECharSet */
+static void
+AddCharacterToCharSet(RECharSet *cs, jschar c)
+{
+ uintN byteIndex = (uintN)(c >> 3);
+ JS_ASSERT(c <= cs->length);
+ cs->u.bits[byteIndex] |= 1 << (c & 0x7);
+}
+
+
+/* Add a character range, c1 to c2 (inclusive) to the RECharSet */
+static void
+AddCharacterRangeToCharSet(RECharSet *cs, uintN c1, uintN c2)
+{
+ uintN i;
+
+ uintN byteIndex1 = c1 >> 3;
+ uintN byteIndex2 = c2 >> 3;
+
+ JS_ASSERT(c2 <= cs->length && c1 <= c2);
+
+ c1 &= 0x7;
+ c2 &= 0x7;
+
+ if (byteIndex1 == byteIndex2) {
+ cs->u.bits[byteIndex1] |= ((uint8)0xFF >> (7 - (c2 - c1))) << c1;
+ } else {
+ cs->u.bits[byteIndex1] |= 0xFF << c1;
+ for (i = byteIndex1 + 1; i < byteIndex2; i++)
+ cs->u.bits[i] = 0xFF;
+ cs->u.bits[byteIndex2] |= (uint8)0xFF >> (7 - c2);
+ }
+}
+
+struct CharacterRange {
+ jschar start;
+ jschar end;
+};
+
+/*
+ * The following characters are taken from the ECMA-262 standard, section 7.2
+ * and 7.3, and the Unicode 3 standard, Table 6-1.
+ */
+static const CharacterRange WhiteSpaceRanges[] = {
+ /* TAB, LF, VT, FF, CR */
+ { 0x0009, 0x000D },
+ /* SPACE */
+ { 0x0020, 0x0020 },
+ /* NO-BREAK SPACE */
+ { 0x00A0, 0x00A0 },
+ /*
+ * EN QUAD, EM QUAD, EN SPACE, EM SPACE, THREE-PER-EM SPACE, FOUR-PER-EM
+ * SPACE, SIX-PER-EM SPACE, FIGURE SPACE, PUNCTUATION SPACE, THIN SPACE,
+ * HAIR SPACE, ZERO WIDTH SPACE
+ */
+ { 0x2000, 0x200B },
+ /* LS, PS */
+ { 0x2028, 0x2029 },
+ /* NARROW NO-BREAK SPACE */
+ { 0x202F, 0x202F },
+ /* IDEOGRAPHIC SPACE */
+ { 0x3000, 0x3000 }
+};
+
+/* ECMA-262 standard, section 15.10.2.6. */
+static const CharacterRange WordRanges[] = {
+ { jschar('0'), jschar('9') },
+ { jschar('A'), jschar('Z') },
+ { jschar('_'), jschar('_') },
+ { jschar('a'), jschar('z') }
+};
+
+static void
+AddCharacterRanges(RECharSet *charSet,
+ const CharacterRange *range,
+ const CharacterRange *end)
+{
+ for (; range < end; ++range)
+ AddCharacterRangeToCharSet(charSet, range->start, range->end);
+}
+
+static void
+AddInvertedCharacterRanges(RECharSet *charSet,
+ const CharacterRange *range,
+ const CharacterRange *end)
+{
+ uint16 previous = 0;
+ for (; range < end; ++range) {
+ AddCharacterRangeToCharSet(charSet, previous, range->start - 1);
+ previous = range->end + 1;
+ }
+ AddCharacterRangeToCharSet(charSet, previous, charSet->length);
+}
+
+/* Compile the source of the class into a RECharSet */
+static JSBool
+ProcessCharSet(REGlobalData *gData, RECharSet *charSet)
+{
+ const jschar *src, *end;
+ JSBool inRange = JS_FALSE;
+ jschar rangeStart = 0;
+ uintN byteLength, n;
+ jschar c, thisCh;
+ intN nDigits, i;
+
+ JS_ASSERT(!charSet->converted);
+ /*
+ * Assert that startIndex and length points to chars inside [] inside
+ * source string.
+ */
+ JS_ASSERT(1 <= charSet->u.src.startIndex);
+ JS_ASSERT(charSet->u.src.startIndex
+ < JSSTRING_LENGTH(gData->regexp->source));
+ JS_ASSERT(charSet->u.src.length <= JSSTRING_LENGTH(gData->regexp->source)
+ - 1 - charSet->u.src.startIndex);
+
+ charSet->converted = JS_TRUE;
+ src = JSSTRING_CHARS(gData->regexp->source) + charSet->u.src.startIndex;
+ end = src + charSet->u.src.length;
+ JS_ASSERT(src[-1] == '[');
+ JS_ASSERT(end[0] == ']');
+
+ byteLength = (charSet->length >> 3) + 1;
+ charSet->u.bits = (uint8 *)JS_malloc(gData->cx, byteLength);
+ if (!charSet->u.bits) {
+ JS_ReportOutOfMemory(gData->cx);
+ gData->ok = JS_FALSE;
+ return JS_FALSE;
+ }
+ memset(charSet->u.bits, 0, byteLength);
+
+ if (src == end)
+ return JS_TRUE;
+
+ if (*src == '^') {
+ JS_ASSERT(charSet->sense == JS_FALSE);
+ ++src;
+ } else {
+ JS_ASSERT(charSet->sense == JS_TRUE);
+ }
+
+ while (src != end) {
+ switch (*src) {
+ case '\\':
+ ++src;
+ c = *src++;
+ switch (c) {
+ case 'b':
+ thisCh = 0x8;
+ break;
+ case 'f':
+ thisCh = 0xC;
+ break;
+ case 'n':
+ thisCh = 0xA;
+ break;
+ case 'r':
+ thisCh = 0xD;
+ break;
+ case 't':
+ thisCh = 0x9;
+ break;
+ case 'v':
+ thisCh = 0xB;
+ break;
+ case 'c':
+ if (src < end && JS_ISWORD(*src)) {
+ thisCh = (jschar)(*src++ & 0x1F);
+ } else {
+ --src;
+ thisCh = '\\';
+ }
+ break;
+ case 'x':
+ nDigits = 2;
+ goto lexHex;
+ case 'u':
+ nDigits = 4;
+ lexHex:
+ n = 0;
+ for (i = 0; (i < nDigits) && (src < end); i++) {
+ uintN digit;
+ c = *src++;
+ if (!isASCIIHexDigit(c, &digit)) {
+ /*
+ * Back off to accepting the original '\'
+ * as a literal
+ */
+ src -= i + 1;
+ n = '\\';
+ break;
+ }
+ n = (n << 4) | digit;
+ }
+ thisCh = (jschar)n;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ /*
+ * This is a non-ECMA extension - decimal escapes (in this
+ * case, octal!) are supposed to be an error inside class
+ * ranges, but supported here for backwards compatibility.
+ */
+ n = JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ n = 8 * n + JS7_UNDEC(c);
+ c = *src;
+ if ('0' <= c && c <= '7') {
+ src++;
+ i = 8 * n + JS7_UNDEC(c);
+ if (i <= 0377)
+ n = i;
+ else
+ src--;
+ }
+ }
+ thisCh = (jschar)n;
+ break;
+
+ case 'd':
+ AddCharacterRangeToCharSet(charSet, '0', '9');
+ continue; /* don't need range processing */
+ case 'D':
+ AddCharacterRangeToCharSet(charSet, 0, '0' - 1);
+ AddCharacterRangeToCharSet(charSet,
+ (jschar)('9' + 1),
+ (jschar)charSet->length);
+ continue;
+ case 's':
+ AddCharacterRanges(charSet, WhiteSpaceRanges,
+ WhiteSpaceRanges + JS_ARRAY_LENGTH(WhiteSpaceRanges));
+ continue;
+ case 'S':
+ AddInvertedCharacterRanges(charSet, WhiteSpaceRanges,
+ WhiteSpaceRanges + JS_ARRAY_LENGTH(WhiteSpaceRanges));
+ continue;
+ case 'w':
+ AddCharacterRanges(charSet, WordRanges,
+ WordRanges + JS_ARRAY_LENGTH(WordRanges));
+ continue;
+ case 'W':
+ AddInvertedCharacterRanges(charSet, WordRanges,
+ WordRanges + JS_ARRAY_LENGTH(WordRanges));
+ continue;
+ default:
+ thisCh = c;
+ break;
+
+ }
+ break;
+
+ default:
+ thisCh = *src++;
+ break;
+
+ }
+ if (inRange) {
+ if (gData->regexp->flags & JSREG_FOLD) {
+ int i;
+
+ JS_ASSERT(rangeStart <= thisCh);
+ for (i = rangeStart; i <= thisCh; i++) {
+ jschar uch, dch;
+
+ AddCharacterToCharSet(charSet, i);
+ uch = upcase(i);
+ dch = downcase(i);
+ if (i != uch)
+ AddCharacterToCharSet(charSet, uch);
+ if (i != dch)
+ AddCharacterToCharSet(charSet, dch);
+ }
+ } else {
+ AddCharacterRangeToCharSet(charSet, rangeStart, thisCh);
+ }
+ inRange = JS_FALSE;
+ } else {
+ if (gData->regexp->flags & JSREG_FOLD) {
+ AddCharacterToCharSet(charSet, upcase(thisCh));
+ AddCharacterToCharSet(charSet, downcase(thisCh));
+ } else {
+ AddCharacterToCharSet(charSet, thisCh);
+ }
+ if (src < end - 1) {
+ if (*src == '-') {
+ ++src;
+ inRange = JS_TRUE;
+ rangeStart = thisCh;
+ }
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+void
+js_DestroyRegExp(JSContext *cx, JSRegExp *re)
+{
+ if (JS_ATOMIC_DECREMENT(&re->nrefs) == 0) {
+#ifdef JS_TRACER
+ /* Don't reuse this compiled code for some new regexp at same addr. */
+ Fragment* fragment = JS_TRACE_MONITOR(cx).reFragmento->getLoop(re);
+ if (fragment)
+ fragment->blacklist();
+#endif
+ if (re->classList) {
+ uintN i;
+ for (i = 0; i < re->classCount; i++) {
+ if (re->classList[i].converted)
+ JS_free(cx, re->classList[i].u.bits);
+ re->classList[i].u.bits = NULL;
+ }
+ JS_free(cx, re->classList);
+ }
+ JS_free(cx, re);
+ }
+}
+
+static JSBool
+ReallocStateStack(REGlobalData *gData)
+{
+ size_t limit = gData->stateStackLimit;
+ size_t sz = sizeof(REProgState) * limit;
+
+ JS_ARENA_GROW_CAST(gData->stateStack, REProgState *,
+ &gData->cx->regexpPool, sz, sz);
+ if (!gData->stateStack) {
+ js_ReportOutOfScriptQuota(gData->cx);
+ gData->ok = JS_FALSE;
+ return JS_FALSE;
+ }
+ gData->stateStackLimit = limit + limit;
+ return JS_TRUE;
+}
+
+#define PUSH_STATE_STACK(data) \
+ JS_BEGIN_MACRO \
+ ++(data)->stateStackTop; \
+ if ((data)->stateStackTop == (data)->stateStackLimit && \
+ !ReallocStateStack((data))) { \
+ return NULL; \
+ } \
+ JS_END_MACRO
+
+/*
+ * Apply the current op against the given input to see if it's going to match
+ * or fail. Return false if we don't get a match, true if we do. If updatecp is
+ * true, then update the current state's cp. Always update startpc to the next
+ * op.
+ */
+static JS_ALWAYS_INLINE REMatchState *
+SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op,
+ jsbytecode **startpc, JSBool updatecp)
+{
+ REMatchState *result = NULL;
+ jschar matchCh;
+ size_t parenIndex;
+ size_t offset, length, index;
+ jsbytecode *pc = *startpc; /* pc has already been incremented past op */
+ jschar *source;
+ const jschar *startcp = x->cp;
+ jschar ch;
+ RECharSet *charSet;
+
+#ifdef REGEXP_DEBUG
+ const char *opname = reop_names[op];
+ re_debug("\n%06d: %*s%s", pc - gData->regexp->program,
+ gData->stateStackTop * 2, "", opname);
+#endif
+ switch (op) {
+ case REOP_EMPTY:
+ result = x;
+ break;
+ case REOP_BOL:
+ if (x->cp != gData->cpbegin) {
+ if (!gData->cx->regExpStatics.multiline &&
+ !(gData->regexp->flags & JSREG_MULTILINE)) {
+ break;
+ }
+ if (!RE_IS_LINE_TERM(x->cp[-1]))
+ break;
+ }
+ result = x;
+ break;
+ case REOP_EOL:
+ if (x->cp != gData->cpend) {
+ if (!gData->cx->regExpStatics.multiline &&
+ !(gData->regexp->flags & JSREG_MULTILINE)) {
+ break;
+ }
+ if (!RE_IS_LINE_TERM(*x->cp))
+ break;
+ }
+ result = x;
+ break;
+ case REOP_WBDRY:
+ if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^
+ !(x->cp != gData->cpend && JS_ISWORD(*x->cp))) {
+ result = x;
+ }
+ break;
+ case REOP_WNONBDRY:
+ if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^
+ (x->cp != gData->cpend && JS_ISWORD(*x->cp))) {
+ result = x;
+ }
+ break;
+ case REOP_DOT:
+ if (x->cp != gData->cpend && !RE_IS_LINE_TERM(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_DIGIT:
+ if (x->cp != gData->cpend && JS7_ISDEC(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_NONDIGIT:
+ if (x->cp != gData->cpend && !JS7_ISDEC(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_ALNUM:
+ if (x->cp != gData->cpend && JS_ISWORD(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_NONALNUM:
+ if (x->cp != gData->cpend && !JS_ISWORD(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_SPACE:
+ if (x->cp != gData->cpend && JS_ISSPACE(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_NONSPACE:
+ if (x->cp != gData->cpend && !JS_ISSPACE(*x->cp)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_BACKREF:
+ pc = ReadCompactIndex(pc, &parenIndex);
+ JS_ASSERT(parenIndex < gData->regexp->parenCount);
+ result = BackrefMatcher(gData, x, parenIndex);
+ break;
+ case REOP_FLAT:
+ pc = ReadCompactIndex(pc, &offset);
+ JS_ASSERT(offset < JSSTRING_LENGTH(gData->regexp->source));
+ pc = ReadCompactIndex(pc, &length);
+ JS_ASSERT(1 <= length);
+ JS_ASSERT(length <= JSSTRING_LENGTH(gData->regexp->source) - offset);
+ if (length <= (size_t)(gData->cpend - x->cp)) {
+ source = JSSTRING_CHARS(gData->regexp->source) + offset;
+ re_debug_chars(source, length);
+ for (index = 0; index != length; index++) {
+ if (source[index] != x->cp[index])
+ return NULL;
+ }
+ x->cp += length;
+ result = x;
+ }
+ break;
+ case REOP_FLAT1:
+ matchCh = *pc++;
+ re_debug(" '%c' == '%c'", (char)matchCh, (char)*x->cp);
+ if (x->cp != gData->cpend && *x->cp == matchCh) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_FLATi:
+ pc = ReadCompactIndex(pc, &offset);
+ JS_ASSERT(offset < JSSTRING_LENGTH(gData->regexp->source));
+ pc = ReadCompactIndex(pc, &length);
+ JS_ASSERT(1 <= length);
+ JS_ASSERT(length <= JSSTRING_LENGTH(gData->regexp->source) - offset);
+ source = JSSTRING_CHARS(gData->regexp->source);
+ result = FlatNIMatcher(gData, x, source + offset, length);
+ break;
+ case REOP_FLAT1i:
+ matchCh = *pc++;
+ if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_UCFLAT1:
+ matchCh = GET_ARG(pc);
+ re_debug(" '%c' == '%c'", (char)matchCh, (char)*x->cp);
+ pc += ARG_LEN;
+ if (x->cp != gData->cpend && *x->cp == matchCh) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_UCFLAT1i:
+ matchCh = GET_ARG(pc);
+ pc += ARG_LEN;
+ if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) {
+ result = x;
+ result->cp++;
+ }
+ break;
+ case REOP_CLASS:
+ pc = ReadCompactIndex(pc, &index);
+ JS_ASSERT(index < gData->regexp->classCount);
+ if (x->cp != gData->cpend) {
+ charSet = &gData->regexp->classList[index];
+ JS_ASSERT(charSet->converted);
+ ch = *x->cp;
+ index = ch >> 3;
+ if (charSet->length != 0 &&
+ ch <= charSet->length &&
+ (charSet->u.bits[index] & (1 << (ch & 0x7)))) {
+ result = x;
+ result->cp++;
+ }
+ }
+ break;
+ case REOP_NCLASS:
+ pc = ReadCompactIndex(pc, &index);
+ JS_ASSERT(index < gData->regexp->classCount);
+ if (x->cp != gData->cpend) {
+ charSet = &gData->regexp->classList[index];
+ JS_ASSERT(charSet->converted);
+ ch = *x->cp;
+ index = ch >> 3;
+ if (charSet->length == 0 ||
+ ch > charSet->length ||
+ !(charSet->u.bits[index] & (1 << (ch & 0x7)))) {
+ result = x;
+ result->cp++;
+ }
+ }
+ break;
+
+ default:
+ JS_ASSERT(JS_FALSE);
+ }
+ if (result) {
+ if (!updatecp)
+ x->cp = startcp;
+ *startpc = pc;
+ re_debug(" * ");
+ return result;
+ }
+ x->cp = startcp;
+ return NULL;
+}
+
+static JS_ALWAYS_INLINE REMatchState *
+ExecuteREBytecode(REGlobalData *gData, REMatchState *x)
+{
+ REMatchState *result = NULL;
+ REBackTrackData *backTrackData;
+ jsbytecode *nextpc, *testpc;
+ REOp nextop;
+ RECapture *cap;
+ REProgState *curState;
+ const jschar *startcp;
+ size_t parenIndex, k;
+ size_t parenSoFar = 0;
+
+ jschar matchCh1, matchCh2;
+ RECharSet *charSet;
+
+ JSBool anchor;
+ jsbytecode *pc = gData->regexp->program;
+ REOp op = (REOp) *pc++;
+
+ /*
+ * If the first node is a simple match, step the index into the string
+ * until that match is made, or fail if it can't be found at all.
+ */
+ if (REOP_IS_SIMPLE(op) && !(gData->regexp->flags & JSREG_STICKY)) {
+ anchor = JS_FALSE;
+ while (x->cp <= gData->cpend) {
+ nextpc = pc; /* reset back to start each time */
+ result = SimpleMatch(gData, x, op, &nextpc, JS_TRUE);
+ if (result) {
+ anchor = JS_TRUE;
+ x = result;
+ pc = nextpc; /* accept skip to next opcode */
+ op = (REOp) *pc++;
+ JS_ASSERT(op < REOP_LIMIT);
+ break;
+ }
+ gData->skipped++;
+ x->cp++;
+ }
+ if (!anchor)
+ goto bad;
+ }
+
+ for (;;) {
+#ifdef REGEXP_DEBUG
+ const char *opname = reop_names[op];
+ re_debug("\n%06d: %*s%s", pc - gData->regexp->program,
+ gData->stateStackTop * 2, "", opname);
+#endif
+ if (REOP_IS_SIMPLE(op)) {
+ result = SimpleMatch(gData, x, op, &pc, JS_TRUE);
+ } else {
+ curState = &gData->stateStack[gData->stateStackTop];
+ switch (op) {
+ case REOP_END:
+ goto good;
+ case REOP_ALTPREREQ2:
+ nextpc = pc + GET_OFFSET(pc); /* start of next op */
+ pc += ARG_LEN;
+ matchCh2 = GET_ARG(pc);
+ pc += ARG_LEN;
+ k = GET_ARG(pc);
+ pc += ARG_LEN;
+
+ if (x->cp != gData->cpend) {
+ if (*x->cp == matchCh2)
+ goto doAlt;
+
+ charSet = &gData->regexp->classList[k];
+ if (!charSet->converted && !ProcessCharSet(gData, charSet))
+ goto bad;
+ matchCh1 = *x->cp;
+ k = matchCh1 >> 3;
+ if ((charSet->length == 0 ||
+ matchCh1 > charSet->length ||
+ !(charSet->u.bits[k] & (1 << (matchCh1 & 0x7)))) ^
+ charSet->sense) {
+ goto doAlt;
+ }
+ }
+ result = NULL;
+ break;
+
+ case REOP_ALTPREREQ:
+ nextpc = pc + GET_OFFSET(pc); /* start of next op */
+ pc += ARG_LEN;
+ matchCh1 = GET_ARG(pc);
+ pc += ARG_LEN;
+ matchCh2 = GET_ARG(pc);
+ pc += ARG_LEN;
+ if (x->cp == gData->cpend ||
+ (*x->cp != matchCh1 && *x->cp != matchCh2)) {
+ result = NULL;
+ break;
+ }
+ /* else false thru... */
+
+ case REOP_ALT:
+ doAlt:
+ nextpc = pc + GET_OFFSET(pc); /* start of next alternate */
+ pc += ARG_LEN; /* start of this alternate */
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ op = (REOp) *pc++;
+ startcp = x->cp;
+ if (REOP_IS_SIMPLE(op)) {
+ if (!SimpleMatch(gData, x, op, &pc, JS_TRUE)) {
+ op = (REOp) *nextpc++;
+ pc = nextpc;
+ continue;
+ }
+ result = x;
+ op = (REOp) *pc++;
+ }
+ nextop = (REOp) *nextpc++;
+ if (!PushBackTrackState(gData, nextop, nextpc, x, startcp, 0, 0))
+ goto bad;
+ continue;
+
+ /*
+ * Occurs at (successful) end of REOP_ALT,
+ */
+ case REOP_JUMP:
+ /*
+ * If we have not gotten a result here, it is because of an
+ * empty match. Do the same thing REOP_EMPTY would do.
+ */
+ if (!result)
+ result = x;
+
+ --gData->stateStackTop;
+ pc += GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ continue;
+
+ /*
+ * Occurs at last (successful) end of REOP_ALT,
+ */
+ case REOP_ENDALT:
+ /*
+ * If we have not gotten a result here, it is because of an
+ * empty match. Do the same thing REOP_EMPTY would do.
+ */
+ if (!result)
+ result = x;
+
+ --gData->stateStackTop;
+ op = (REOp) *pc++;
+ continue;
+
+ case REOP_LPAREN:
+ pc = ReadCompactIndex(pc, &parenIndex);
+ re_debug("[ %lu ]", (unsigned long) parenIndex);
+ JS_ASSERT(parenIndex < gData->regexp->parenCount);
+ if (parenIndex + 1 > parenSoFar)
+ parenSoFar = parenIndex + 1;
+ x->parens[parenIndex].index = x->cp - gData->cpbegin;
+ x->parens[parenIndex].length = 0;
+ op = (REOp) *pc++;
+ continue;
+
+ case REOP_RPAREN:
+ {
+ ptrdiff_t delta;
+
+ pc = ReadCompactIndex(pc, &parenIndex);
+ JS_ASSERT(parenIndex < gData->regexp->parenCount);
+ cap = &x->parens[parenIndex];
+ delta = x->cp - (gData->cpbegin + cap->index);
+ cap->length = (delta < 0) ? 0 : (size_t) delta;
+ op = (REOp) *pc++;
+
+ if (!result)
+ result = x;
+ continue;
+ }
+ case REOP_ASSERT:
+ nextpc = pc + GET_OFFSET(pc); /* start of term after ASSERT */
+ pc += ARG_LEN; /* start of ASSERT child */
+ op = (REOp) *pc++;
+ testpc = pc;
+ if (REOP_IS_SIMPLE(op) &&
+ !SimpleMatch(gData, x, op, &testpc, JS_FALSE)) {
+ result = NULL;
+ break;
+ }
+ curState->u.assertion.top =
+ (char *)gData->backTrackSP - (char *)gData->backTrackStack;
+ curState->u.assertion.sz = gData->cursz;
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (!PushBackTrackState(gData, REOP_ASSERTTEST,
+ nextpc, x, x->cp, 0, 0)) {
+ goto bad;
+ }
+ continue;
+
+ case REOP_ASSERT_NOT:
+ nextpc = pc + GET_OFFSET(pc);
+ pc += ARG_LEN;
+ op = (REOp) *pc++;
+ testpc = pc;
+ if (REOP_IS_SIMPLE(op) /* Note - fail to fail! */ &&
+ SimpleMatch(gData, x, op, &testpc, JS_FALSE) &&
+ *testpc == REOP_ASSERTNOTTEST) {
+ result = NULL;
+ break;
+ }
+ curState->u.assertion.top
+ = (char *)gData->backTrackSP -
+ (char *)gData->backTrackStack;
+ curState->u.assertion.sz = gData->cursz;
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (!PushBackTrackState(gData, REOP_ASSERTNOTTEST,
+ nextpc, x, x->cp, 0, 0)) {
+ goto bad;
+ }
+ continue;
+
+ case REOP_ASSERTTEST:
+ --gData->stateStackTop;
+ --curState;
+ x->cp = gData->cpbegin + curState->index;
+ gData->backTrackSP =
+ (REBackTrackData *) ((char *)gData->backTrackStack +
+ curState->u.assertion.top);
+ gData->cursz = curState->u.assertion.sz;
+ if (result)
+ result = x;
+ break;
+
+ case REOP_ASSERTNOTTEST:
+ --gData->stateStackTop;
+ --curState;
+ x->cp = gData->cpbegin + curState->index;
+ gData->backTrackSP =
+ (REBackTrackData *) ((char *)gData->backTrackStack +
+ curState->u.assertion.top);
+ gData->cursz = curState->u.assertion.sz;
+ result = (!result) ? x : NULL;
+ break;
+ case REOP_STAR:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = (uintN)-1;
+ goto quantcommon;
+ case REOP_PLUS:
+ curState->u.quantifier.min = 1;
+ curState->u.quantifier.max = (uintN)-1;
+ goto quantcommon;
+ case REOP_OPT:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = 1;
+ goto quantcommon;
+ case REOP_QUANT:
+ pc = ReadCompactIndex(pc, &k);
+ curState->u.quantifier.min = k;
+ pc = ReadCompactIndex(pc, &k);
+ /* max is k - 1 to use one byte for (uintN)-1 sentinel. */
+ curState->u.quantifier.max = k - 1;
+ JS_ASSERT(curState->u.quantifier.min
+ <= curState->u.quantifier.max);
+ quantcommon:
+ if (curState->u.quantifier.max == 0) {
+ pc = pc + GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ result = x;
+ continue;
+ }
+ /* Step over <next> */
+ nextpc = pc + ARG_LEN;
+ op = (REOp) *nextpc++;
+ startcp = x->cp;
+ if (REOP_IS_SIMPLE(op)) {
+ if (!SimpleMatch(gData, x, op, &nextpc, JS_TRUE)) {
+ if (curState->u.quantifier.min == 0)
+ result = x;
+ else
+ result = NULL;
+ pc = pc + GET_OFFSET(pc);
+ break;
+ }
+ op = (REOp) *nextpc++;
+ result = x;
+ }
+ curState->index = startcp - gData->cpbegin;
+ curState->continue_op = REOP_REPEAT;
+ curState->continue_pc = pc;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (curState->u.quantifier.min == 0 &&
+ !PushBackTrackState(gData, REOP_REPEAT, pc, x, startcp,
+ 0, 0)) {
+ goto bad;
+ }
+ pc = nextpc;
+ continue;
+
+ case REOP_ENDCHILD: /* marks the end of a quantifier child */
+ pc = curState[-1].continue_pc;
+ op = (REOp) curState[-1].continue_op;
+
+ if (!result)
+ result = x;
+ continue;
+
+ case REOP_REPEAT:
+ --curState;
+ do {
+ --gData->stateStackTop;
+ if (!result) {
+ /* Failed, see if we have enough children. */
+ if (curState->u.quantifier.min == 0)
+ goto repeatDone;
+ goto break_switch;
+ }
+ if (curState->u.quantifier.min == 0 &&
+ x->cp == gData->cpbegin + curState->index) {
+ /* matched an empty string, that'll get us nowhere */
+ result = NULL;
+ goto break_switch;
+ }
+ if (curState->u.quantifier.min != 0)
+ curState->u.quantifier.min--;
+ if (curState->u.quantifier.max != (uintN) -1)
+ curState->u.quantifier.max--;
+ if (curState->u.quantifier.max == 0)
+ goto repeatDone;
+ nextpc = pc + ARG_LEN;
+ nextop = (REOp) *nextpc;
+ startcp = x->cp;
+ if (REOP_IS_SIMPLE(nextop)) {
+ nextpc++;
+ if (!SimpleMatch(gData, x, nextop, &nextpc, JS_TRUE)) {
+ if (curState->u.quantifier.min == 0)
+ goto repeatDone;
+ result = NULL;
+ goto break_switch;
+ }
+ result = x;
+ }
+ curState->index = startcp - gData->cpbegin;
+ PUSH_STATE_STACK(gData);
+ if (curState->u.quantifier.min == 0 &&
+ !PushBackTrackState(gData, REOP_REPEAT,
+ pc, x, startcp,
+ curState->parenSoFar,
+ parenSoFar -
+ curState->parenSoFar)) {
+ goto bad;
+ }
+ } while (*nextpc == REOP_ENDCHILD);
+ pc = nextpc;
+ op = (REOp) *pc++;
+ parenSoFar = curState->parenSoFar;
+ continue;
+
+ repeatDone:
+ result = x;
+ pc += GET_OFFSET(pc);
+ goto break_switch;
+
+ case REOP_MINIMALSTAR:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = (uintN)-1;
+ goto minimalquantcommon;
+ case REOP_MINIMALPLUS:
+ curState->u.quantifier.min = 1;
+ curState->u.quantifier.max = (uintN)-1;
+ goto minimalquantcommon;
+ case REOP_MINIMALOPT:
+ curState->u.quantifier.min = 0;
+ curState->u.quantifier.max = 1;
+ goto minimalquantcommon;
+ case REOP_MINIMALQUANT:
+ pc = ReadCompactIndex(pc, &k);
+ curState->u.quantifier.min = k;
+ pc = ReadCompactIndex(pc, &k);
+ /* See REOP_QUANT comments about k - 1. */
+ curState->u.quantifier.max = k - 1;
+ JS_ASSERT(curState->u.quantifier.min
+ <= curState->u.quantifier.max);
+ minimalquantcommon:
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (curState->u.quantifier.min != 0) {
+ curState->continue_op = REOP_MINIMALREPEAT;
+ curState->continue_pc = pc;
+ /* step over <next> */
+ pc += OFFSET_LEN;
+ op = (REOp) *pc++;
+ } else {
+ if (!PushBackTrackState(gData, REOP_MINIMALREPEAT,
+ pc, x, x->cp, 0, 0)) {
+ goto bad;
+ }
+ --gData->stateStackTop;
+ pc = pc + GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ }
+ continue;
+
+ case REOP_MINIMALREPEAT:
+ --gData->stateStackTop;
+ --curState;
+
+ re_debug("{%d,%d}", curState->u.quantifier.min,
+ curState->u.quantifier.max);
+#define PREPARE_REPEAT() \
+ JS_BEGIN_MACRO \
+ curState->index = x->cp - gData->cpbegin; \
+ curState->continue_op = REOP_MINIMALREPEAT; \
+ curState->continue_pc = pc; \
+ pc += ARG_LEN; \
+ for (k = curState->parenSoFar; k < parenSoFar; k++) \
+ x->parens[k].index = -1; \
+ PUSH_STATE_STACK(gData); \
+ op = (REOp) *pc++; \
+ JS_ASSERT(op < REOP_LIMIT); \
+ JS_END_MACRO
+
+ if (!result) {
+ re_debug(" - ");
+ /*
+ * Non-greedy failure - try to consume another child.
+ */
+ if (curState->u.quantifier.max == (uintN) -1 ||
+ curState->u.quantifier.max > 0) {
+ PREPARE_REPEAT();
+ continue;
+ }
+ /* Don't need to adjust pc since we're going to pop. */
+ break;
+ }
+ if (curState->u.quantifier.min == 0 &&
+ x->cp == gData->cpbegin + curState->index) {
+ /* Matched an empty string, that'll get us nowhere. */
+ result = NULL;
+ break;
+ }
+ if (curState->u.quantifier.min != 0)
+ curState->u.quantifier.min--;
+ if (curState->u.quantifier.max != (uintN) -1)
+ curState->u.quantifier.max--;
+ if (curState->u.quantifier.min != 0) {
+ PREPARE_REPEAT();
+ continue;
+ }
+ curState->index = x->cp - gData->cpbegin;
+ curState->parenSoFar = parenSoFar;
+ PUSH_STATE_STACK(gData);
+ if (!PushBackTrackState(gData, REOP_MINIMALREPEAT,
+ pc, x, x->cp,
+ curState->parenSoFar,
+ parenSoFar - curState->parenSoFar)) {
+ goto bad;
+ }
+ --gData->stateStackTop;
+ pc = pc + GET_OFFSET(pc);
+ op = (REOp) *pc++;
+ JS_ASSERT(op < REOP_LIMIT);
+ continue;
+ default:
+ JS_ASSERT(JS_FALSE);
+ result = NULL;
+ }
+ break_switch:;
+ }
+
+ /*
+ * If the match failed and there's a backtrack option, take it.
+ * Otherwise this is a complete and utter failure.
+ */
+ if (!result) {
+ if (gData->cursz == 0)
+ return NULL;
+ if (!JS_CHECK_OPERATION_LIMIT(gData->cx, JSOW_JUMP)) {
+ gData->ok = JS_FALSE;
+ return NULL;
+ }
+
+ /* Potentially detect explosive regex here. */
+ gData->backTrackCount++;
+ if (gData->backTrackLimit &&
+ gData->backTrackCount >= gData->backTrackLimit) {
+ JS_ReportErrorNumber(gData->cx, js_GetErrorMessage, NULL,
+ JSMSG_REGEXP_TOO_COMPLEX);
+ gData->ok = JS_FALSE;
+ return NULL;
+ }
+
+ backTrackData = gData->backTrackSP;
+ gData->cursz = backTrackData->sz;
+ gData->backTrackSP =
+ (REBackTrackData *) ((char *)backTrackData - backTrackData->sz);
+ x->cp = backTrackData->cp;
+ pc = backTrackData->backtrack_pc;
+ op = (REOp) backTrackData->backtrack_op;
+ JS_ASSERT(op < REOP_LIMIT);
+ gData->stateStackTop = backTrackData->saveStateStackTop;
+ JS_ASSERT(gData->stateStackTop);
+
+ memcpy(gData->stateStack, backTrackData + 1,
+ sizeof(REProgState) * backTrackData->saveStateStackTop);
+ curState = &gData->stateStack[gData->stateStackTop - 1];
+
+ if (backTrackData->parenCount) {
+ memcpy(&x->parens[backTrackData->parenIndex],
+ (char *)(backTrackData + 1) +
+ sizeof(REProgState) * backTrackData->saveStateStackTop,
+ sizeof(RECapture) * backTrackData->parenCount);
+ parenSoFar = backTrackData->parenIndex + backTrackData->parenCount;
+ } else {
+ for (k = curState->parenSoFar; k < parenSoFar; k++)
+ x->parens[k].index = -1;
+ parenSoFar = curState->parenSoFar;
+ }
+
+ re_debug("\tBT_Pop: %ld,%ld",
+ (unsigned long) backTrackData->parenIndex,
+ (unsigned long) backTrackData->parenCount);
+ continue;
+ }
+ x = result;
+
+ /*
+ * Continue with the expression.
+ */
+ op = (REOp)*pc++;
+ JS_ASSERT(op < REOP_LIMIT);
+ }
+
+bad:
+ re_debug("\n");
+ return NULL;
+
+good:
+ re_debug("\n");
+ return x;
+}
+
+static REMatchState *
+MatchRegExp(REGlobalData *gData, REMatchState *x)
+{
+ REMatchState *result;
+ const jschar *cp = x->cp;
+ const jschar *cp2;
+ uintN j;
+#ifdef JS_TRACER
+ Fragment *fragment;
+
+ /* Run with native regexp if possible. */
+ if (TRACING_ENABLED(gData->cx) &&
+ ((fragment = JS_TRACE_MONITOR(gData->cx).reFragmento->getLoop(gData->regexp)) != NULL)
+ && fragment->code() && !fragment->isBlacklisted()) {
+ union { NIns *code; REMatchState* (FASTCALL *func)(void*, void*); } u;
+ u.code = fragment->code();
+ REMatchState *lr;
+ gData->skipped = (ptrdiff_t) x->cp;
+
+ debug_only_v(printf("entering REGEXP trace at %s:%u@%u, code: %p\n",
+ gData->cx->fp->script->filename,
+ js_FramePCToLineNumber(gData->cx, gData->cx->fp),
+ FramePCOffset(gData->cx->fp),
+ fragment->code()););
+
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+ SIMULATE_FASTCALL(lr, x, gData, u.func);
+#else
+ lr = u.func(x, gData);
+#endif
+
+ debug_only_v(printf("leaving REGEXP trace\n"));
+
+ gData->skipped = ((const jschar *) gData->skipped) - cp;
+ return lr;
+ }
+#endif
+ /*
+ * Have to include the position beyond the last character
+ * in order to detect end-of-input/line condition.
+ */
+ for (cp2 = cp; cp2 <= gData->cpend; cp2++) {
+ gData->skipped = cp2 - cp;
+ x->cp = cp2;
+ for (j = 0; j < gData->regexp->parenCount; j++)
+ x->parens[j].index = -1;
+ result = ExecuteREBytecode(gData, x);
+ if (!gData->ok || result || (gData->regexp->flags & JSREG_STICKY))
+ return result;
+ gData->backTrackSP = gData->backTrackStack;
+ gData->cursz = 0;
+ gData->stateStackTop = 0;
+ cp2 = cp + gData->skipped;
+ }
+ return NULL;
+}
+
+#define MIN_BACKTRACK_LIMIT 400000
+
+static REMatchState *
+InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re, size_t length)
+{
+ REMatchState *result;
+ uintN i;
+
+ gData->backTrackStackSize = INITIAL_BACKTRACK;
+ JS_ARENA_ALLOCATE_CAST(gData->backTrackStack, REBackTrackData *,
+ &cx->regexpPool,
+ INITIAL_BACKTRACK);
+ if (!gData->backTrackStack)
+ goto bad;
+
+ gData->backTrackSP = gData->backTrackStack;
+ gData->cursz = 0;
+ gData->backTrackCount = 0;
+ gData->backTrackLimit = 0;
+ if (JS_GetOptions(cx) & JSOPTION_RELIMIT) {
+ gData->backTrackLimit = length * length * length; /* O(n^3) */
+ if (gData->backTrackLimit < MIN_BACKTRACK_LIMIT)
+ gData->backTrackLimit = MIN_BACKTRACK_LIMIT;
+ }
+
+ gData->stateStackLimit = INITIAL_STATESTACK;
+ JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *,
+ &cx->regexpPool,
+ sizeof(REProgState) * INITIAL_STATESTACK);
+ if (!gData->stateStack)
+ goto bad;
+
+ gData->stateStackTop = 0;
+ gData->cx = cx;
+ gData->regexp = re;
+ gData->ok = JS_TRUE;
+
+ JS_ARENA_ALLOCATE_CAST(result, REMatchState *,
+ &cx->regexpPool,
+ offsetof(REMatchState, parens)
+ + re->parenCount * sizeof(RECapture));
+ if (!result)
+ goto bad;
+
+ for (i = 0; i < re->classCount; i++) {
+ if (!re->classList[i].converted &&
+ !ProcessCharSet(gData, &re->classList[i])) {
+ return NULL;
+ }
+ }
+
+ return result;
+
+bad:
+ js_ReportOutOfScriptQuota(cx);
+ gData->ok = JS_FALSE;
+ return NULL;
+}
+
+JSBool
+js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
+ JSBool test, jsval *rval)
+{
+ REGlobalData gData;
+ REMatchState *x, *result;
+
+ const jschar *cp, *ep;
+ size_t i, length, start;
+ JSSubString *morepar;
+ JSBool ok;
+ JSRegExpStatics *res;
+ ptrdiff_t matchlen;
+ uintN num, morenum;
+ JSString *parstr, *matchstr;
+ JSObject *obj;
+
+ RECapture *parsub = NULL;
+ void *mark;
+ int64 *timestamp;
+
+ /*
+ * It's safe to load from cp because JSStrings have a zero at the end,
+ * and we never let cp get beyond cpend.
+ */
+ start = *indexp;
+ JSSTRING_CHARS_AND_LENGTH(str, cp, length);
+ if (start > length)
+ start = length;
+ gData.cpbegin = cp;
+ gData.cpend = cp + length;
+ cp += start;
+ gData.start = start;
+ gData.skipped = 0;
+
+ if (!cx->regexpPool.first.next) {
+ /*
+ * The first arena in the regexpPool must have a timestamp at its base.
+ */
+ JS_ARENA_ALLOCATE_CAST(timestamp, int64 *,
+ &cx->regexpPool, sizeof *timestamp);
+ if (!timestamp)
+ return JS_FALSE;
+ *timestamp = JS_Now();
+ }
+ mark = JS_ARENA_MARK(&cx->regexpPool);
+
+ x = InitMatch(cx, &gData, re, length);
+
+ if (!x) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ x->cp = cp;
+
+ /*
+ * Call the recursive matcher to do the real work. Return null on mismatch
+ * whether testing or not. On match, return an extended Array object.
+ */
+ result = MatchRegExp(&gData, x);
+ ok = gData.ok;
+ if (!ok)
+ goto out;
+ if (!result) {
+ *rval = JSVAL_NULL;
+ goto out;
+ }
+ cp = result->cp;
+ i = cp - gData.cpbegin;
+ *indexp = i;
+ matchlen = i - (start + gData.skipped);
+ ep = cp;
+ cp -= matchlen;
+
+ if (test) {
+ /*
+ * Testing for a match and updating cx->regExpStatics: don't allocate
+ * an array object, do return true.
+ */
+ *rval = JSVAL_TRUE;
+
+ /* Avoid warning. (gcc doesn't detect that obj is needed iff !test); */
+ obj = NULL;
+ } else {
+ /*
+ * The array returned on match has element 0 bound to the matched
+ * string, elements 1 through state.parenCount bound to the paren
+ * matches, an index property telling the length of the left context,
+ * and an input property referring to the input string.
+ */
+ obj = js_NewSlowArrayObject(cx);
+ if (!obj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ *rval = OBJECT_TO_JSVAL(obj);
+
+#define DEFVAL(val, id) { \
+ ok = js_DefineProperty(cx, obj, id, val, \
+ JS_PropertyStub, JS_PropertyStub, \
+ JSPROP_ENUMERATE, NULL); \
+ if (!ok) { \
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL; \
+ cx->weakRoots.newborn[GCX_STRING] = NULL; \
+ goto out; \
+ } \
+}
+
+ matchstr = js_NewStringCopyN(cx, cp, matchlen);
+ if (!matchstr) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ ok = JS_FALSE;
+ goto out;
+ }
+ DEFVAL(STRING_TO_JSVAL(matchstr), INT_TO_JSID(0));
+ }
+
+ res = &cx->regExpStatics;
+ res->input = str;
+ res->parenCount = re->parenCount;
+ if (re->parenCount == 0) {
+ res->lastParen = js_EmptySubString;
+ } else {
+ for (num = 0; num < re->parenCount; num++) {
+ parsub = &result->parens[num];
+ if (num < 9) {
+ if (parsub->index == -1) {
+ res->parens[num].chars = NULL;
+ res->parens[num].length = 0;
+ } else {
+ res->parens[num].chars = gData.cpbegin + parsub->index;
+ res->parens[num].length = parsub->length;
+ }
+ } else {
+ morenum = num - 9;
+ morepar = res->moreParens;
+ if (!morepar) {
+ res->moreLength = 10;
+ morepar = (JSSubString*)
+ JS_malloc(cx, 10 * sizeof(JSSubString));
+ } else if (morenum >= res->moreLength) {
+ res->moreLength += 10;
+ morepar = (JSSubString*)
+ JS_realloc(cx, morepar,
+ res->moreLength * sizeof(JSSubString));
+ }
+ if (!morepar) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ cx->weakRoots.newborn[GCX_STRING] = NULL;
+ ok = JS_FALSE;
+ goto out;
+ }
+ res->moreParens = morepar;
+ if (parsub->index == -1) {
+ morepar[morenum].chars = NULL;
+ morepar[morenum].length = 0;
+ } else {
+ morepar[morenum].chars = gData.cpbegin + parsub->index;
+ morepar[morenum].length = parsub->length;
+ }
+ }
+ if (test)
+ continue;
+ if (parsub->index == -1) {
+ ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1),
+ JSVAL_VOID, NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ } else {
+ parstr = js_NewStringCopyN(cx, gData.cpbegin + parsub->index,
+ parsub->length);
+ if (!parstr) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ cx->weakRoots.newborn[GCX_STRING] = NULL;
+ ok = JS_FALSE;
+ goto out;
+ }
+ ok = js_DefineProperty(cx, obj, INT_TO_JSID(num + 1),
+ STRING_TO_JSVAL(parstr), NULL, NULL,
+ JSPROP_ENUMERATE, NULL);
+ }
+ if (!ok) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ cx->weakRoots.newborn[GCX_STRING] = NULL;
+ goto out;
+ }
+ }
+ if (parsub->index == -1) {
+ res->lastParen = js_EmptySubString;
+ } else {
+ res->lastParen.chars = gData.cpbegin + parsub->index;
+ res->lastParen.length = parsub->length;
+ }
+ }
+
+ if (!test) {
+ /*
+ * Define the index and input properties last for better for/in loop
+ * order (so they come after the elements).
+ */
+ DEFVAL(INT_TO_JSVAL(start + gData.skipped),
+ ATOM_TO_JSID(cx->runtime->atomState.indexAtom));
+ DEFVAL(STRING_TO_JSVAL(str),
+ ATOM_TO_JSID(cx->runtime->atomState.inputAtom));
+ }
+
+#undef DEFVAL
+
+ res->lastMatch.chars = cp;
+ res->lastMatch.length = matchlen;
+
+ /*
+ * For JS1.3 and ECMAv2, emulate Perl5 exactly:
+ *
+ * js1.3 "hi", "hi there" "hihitherehi therebye"
+ */
+ res->leftContext.chars = JSSTRING_CHARS(str);
+ res->leftContext.length = start + gData.skipped;
+ res->rightContext.chars = ep;
+ res->rightContext.length = gData.cpend - ep;
+
+out:
+ JS_ARENA_RELEASE(&cx->regexpPool, mark);
+ return ok;
+}
+
+/************************************************************************/
+
+#define REGEXP_PROP_ATTRS (JSPROP_PERMANENT | JSPROP_SHARED)
+#define RO_REGEXP_PROP_ATTRS (REGEXP_PROP_ATTRS | JSPROP_READONLY)
+
+static JSPropertySpec regexp_props[] = {
+ {"source", REGEXP_SOURCE, RO_REGEXP_PROP_ATTRS,0,0},
+ {"global", REGEXP_GLOBAL, RO_REGEXP_PROP_ATTRS,0,0},
+ {"ignoreCase", REGEXP_IGNORE_CASE, RO_REGEXP_PROP_ATTRS,0,0},
+ {"lastIndex", REGEXP_LAST_INDEX, REGEXP_PROP_ATTRS,0,0},
+ {"multiline", REGEXP_MULTILINE, RO_REGEXP_PROP_ATTRS,0,0},
+ {"sticky", REGEXP_STICKY, RO_REGEXP_PROP_ATTRS,0,0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+regexp_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSRegExp *re;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) {
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (!obj)
+ return JS_TRUE;
+ }
+ slot = JSVAL_TO_INT(id);
+ if (slot == REGEXP_LAST_INDEX)
+ return JS_GetReservedSlot(cx, obj, 0, vp);
+
+ JS_LOCK_OBJ(cx, obj);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (re) {
+ switch (slot) {
+ case REGEXP_SOURCE:
+ *vp = STRING_TO_JSVAL(re->source);
+ break;
+ case REGEXP_GLOBAL:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_GLOB) != 0);
+ break;
+ case REGEXP_IGNORE_CASE:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_FOLD) != 0);
+ break;
+ case REGEXP_MULTILINE:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_MULTILINE) != 0);
+ break;
+ case REGEXP_STICKY:
+ *vp = BOOLEAN_TO_JSVAL((re->flags & JSREG_STICKY) != 0);
+ break;
+ }
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+}
+
+static JSBool
+regexp_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSBool ok;
+ jsint slot;
+ jsdouble lastIndex;
+
+ ok = JS_TRUE;
+ if (!JSVAL_IS_INT(id))
+ return ok;
+ while (OBJ_GET_CLASS(cx, obj) != &js_RegExpClass) {
+ obj = OBJ_GET_PROTO(cx, obj);
+ if (!obj)
+ return JS_TRUE;
+ }
+ slot = JSVAL_TO_INT(id);
+ if (slot == REGEXP_LAST_INDEX) {
+ if (!JS_ValueToNumber(cx, *vp, &lastIndex))
+ return JS_FALSE;
+ lastIndex = js_DoubleToInteger(lastIndex);
+ ok = JS_NewNumberValue(cx, lastIndex, vp) &&
+ JS_SetReservedSlot(cx, obj, 0, *vp);
+ }
+ return ok;
+}
+
+/*
+ * RegExp class static properties and their Perl counterparts:
+ *
+ * RegExp.input $_
+ * RegExp.multiline $*
+ * RegExp.lastMatch $&
+ * RegExp.lastParen $+
+ * RegExp.leftContext $`
+ * RegExp.rightContext $'
+ */
+enum regexp_static_tinyid {
+ REGEXP_STATIC_INPUT = -1,
+ REGEXP_STATIC_MULTILINE = -2,
+ REGEXP_STATIC_LAST_MATCH = -3,
+ REGEXP_STATIC_LAST_PAREN = -4,
+ REGEXP_STATIC_LEFT_CONTEXT = -5,
+ REGEXP_STATIC_RIGHT_CONTEXT = -6
+};
+
+JSBool
+js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res)
+{
+ JS_ClearRegExpStatics(cx);
+ return js_AddRoot(cx, &res->input, "res->input");
+}
+
+void
+js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res)
+{
+ if (res->moreParens) {
+ JS_free(cx, res->moreParens);
+ res->moreParens = NULL;
+ }
+ js_RemoveRoot(cx->runtime, &res->input);
+}
+
+static JSBool
+regexp_static_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsint slot;
+ JSRegExpStatics *res;
+ JSString *str;
+ JSSubString *sub;
+
+ res = &cx->regExpStatics;
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ slot = JSVAL_TO_INT(id);
+ switch (slot) {
+ case REGEXP_STATIC_INPUT:
+ *vp = res->input ? STRING_TO_JSVAL(res->input)
+ : JS_GetEmptyStringValue(cx);
+ return JS_TRUE;
+ case REGEXP_STATIC_MULTILINE:
+ *vp = BOOLEAN_TO_JSVAL(res->multiline);
+ return JS_TRUE;
+ case REGEXP_STATIC_LAST_MATCH:
+ sub = &res->lastMatch;
+ break;
+ case REGEXP_STATIC_LAST_PAREN:
+ sub = &res->lastParen;
+ break;
+ case REGEXP_STATIC_LEFT_CONTEXT:
+ sub = &res->leftContext;
+ break;
+ case REGEXP_STATIC_RIGHT_CONTEXT:
+ sub = &res->rightContext;
+ break;
+ default:
+ sub = REGEXP_PAREN_SUBSTRING(res, slot);
+ break;
+ }
+ str = js_NewStringCopyN(cx, sub->chars, sub->length);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+regexp_static_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSRegExpStatics *res;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+ res = &cx->regExpStatics;
+ /* XXX use if-else rather than switch to keep MSVC1.52 from crashing */
+ if (JSVAL_TO_INT(id) == REGEXP_STATIC_INPUT) {
+ if (!JSVAL_IS_STRING(*vp) &&
+ !JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp)) {
+ return JS_FALSE;
+ }
+ res->input = JSVAL_TO_STRING(*vp);
+ } else if (JSVAL_TO_INT(id) == REGEXP_STATIC_MULTILINE) {
+ if (!JSVAL_IS_BOOLEAN(*vp) &&
+ !JS_ConvertValue(cx, *vp, JSTYPE_BOOLEAN, vp)) {
+ return JS_FALSE;
+ }
+ res->multiline = JSVAL_TO_BOOLEAN(*vp);
+ }
+ return JS_TRUE;
+}
+#define REGEXP_STATIC_PROP_ATTRS (REGEXP_PROP_ATTRS | JSPROP_ENUMERATE)
+#define RO_REGEXP_STATIC_PROP_ATTRS (REGEXP_STATIC_PROP_ATTRS | JSPROP_READONLY)
+
+static JSPropertySpec regexp_static_props[] = {
+ {"input",
+ REGEXP_STATIC_INPUT,
+ REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_setProperty},
+ {"multiline",
+ REGEXP_STATIC_MULTILINE,
+ REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_setProperty},
+ {"lastMatch",
+ REGEXP_STATIC_LAST_MATCH,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"lastParen",
+ REGEXP_STATIC_LAST_PAREN,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"leftContext",
+ REGEXP_STATIC_LEFT_CONTEXT,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"rightContext",
+ REGEXP_STATIC_RIGHT_CONTEXT,
+ RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+
+ /* XXX should have block scope and local $1, etc. */
+ {"$1", 0, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$2", 1, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$3", 2, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$4", 3, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$5", 4, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$6", 5, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$7", 6, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$8", 7, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+ {"$9", 8, RO_REGEXP_STATIC_PROP_ATTRS,
+ regexp_static_getProperty, regexp_static_getProperty},
+
+ {0,0,0,0,0}
+};
+
+static void
+regexp_finalize(JSContext *cx, JSObject *obj)
+{
+ JSRegExp *re;
+
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!re)
+ return;
+ js_DestroyRegExp(cx, re);
+}
+
+/* Forward static prototype. */
+static JSBool
+regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ JSBool test, jsval *rval);
+
+static JSBool
+regexp_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ return regexp_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv,
+ JS_FALSE, rval);
+}
+
+#if JS_HAS_XDR
+
+#include "jsxdrapi.h"
+
+static JSBool
+regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
+{
+ JSRegExp *re;
+ JSString *source;
+ uint32 flagsword;
+ JSObject *obj;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ re = (JSRegExp *) JS_GetPrivate(xdr->cx, *objp);
+ if (!re)
+ return JS_FALSE;
+ source = re->source;
+ flagsword = (uint32)re->flags;
+ }
+ if (!JS_XDRString(xdr, &source) ||
+ !JS_XDRUint32(xdr, &flagsword)) {
+ return JS_FALSE;
+ }
+ if (xdr->mode == JSXDR_DECODE) {
+ obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ STOBJ_CLEAR_PARENT(obj);
+ STOBJ_CLEAR_PROTO(obj);
+ re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE);
+ if (!re)
+ return JS_FALSE;
+ if (!JS_SetPrivate(xdr->cx, obj, re) ||
+ !js_SetLastIndex(xdr->cx, obj, 0)) {
+ js_DestroyRegExp(xdr->cx, re);
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ return JS_TRUE;
+}
+
+#else /* !JS_HAS_XDR */
+
+#define regexp_xdrObject NULL
+
+#endif /* !JS_HAS_XDR */
+
+static void
+regexp_trace(JSTracer *trc, JSObject *obj)
+{
+ JSRegExp *re;
+
+ re = (JSRegExp *) JS_GetPrivate(trc->context, obj);
+ if (re && re->source)
+ JS_CALL_STRING_TRACER(trc, re->source, "source");
+}
+
+JSClass js_RegExpClass = {
+ js_RegExp_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp),
+ JS_PropertyStub, JS_PropertyStub,
+ regexp_getProperty, regexp_setProperty,
+ JS_EnumerateStub, JS_ResolveStub,
+ JS_ConvertStub, regexp_finalize,
+ NULL, NULL,
+ regexp_call, NULL,
+ regexp_xdrObject, NULL,
+ JS_CLASS_TRACE(regexp_trace), 0
+};
+
+static const jschar empty_regexp_ucstr[] = {'(', '?', ':', ')', 0};
+
+JSBool
+js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp)
+{
+ JSRegExp *re;
+ const jschar *source;
+ jschar *chars;
+ size_t length, nflags;
+ uintN flags;
+ JSString *str;
+
+ if (!JS_InstanceOf(cx, obj, &js_RegExpClass, vp + 2))
+ return JS_FALSE;
+ JS_LOCK_OBJ(cx, obj);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!re) {
+ JS_UNLOCK_OBJ(cx, obj);
+ *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ JSSTRING_CHARS_AND_LENGTH(re->source, source, length);
+ if (length == 0) {
+ source = empty_regexp_ucstr;
+ length = JS_ARRAY_LENGTH(empty_regexp_ucstr) - 1;
+ }
+ length += 2;
+ nflags = 0;
+ for (flags = re->flags; flags != 0; flags &= flags - 1)
+ nflags++;
+ chars = (jschar*) JS_malloc(cx, (length + nflags + 1) * sizeof(jschar));
+ if (!chars) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_FALSE;
+ }
+
+ chars[0] = '/';
+ js_strncpy(&chars[1], source, length - 2);
+ chars[length-1] = '/';
+ if (nflags) {
+ if (re->flags & JSREG_GLOB)
+ chars[length++] = 'g';
+ if (re->flags & JSREG_FOLD)
+ chars[length++] = 'i';
+ if (re->flags & JSREG_MULTILINE)
+ chars[length++] = 'm';
+ if (re->flags & JSREG_STICKY)
+ chars[length++] = 'y';
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ chars[length] = 0;
+
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+regexp_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_regexp_toString(cx, obj, vp);
+}
+
+static JSBool
+regexp_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *opt, *str;
+ JSRegExp *oldre, *re;
+ JSBool ok, ok2;
+ JSObject *obj2;
+ size_t length, nbytes;
+ const jschar *cp, *start, *end;
+ jschar *nstart, *ncp, *tmp;
+
+ if (!JS_InstanceOf(cx, obj, &js_RegExpClass, argv))
+ return JS_FALSE;
+ opt = NULL;
+ if (argc == 0) {
+ str = cx->runtime->emptyString;
+ } else {
+ if (JSVAL_IS_OBJECT(argv[0])) {
+ /*
+ * If we get passed in a RegExp object we construct a new
+ * RegExp that is a duplicate of it by re-compiling the
+ * original source code. ECMA requires that it be an error
+ * here if the flags are specified. (We must use the flags
+ * from the original RegExp also).
+ */
+ obj2 = JSVAL_TO_OBJECT(argv[0]);
+ if (obj2 && OBJ_GET_CLASS(cx, obj2) == &js_RegExpClass) {
+ if (argc >= 2 && !JSVAL_IS_VOID(argv[1])) { /* 'flags' passed */
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NEWREGEXP_FLAGGED);
+ return JS_FALSE;
+ }
+ JS_LOCK_OBJ(cx, obj2);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj2);
+ if (!re) {
+ JS_UNLOCK_OBJ(cx, obj2);
+ return JS_FALSE;
+ }
+ re = js_NewRegExp(cx, NULL, re->source, re->flags, JS_FALSE);
+ JS_UNLOCK_OBJ(cx, obj2);
+ goto created;
+ }
+ }
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+ if (argc > 1) {
+ if (JSVAL_IS_VOID(argv[1])) {
+ opt = NULL;
+ } else {
+ opt = js_ValueToString(cx, argv[1]);
+ if (!opt)
+ return JS_FALSE;
+ argv[1] = STRING_TO_JSVAL(opt);
+ }
+ }
+
+ /* Escape any naked slashes in the regexp source. */
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ end = start + length;
+ nstart = ncp = NULL;
+ for (cp = start; cp < end; cp++) {
+ if (*cp == '/' && (cp == start || cp[-1] != '\\')) {
+ nbytes = (++length + 1) * sizeof(jschar);
+ if (!nstart) {
+ nstart = (jschar *) JS_malloc(cx, nbytes);
+ if (!nstart)
+ return JS_FALSE;
+ ncp = nstart + (cp - start);
+ js_strncpy(nstart, start, cp - start);
+ } else {
+ tmp = (jschar *) JS_realloc(cx, nstart, nbytes);
+ if (!tmp) {
+ JS_free(cx, nstart);
+ return JS_FALSE;
+ }
+ ncp = tmp + (ncp - nstart);
+ nstart = tmp;
+ }
+ *ncp++ = '\\';
+ }
+ if (nstart)
+ *ncp++ = *cp;
+ }
+
+ if (nstart) {
+ /* Don't forget to store the backstop after the new string. */
+ JS_ASSERT((size_t)(ncp - nstart) == length);
+ *ncp = 0;
+ str = js_NewString(cx, nstart, length);
+ if (!str) {
+ JS_free(cx, nstart);
+ return JS_FALSE;
+ }
+ argv[0] = STRING_TO_JSVAL(str);
+ }
+ }
+
+ re = js_NewRegExpOpt(cx, str, opt, JS_FALSE);
+created:
+ if (!re)
+ return JS_FALSE;
+ JS_LOCK_OBJ(cx, obj);
+ oldre = (JSRegExp *) JS_GetPrivate(cx, obj);
+ ok = JS_SetPrivate(cx, obj, re);
+ ok2 = js_SetLastIndex(cx, obj, 0);
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!ok) {
+ js_DestroyRegExp(cx, re);
+ return JS_FALSE;
+ }
+ if (oldre)
+ js_DestroyRegExp(cx, oldre);
+ *rval = OBJECT_TO_JSVAL(obj);
+ return ok2;
+}
+
+static JSBool
+regexp_compile(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && regexp_compile_sub(cx, obj, argc, vp + 2, vp);
+}
+
+static JSBool
+regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ JSBool test, jsval *rval)
+{
+ JSBool ok, sticky;
+ JSRegExp *re;
+ jsdouble lastIndex;
+ JSString *str;
+ size_t i;
+
+ ok = JS_InstanceOf(cx, obj, &js_RegExpClass, argv);
+ if (!ok)
+ return JS_FALSE;
+ JS_LOCK_OBJ(cx, obj);
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!re) {
+ JS_UNLOCK_OBJ(cx, obj);
+ return JS_TRUE;
+ }
+
+ /* NB: we must reach out: after this paragraph, in order to drop re. */
+ HOLD_REGEXP(cx, re);
+ sticky = (re->flags & JSREG_STICKY) != 0;
+ if (re->flags & (JSREG_GLOB | JSREG_STICKY)) {
+ ok = js_GetLastIndex(cx, obj, &lastIndex);
+ } else {
+ lastIndex = 0;
+ }
+ JS_UNLOCK_OBJ(cx, obj);
+ if (!ok)
+ goto out;
+
+ /* Now that obj is unlocked, it's safe to (potentially) grab the GC lock. */
+ if (argc == 0) {
+ str = cx->regExpStatics.input;
+ if (!str) {
+ const char *bytes = js_GetStringBytes(cx, re->source);
+
+ if (bytes) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NO_INPUT,
+ bytes,
+ (re->flags & JSREG_GLOB) ? "g" : "",
+ (re->flags & JSREG_FOLD) ? "i" : "",
+ (re->flags & JSREG_MULTILINE) ? "m" : "",
+ (re->flags & JSREG_STICKY) ? "y" : "");
+ }
+ ok = JS_FALSE;
+ goto out;
+ }
+ } else {
+ str = js_ValueToString(cx, argv[0]);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ argv[0] = STRING_TO_JSVAL(str);
+ }
+
+ if (lastIndex < 0 || JSSTRING_LENGTH(str) < lastIndex) {
+ ok = js_SetLastIndex(cx, obj, 0);
+ *rval = JSVAL_NULL;
+ } else {
+ i = (size_t) lastIndex;
+ ok = js_ExecuteRegExp(cx, re, str, &i, test, rval);
+ if (ok &&
+ ((re->flags & JSREG_GLOB) || (*rval != JSVAL_NULL && sticky))) {
+ ok = js_SetLastIndex(cx, obj, (*rval == JSVAL_NULL) ? 0 : i);
+ }
+ }
+
+out:
+ DROP_REGEXP(cx, re);
+ return ok;
+}
+
+static JSBool
+regexp_exec(JSContext *cx, uintN argc, jsval *vp)
+{
+ return regexp_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, JS_FALSE,
+ vp);
+}
+
+static JSBool
+regexp_test(JSContext *cx, uintN argc, jsval *vp)
+{
+ if (!regexp_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, JS_TRUE, vp))
+ return JS_FALSE;
+ if (*vp != JSVAL_TRUE)
+ *vp = JSVAL_FALSE;
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static jsint FASTCALL
+Regexp_p_test(JSContext* cx, JSObject* regexp, JSString* str)
+{
+ jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(str) };
+ if (!regexp_exec_sub(cx, regexp, 1, vp + 2, JS_TRUE, vp))
+ return JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ return *vp == JSVAL_TRUE;
+}
+
+JS_DEFINE_TRCINFO_1(regexp_test,
+ (3, (static, BOOL_FAIL, Regexp_p_test, CONTEXT, THIS, STRING, 1, 1)))
+
+#endif
+
+static JSFunctionSpec regexp_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, regexp_toString, 0,0),
+#endif
+ JS_FN(js_toString_str, regexp_toString, 0,0),
+ JS_FN("compile", regexp_compile, 2,0),
+ JS_FN("exec", regexp_exec, 1,0),
+ JS_TN("test", regexp_test, 1,0, regexp_test_trcinfo),
+ JS_FS_END
+};
+
+static JSBool
+RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ /*
+ * If first arg is regexp and no flags are given, just return the arg.
+ * (regexp_compile_sub detects the regexp + flags case and throws a
+ * TypeError.) See 10.15.3.1.
+ */
+ if ((argc < 2 || JSVAL_IS_VOID(argv[1])) &&
+ !JSVAL_IS_PRIMITIVE(argv[0]) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[0])) == &js_RegExpClass) {
+ *rval = argv[0];
+ return JS_TRUE;
+ }
+
+ /* Otherwise, replace obj with a new RegExp object. */
+ obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * regexp_compile_sub does not use rval to root its temporaries so we
+ * can use it to root obj.
+ */
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+ return regexp_compile_sub(cx, obj, argc, argv, rval);
+}
+
+JSObject *
+js_InitRegExpClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *ctor;
+ jsval rval;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_RegExpClass, RegExp, 1,
+ regexp_props, regexp_methods,
+ regexp_static_props, NULL);
+
+ if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
+ return NULL;
+ if (!JS_AliasProperty(cx, ctor, "input", "$_") ||
+ !JS_AliasProperty(cx, ctor, "multiline", "$*") ||
+ !JS_AliasProperty(cx, ctor, "lastMatch", "$&") ||
+ !JS_AliasProperty(cx, ctor, "lastParen", "$+") ||
+ !JS_AliasProperty(cx, ctor, "leftContext", "$`") ||
+ !JS_AliasProperty(cx, ctor, "rightContext", "$'")) {
+ goto bad;
+ }
+
+ /* Give RegExp.prototype private data so it matches the empty string. */
+ if (!regexp_compile_sub(cx, proto, 0, NULL, &rval))
+ goto bad;
+ return proto;
+
+bad:
+ JS_DeleteProperty(cx, obj, js_RegExpClass.name);
+ return NULL;
+}
+
+JSObject *
+js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
+ jschar *chars, size_t length, uintN flags)
+{
+ JSString *str;
+ JSObject *obj;
+ JSRegExp *re;
+ JSTempValueRooter tvr;
+
+ str = js_NewStringCopyN(cx, chars, length);
+ if (!str)
+ return NULL;
+ re = js_NewRegExp(cx, ts, str, flags, JS_FALSE);
+ if (!re)
+ return NULL;
+ JS_PUSH_TEMP_ROOT_STRING(cx, str, &tvr);
+ obj = js_NewObject(cx, &js_RegExpClass, NULL, NULL, 0);
+ if (!obj || !JS_SetPrivate(cx, obj, re)) {
+ js_DestroyRegExp(cx, re);
+ obj = NULL;
+ }
+ if (obj && !js_SetLastIndex(cx, obj, 0))
+ obj = NULL;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+JSObject *
+js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent)
+{
+ JSObject *clone;
+ JSRegExp *re;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_RegExpClass);
+ clone = js_NewObject(cx, &js_RegExpClass, NULL, parent, 0);
+ if (!clone)
+ return NULL;
+ re = (JSRegExp *) JS_GetPrivate(cx, obj);
+ if (!JS_SetPrivate(cx, clone, re) || !js_SetLastIndex(cx, clone, 0)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+ HOLD_REGEXP(cx, re);
+ return clone;
+}
+
+JSBool
+js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex)
+{
+ jsval v;
+
+ return JS_GetReservedSlot(cx, obj, 0, &v) &&
+ JS_ValueToNumber(cx, v, lastIndex);
+}
+
+JSBool
+js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex)
+{
+ jsval v;
+
+ return JS_NewNumberValue(cx, lastIndex, &v) &&
+ JS_SetReservedSlot(cx, obj, 0, v);
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h
new file mode 100644
index 0000000..12d74a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsregexp.h
@@ -0,0 +1,192 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsregexp_h___
+#define jsregexp_h___
+/*
+ * JS regular expression interface.
+ */
+#include <stddef.h>
+#include "jspubtd.h"
+#include "jsstr.h"
+
+#ifdef JS_THREADSAFE
+#include "jsdhash.h"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+struct JSRegExpStatics {
+ JSString *input; /* input string to match (perl $_, GC root) */
+ JSBool multiline; /* whether input contains newlines (perl $*) */
+ uint16 parenCount; /* number of valid elements in parens[] */
+ uint16 moreLength; /* number of allocated elements in moreParens */
+ JSSubString parens[9]; /* last set of parens matched (perl $1, $2) */
+ JSSubString *moreParens; /* null or realloc'd vector for $10, etc. */
+ JSSubString lastMatch; /* last string matched (perl $&) */
+ JSSubString lastParen; /* last paren matched (perl $+) */
+ JSSubString leftContext; /* input to left of last match (perl $`) */
+ JSSubString rightContext; /* input to right of last match (perl $') */
+};
+
+/*
+ * This struct holds a bitmap representation of a class from a regexp.
+ * There's a list of these referenced by the classList field in the JSRegExp
+ * struct below. The initial state has startIndex set to the offset in the
+ * original regexp source of the beginning of the class contents. The first
+ * use of the class converts the source representation into a bitmap.
+ *
+ */
+typedef struct RECharSet {
+ JSPackedBool converted;
+ JSPackedBool sense;
+ uint16 length;
+ union {
+ uint8 *bits;
+ struct {
+ size_t startIndex;
+ size_t length;
+ } src;
+ } u;
+} RECharSet;
+
+/*
+ * This macro is safe because moreParens is guaranteed to be allocated and big
+ * enough to hold parenCount, or else be null when parenCount is 0.
+ */
+#define REGEXP_PAREN_SUBSTRING(res, num) \
+ (((jsuint)(num) < (jsuint)(res)->parenCount) \
+ ? ((jsuint)(num) < 9) \
+ ? &(res)->parens[num] \
+ : &(res)->moreParens[(num) - 9] \
+ : &js_EmptySubString)
+
+typedef struct RENode RENode;
+
+struct JSRegExp {
+ jsrefcount nrefs; /* reference count */
+ uint16 flags; /* flags, see jsapi.h's JSREG_* defines */
+ size_t parenCount; /* number of parenthesized submatches */
+ size_t classCount; /* count [...] bitmaps */
+ RECharSet *classList; /* list of [...] bitmaps */
+ JSString *source; /* locked source string, sans // */
+ jsbytecode program[1]; /* regular expression bytecode */
+};
+
+extern JSRegExp *
+js_NewRegExp(JSContext *cx, JSTokenStream *ts,
+ JSString *str, uintN flags, JSBool flat);
+
+extern JSRegExp *
+js_NewRegExpOpt(JSContext *cx, JSString *str, JSString *opt, JSBool flat);
+
+#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs)
+#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re)
+
+extern void
+js_DestroyRegExp(JSContext *cx, JSRegExp *re);
+
+/*
+ * Execute re on input str at *indexp, returning null in *rval on mismatch.
+ * On match, return true if test is true, otherwise return an array object.
+ * Update *indexp and cx->regExpStatics always on match.
+ */
+extern JSBool
+js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp,
+ JSBool test, jsval *rval);
+
+/*
+ * These two add and remove GC roots, respectively, so their calls must be
+ * well-ordered.
+ */
+extern JSBool
+js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res);
+
+extern void
+js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res);
+
+#define VALUE_IS_REGEXP(cx, v) \
+ (JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && \
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass)
+
+extern JSClass js_RegExpClass;
+
+enum regexp_tinyid {
+ REGEXP_SOURCE = -1,
+ REGEXP_GLOBAL = -2,
+ REGEXP_IGNORE_CASE = -3,
+ REGEXP_LAST_INDEX = -4,
+ REGEXP_MULTILINE = -5,
+ REGEXP_STICKY = -6
+};
+
+extern JSObject *
+js_InitRegExpClass(JSContext *cx, JSObject *obj);
+
+/*
+ * Export js_regexp_toString to the decompiler.
+ */
+extern JSBool
+js_regexp_toString(JSContext *cx, JSObject *obj, jsval *vp);
+
+/*
+ * Create, serialize/deserialize, or clone a RegExp object.
+ */
+extern JSObject *
+js_NewRegExpObject(JSContext *cx, JSTokenStream *ts,
+ jschar *chars, size_t length, uintN flags);
+
+extern JSBool
+js_XDRRegExp(JSXDRState *xdr, JSObject **objp);
+
+extern JSObject *
+js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent);
+
+/*
+ * Get and set the per-object (clone or clone-parent) lastIndex slot.
+ */
+extern JSBool
+js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex);
+
+extern JSBool
+js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex);
+
+JS_END_EXTERN_C
+
+#endif /* jsregexp_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl b/tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl
new file mode 100644
index 0000000..d7454c1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsreops.tbl
@@ -0,0 +1,145 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=0 ft=C:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "as is" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contentsof this file are subject to the Mozilla Public License Version
+ * 1.1 (the "license"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of thter (the "lgpl"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+/* Note : contiguity of 'simple opcodes' is important for SimpleMatch() */
+
+/* match rest of input against rest of r.e. */
+REOP_DEF(REOP_EMPTY, "empty")
+/* beginning of input (or line if multiline) */
+REOP_DEF(REOP_BOL, "bol")
+/* end of input (or line if multiline) */
+REOP_DEF(REOP_EOL, "eol")
+/* match "" at word boundary */
+REOP_DEF(REOP_WBDRY, "wbdry")
+/* match "" at word non-boundary */
+REOP_DEF(REOP_WNONBDRY, "wnonbdry")
+/* stands for any character */
+REOP_DEF(REOP_DOT, "dot")
+/* match a digit char: [0-9] */
+REOP_DEF(REOP_DIGIT, "digit")
+/* match a non-digit char: [^0-9] */
+REOP_DEF(REOP_NONDIGIT, "nondigit")
+/* match an alphanumeric char: [0-9a-z_A-Z] */
+REOP_DEF(REOP_ALNUM, "alnum")
+/* match a non-alphanumeric char: [^0-9a-z_A-Z] */
+REOP_DEF(REOP_NONALNUM, "nonalnum")
+/* match a whitespace char */
+REOP_DEF(REOP_SPACE, "space")
+/* match a non-whitespace char */
+REOP_DEF(REOP_NONSPACE, "nonspace")
+/* back-reference (e.g., \1) to a parenthetical */
+REOP_DEF(REOP_BACKREF, "backref")
+/* match a flat string */
+REOP_DEF(REOP_FLAT, "flat")
+/* match a single char */
+REOP_DEF(REOP_FLAT1, "flat1")
+/* case-independent REOP_FLAT */
+REOP_DEF(REOP_FLATi, "flati")
+/* case-independent REOP_FLAT1 */
+REOP_DEF(REOP_FLAT1i, "flat1i")
+/* single Unicode char */
+REOP_DEF(REOP_UCFLAT1, "ucflat1")
+/* case-independent REOP_UCFLAT1 */
+REOP_DEF(REOP_UCFLAT1i, "ucflat1i")
+/* flat Unicode string; len immediate counts chars */
+REOP_DEF(REOP_UCFLAT, "ucflat")
+/* case-independent REOP_UCFLAT */
+REOP_DEF(REOP_UCFLATi, "ucflati")
+/* character class with index */
+REOP_DEF(REOP_CLASS, "class")
+/* negated character class with index */
+REOP_DEF(REOP_NCLASS, "nclass")
+
+/* NCLASS is considered to be the last "simple" op-code */
+
+
+/* alternative subexpressions in kid and next */
+REOP_DEF(REOP_ALT, "alt")
+/* quantified atom: atom{1,2} */
+REOP_DEF(REOP_QUANT, "quant")
+/* zero or more occurrences of kid */
+REOP_DEF(REOP_STAR, "star")
+/* one or more occurrences of kid */
+REOP_DEF(REOP_PLUS, "plus")
+/* optional subexpression in kid */
+REOP_DEF(REOP_OPT, "opt")
+/* left paren bytecode: kid is u.num'th sub-regexp */
+REOP_DEF(REOP_LPAREN, "lparen")
+/* right paren bytecode */
+REOP_DEF(REOP_RPAREN, "rparen")
+/* for deoptimized closure loops */
+REOP_DEF(REOP_JUMP, "jump")
+/* optimize .* to use a single opcode */
+REOP_DEF(REOP_DOTSTAR, "dotstar")
+/* non-capturing version of REOP_LPAREN */
+REOP_DEF(REOP_LPARENNON, "lparennon")
+/* zero width positive lookahead assertion */
+REOP_DEF(REOP_ASSERT, "assert")
+/* zero width negative lookahead assertion */
+REOP_DEF(REOP_ASSERT_NOT, "assert_not")
+/* sentinel at end of assertion child */
+REOP_DEF(REOP_ASSERTTEST, "asserttest")
+/* sentinel at end of !assertion child */
+REOP_DEF(REOP_ASSERTNOTTEST, "assertnottest")
+/* non-greedy version of * */
+REOP_DEF(REOP_MINIMALSTAR, "minimalstar")
+/* non-greedy version of + */
+REOP_DEF(REOP_MINIMALPLUS, "minimalplus")
+/* non-greedy version of ? */
+REOP_DEF(REOP_MINIMALOPT, "minimalopt")
+/* non-greedy version of {} */
+REOP_DEF(REOP_MINIMALQUANT, "minimalquant")
+/* sentinel at end of quantifier child */
+REOP_DEF(REOP_ENDCHILD, "endchild")
+/* directs execution of greedy quantifier */
+REOP_DEF(REOP_REPEAT, "repeat")
+/* directs execution of non-greedy quantifier */
+REOP_DEF(REOP_MINIMALREPEAT, "minimalrepeat")
+/* prerequisite for ALT, either of two chars */
+REOP_DEF(REOP_ALTPREREQ, "altprereq")
+/* prerequisite for ALT, a char or a class */
+REOP_DEF(REOP_ALTPREREQ2, "altprereq2")
+/* end of final alternate */
+REOP_DEF(REOP_ENDALT, "endalt")
+/* concatenation of terms (parse time only) */
+REOP_DEF(REOP_CONCAT, "concat")
+/* end of expression */
+REOP_DEF(REOP_END, "end")
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp
new file mode 100644
index 0000000..f112a9a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.cpp
@@ -0,0 +1,2017 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=8 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS lexical scanner.
+ */
+#include "jsstddef.h"
+#include <stdio.h> /* first to avoid trouble on some systems */
+#include <errno.h>
+#include <limits.h>
+#include <math.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h" /* Added by JSIFY */
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsdtoa.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsemit.h"
+#include "jsexn.h"
+#include "jsnum.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsregexp.h"
+#include "jsscan.h"
+#include "jsscript.h"
+#include "jsstaticcheck.h"
+
+#if JS_HAS_XML_SUPPORT
+#include "jsxml.h"
+#endif
+
+#define JS_KEYWORD(keyword, type, op, version) \
+ const char js_##keyword##_str[] = #keyword;
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+
+struct keyword {
+ const char *chars; /* C string with keyword text */
+ JSTokenType tokentype; /* JSTokenType */
+ JSOp op; /* JSOp */
+ JSVersion version; /* JSVersion */
+};
+
+static const struct keyword keyword_defs[] = {
+#define JS_KEYWORD(keyword, type, op, version) \
+ {js_##keyword##_str, type, op, version},
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+};
+
+#define KEYWORD_COUNT JS_ARRAY_LENGTH(keyword_defs)
+
+static const struct keyword *
+FindKeyword(const jschar *s, size_t length)
+{
+ register size_t i;
+ const struct keyword *kw;
+ const char *chars;
+
+ JS_ASSERT(length != 0);
+
+#define JSKW_LENGTH() length
+#define JSKW_AT(column) s[column]
+#define JSKW_GOT_MATCH(index) i = (index); goto got_match;
+#define JSKW_TEST_GUESS(index) i = (index); goto test_guess;
+#define JSKW_NO_MATCH() goto no_match;
+#include "jsautokw.h"
+#undef JSKW_NO_MATCH
+#undef JSKW_TEST_GUESS
+#undef JSKW_GOT_MATCH
+#undef JSKW_AT
+#undef JSKW_LENGTH
+
+ got_match:
+ return &keyword_defs[i];
+
+ test_guess:
+ kw = &keyword_defs[i];
+ chars = kw->chars;
+ do {
+ if (*s++ != (unsigned char)(*chars++))
+ goto no_match;
+ } while (--length != 0);
+ return kw;
+
+ no_match:
+ return NULL;
+}
+
+JSTokenType
+js_CheckKeyword(const jschar *str, size_t length)
+{
+ const struct keyword *kw;
+
+ JS_ASSERT(length != 0);
+ kw = FindKeyword(str, length);
+ return kw ? kw->tokentype : TOK_EOF;
+}
+
+JS_FRIEND_API(void)
+js_MapKeywords(void (*mapfun)(const char *))
+{
+ size_t i;
+
+ for (i = 0; i != KEYWORD_COUNT; ++i)
+ mapfun(keyword_defs[i].chars);
+}
+
+JSBool
+js_IsIdentifier(JSString *str)
+{
+ size_t length;
+ jschar c, *chars, *end;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0)
+ return JS_FALSE;
+ c = *chars;
+ if (!JS_ISIDSTART(c))
+ return JS_FALSE;
+ end = chars + length;
+ while (++chars != end) {
+ c = *chars;
+ if (!JS_ISIDENT(c))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+#define TBMIN 64
+
+static JSBool
+GrowTokenBuf(JSStringBuffer *sb, size_t newlength)
+{
+ JSContext *cx;
+ jschar *base;
+ ptrdiff_t offset, length;
+ size_t tbsize;
+ JSArenaPool *pool;
+
+ cx = (JSContext*) sb->data;
+ base = sb->base;
+ offset = PTRDIFF(sb->ptr, base, jschar);
+ pool = &cx->tempPool;
+ if (!base) {
+ tbsize = TBMIN * sizeof(jschar);
+ length = TBMIN - 1;
+ JS_ARENA_ALLOCATE_CAST(base, jschar *, pool, tbsize);
+ } else {
+ length = PTRDIFF(sb->limit, base, jschar);
+ if ((size_t)length >= ~(size_t)0 / sizeof(jschar)) {
+ base = NULL;
+ } else {
+ tbsize = (length + 1) * sizeof(jschar);
+ length += length + 1;
+ JS_ARENA_GROW_CAST(base, jschar *, pool, tbsize, tbsize);
+ }
+ }
+ if (!base) {
+ js_ReportOutOfScriptQuota(cx);
+ sb->base = STRING_BUFFER_ERROR_BASE;
+ return JS_FALSE;
+ }
+ sb->base = base;
+ sb->limit = base + length;
+ sb->ptr = base + offset;
+ return JS_TRUE;
+}
+
+JSBool
+js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
+ const jschar *base, size_t length,
+ FILE *fp, const char *filename, uintN lineno)
+{
+ jschar *buf;
+ size_t nb;
+
+ JS_ASSERT_IF(fp, !base);
+ JS_ASSERT_IF(!base, length == 0);
+ nb = fp
+ ? 2 * JS_LINE_LIMIT * sizeof(jschar)
+ : JS_LINE_LIMIT * sizeof(jschar);
+ JS_ARENA_ALLOCATE_CAST(buf, jschar *, &cx->tempPool, nb);
+ if (!buf) {
+ js_ReportOutOfScriptQuota(cx);
+ return JS_FALSE;
+ }
+ memset(buf, 0, nb);
+ memset(ts, 0, sizeof(*ts));
+ ts->filename = filename;
+ ts->lineno = lineno;
+ ts->linebuf.base = ts->linebuf.limit = ts->linebuf.ptr = buf;
+ if (fp) {
+ ts->file = fp;
+ ts->userbuf.base = buf + JS_LINE_LIMIT;
+ ts->userbuf.ptr = ts->userbuf.limit = ts->userbuf.base + JS_LINE_LIMIT;
+ } else {
+ ts->userbuf.base = (jschar *)base;
+ ts->userbuf.limit = (jschar *)base + length;
+ ts->userbuf.ptr = (jschar *)base;
+ }
+ ts->tokenbuf.grow = GrowTokenBuf;
+ ts->tokenbuf.data = cx;
+ ts->listener = cx->debugHooks->sourceHandler;
+ ts->listenerData = cx->debugHooks->sourceHandlerData;
+ return JS_TRUE;
+}
+
+void
+js_CloseTokenStream(JSContext *cx, JSTokenStream *ts)
+{
+ if (ts->flags & TSF_OWNFILENAME)
+ JS_free(cx, (void *) ts->filename);
+}
+
+JS_FRIEND_API(int)
+js_fgets(char *buf, int size, FILE *file)
+{
+ int n, i, c;
+ JSBool crflag;
+
+ n = size - 1;
+ if (n < 0)
+ return -1;
+
+ crflag = JS_FALSE;
+ for (i = 0; i < n && (c = getc(file)) != EOF; i++) {
+ buf[i] = c;
+ if (c == '\n') { /* any \n ends a line */
+ i++; /* keep the \n; we know there is room for \0 */
+ break;
+ }
+ if (crflag) { /* \r not followed by \n ends line at the \r */
+ ungetc(c, file);
+ break; /* and overwrite c in buf with \0 */
+ }
+ crflag = (c == '\r');
+ }
+
+ buf[i] = '\0';
+ return i;
+}
+
+static int32
+GetChar(JSTokenStream *ts)
+{
+ int32 c;
+ ptrdiff_t i, j, len, olen;
+ JSBool crflag;
+ char cbuf[JS_LINE_LIMIT];
+ jschar *ubuf, *nl;
+
+ if (ts->ungetpos != 0) {
+ c = ts->ungetbuf[--ts->ungetpos];
+ } else {
+ if (ts->linebuf.ptr == ts->linebuf.limit) {
+ len = PTRDIFF(ts->userbuf.limit, ts->userbuf.ptr, jschar);
+ if (len <= 0) {
+ if (!ts->file) {
+ ts->flags |= TSF_EOF;
+ return EOF;
+ }
+
+ /* Fill ts->userbuf so that \r and \r\n convert to \n. */
+ crflag = (ts->flags & TSF_CRFLAG) != 0;
+ len = js_fgets(cbuf, JS_LINE_LIMIT - crflag, ts->file);
+ if (len <= 0) {
+ ts->flags |= TSF_EOF;
+ return EOF;
+ }
+ olen = len;
+ ubuf = ts->userbuf.base;
+ i = 0;
+ if (crflag) {
+ ts->flags &= ~TSF_CRFLAG;
+ if (cbuf[0] != '\n') {
+ ubuf[i++] = '\n';
+ len++;
+ ts->linepos--;
+ }
+ }
+ for (j = 0; i < len; i++, j++)
+ ubuf[i] = (jschar) (unsigned char) cbuf[j];
+ ts->userbuf.limit = ubuf + len;
+ ts->userbuf.ptr = ubuf;
+ }
+ if (ts->listener) {
+ ts->listener(ts->filename, ts->lineno, ts->userbuf.ptr, len,
+ &ts->listenerTSData, ts->listenerData);
+ }
+
+ nl = ts->saveEOL;
+ if (!nl) {
+ /*
+ * Any one of \n, \r, or \r\n ends a line (the longest
+ * match wins). Also allow the Unicode line and paragraph
+ * separators.
+ */
+ for (nl = ts->userbuf.ptr; nl < ts->userbuf.limit; nl++) {
+ /*
+ * Try to prevent value-testing on most characters by
+ * filtering out characters that aren't 000x or 202x.
+ */
+ if ((*nl & 0xDFD0) == 0) {
+ if (*nl == '\n')
+ break;
+ if (*nl == '\r') {
+ if (nl + 1 < ts->userbuf.limit && nl[1] == '\n')
+ nl++;
+ break;
+ }
+ if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR)
+ break;
+ }
+ }
+ }
+
+ /*
+ * If there was a line terminator, copy thru it into linebuf.
+ * Else copy JS_LINE_LIMIT-1 bytes into linebuf.
+ */
+ if (nl < ts->userbuf.limit)
+ len = PTRDIFF(nl, ts->userbuf.ptr, jschar) + 1;
+ if (len >= JS_LINE_LIMIT) {
+ len = JS_LINE_LIMIT - 1;
+ ts->saveEOL = nl;
+ } else {
+ ts->saveEOL = NULL;
+ }
+ js_strncpy(ts->linebuf.base, ts->userbuf.ptr, len);
+ ts->userbuf.ptr += len;
+ olen = len;
+
+ /*
+ * Make sure linebuf contains \n for EOL (don't do this in
+ * userbuf because the user's string might be readonly).
+ */
+ if (nl < ts->userbuf.limit) {
+ if (*nl == '\r') {
+ if (ts->linebuf.base[len-1] == '\r') {
+ /*
+ * Does the line segment end in \r? We must check
+ * for a \n at the front of the next segment before
+ * storing a \n into linebuf. This case matters
+ * only when we're reading from a file.
+ */
+ if (nl + 1 == ts->userbuf.limit && ts->file) {
+ len--;
+ ts->flags |= TSF_CRFLAG; /* clear NLFLAG? */
+ if (len == 0) {
+ /*
+ * This can happen when a segment ends in
+ * \r\r. Start over. ptr == limit in this
+ * case, so we'll fall into buffer-filling
+ * code.
+ */
+ return GetChar(ts);
+ }
+ } else {
+ ts->linebuf.base[len-1] = '\n';
+ }
+ }
+ } else if (*nl == '\n') {
+ if (nl > ts->userbuf.base &&
+ nl[-1] == '\r' &&
+ ts->linebuf.base[len-2] == '\r') {
+ len--;
+ JS_ASSERT(ts->linebuf.base[len] == '\n');
+ ts->linebuf.base[len-1] = '\n';
+ }
+ } else if (*nl == LINE_SEPARATOR || *nl == PARA_SEPARATOR) {
+ ts->linebuf.base[len-1] = '\n';
+ }
+ }
+
+ /* Reset linebuf based on adjusted segment length. */
+ ts->linebuf.limit = ts->linebuf.base + len;
+ ts->linebuf.ptr = ts->linebuf.base;
+
+ /* Update position of linebuf within physical userbuf line. */
+ if (!(ts->flags & TSF_NLFLAG))
+ ts->linepos += ts->linelen;
+ else
+ ts->linepos = 0;
+ if (ts->linebuf.limit[-1] == '\n')
+ ts->flags |= TSF_NLFLAG;
+ else
+ ts->flags &= ~TSF_NLFLAG;
+
+ /* Update linelen from original segment length. */
+ ts->linelen = olen;
+ }
+ c = *ts->linebuf.ptr++;
+ }
+ if (c == '\n')
+ ts->lineno++;
+ return c;
+}
+
+static void
+UngetChar(JSTokenStream *ts, int32 c)
+{
+ if (c == EOF)
+ return;
+ JS_ASSERT(ts->ungetpos < JS_ARRAY_LENGTH(ts->ungetbuf));
+ if (c == '\n')
+ ts->lineno--;
+ ts->ungetbuf[ts->ungetpos++] = (jschar)c;
+}
+
+static int32
+PeekChar(JSTokenStream *ts)
+{
+ int32 c;
+
+ c = GetChar(ts);
+ UngetChar(ts, c);
+ return c;
+}
+
+/*
+ * Peek n chars ahead into ts. Return true if n chars were read, false if
+ * there weren't enough characters in the input stream. This function cannot
+ * be used to peek into or past a newline.
+ */
+static JSBool
+PeekChars(JSTokenStream *ts, intN n, jschar *cp)
+{
+ intN i, j;
+ int32 c;
+
+ for (i = 0; i < n; i++) {
+ c = GetChar(ts);
+ if (c == EOF)
+ break;
+ if (c == '\n') {
+ UngetChar(ts, c);
+ break;
+ }
+ cp[i] = (jschar)c;
+ }
+ for (j = i - 1; j >= 0; j--)
+ UngetChar(ts, cp[j]);
+ return i == n;
+}
+
+static void
+SkipChars(JSTokenStream *ts, intN n)
+{
+ while (--n >= 0)
+ GetChar(ts);
+}
+
+static JSBool
+MatchChar(JSTokenStream *ts, int32 expect)
+{
+ int32 c;
+
+ c = GetChar(ts);
+ if (c == expect)
+ return JS_TRUE;
+ UngetChar(ts, c);
+ return JS_FALSE;
+}
+
+JSBool
+js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ uintN flags, uintN errorNumber, ...)
+{
+ JSErrorReport report;
+ char *message;
+ size_t linelength;
+ jschar *linechars;
+ char *linebytes;
+ va_list ap;
+ JSBool warning, ok;
+ JSTokenPos *tp;
+ uintN index, i;
+ JSErrorReporter onError;
+
+ JS_ASSERT(ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
+
+ if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
+ return JS_TRUE;
+
+ memset(&report, 0, sizeof report);
+ report.flags = flags;
+ report.errorNumber = errorNumber;
+ message = NULL;
+ linechars = NULL;
+ linebytes = NULL;
+
+ MUST_FLOW_THROUGH("out");
+ va_start(ap, errorNumber);
+ ok = js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL,
+ errorNumber, &message, &report, &warning,
+ !(flags & JSREPORT_UC), ap);
+ va_end(ap);
+ if (!ok) {
+ warning = JS_FALSE;
+ goto out;
+ }
+
+ report.filename = ts->filename;
+
+ if (pn) {
+ report.lineno = pn->pn_pos.begin.lineno;
+ if (report.lineno != ts->lineno)
+ goto report;
+ tp = &pn->pn_pos;
+ } else {
+ /* Point to the current token, not the next one to get. */
+ tp = &ts->tokens[ts->cursor].pos;
+ }
+ report.lineno = ts->lineno;
+ linelength = PTRDIFF(ts->linebuf.limit, ts->linebuf.base, jschar);
+ linechars = (jschar *)JS_malloc(cx, (linelength + 1) * sizeof(jschar));
+ if (!linechars) {
+ warning = JS_FALSE;
+ goto out;
+ }
+ memcpy(linechars, ts->linebuf.base, linelength * sizeof(jschar));
+ linechars[linelength] = 0;
+ linebytes = js_DeflateString(cx, linechars, linelength);
+ if (!linebytes) {
+ warning = JS_FALSE;
+ goto out;
+ }
+ report.linebuf = linebytes;
+
+ /*
+ * FIXME: What should instead happen here is that we should
+ * find error-tokens in userbuf, if !ts->file. That will
+ * allow us to deliver a more helpful error message, which
+ * includes all or part of the bad string or bad token. The
+ * code here yields something that looks truncated.
+ * See https://bugzilla.mozilla.org/show_bug.cgi?id=352970
+ */
+ index = 0;
+ if (tp->begin.lineno == tp->end.lineno) {
+ if (tp->begin.index < ts->linepos)
+ goto report;
+
+ index = tp->begin.index - ts->linepos;
+ }
+
+ report.tokenptr = report.linebuf + index;
+ report.uclinebuf = linechars;
+ report.uctokenptr = report.uclinebuf + index;
+
+ /*
+ * If there's a runtime exception type associated with this error
+ * number, set that as the pending exception. For errors occuring at
+ * compile time, this is very likely to be a JSEXN_SYNTAXERR.
+ *
+ * If an exception is thrown but not caught, the JSREPORT_EXCEPTION
+ * flag will be set in report.flags. Proper behavior for an error
+ * reporter is to ignore a report with this flag for all but top-level
+ * compilation errors. The exception will remain pending, and so long
+ * as the non-top-level "load", "eval", or "compile" native function
+ * returns false, the top-level reporter will eventually receive the
+ * uncaught exception report.
+ *
+ * XXX it'd probably be best if there was only one call to this
+ * function, but there seem to be two error reporter call points.
+ */
+ report:
+ onError = cx->errorReporter;
+
+ /*
+ * Try to raise an exception only if there isn't one already set --
+ * otherwise the exception will describe the last compile-time error,
+ * which is likely spurious.
+ */
+ if (!(ts->flags & TSF_ERROR)) {
+ if (js_ErrorToException(cx, message, &report))
+ onError = NULL;
+ }
+
+ /*
+ * Suppress any compile-time errors that don't occur at the top level.
+ * This may still fail, as interplevel may be zero in contexts where we
+ * don't really want to call the error reporter, as when js is called
+ * by other code which could catch the error.
+ */
+ if (cx->interpLevel != 0 && !JSREPORT_IS_WARNING(flags))
+ onError = NULL;
+
+ if (onError) {
+ JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
+
+ /*
+ * If debugErrorHook is present then we give it a chance to veto
+ * sending the error on to the regular error reporter.
+ */
+ if (hook && !hook(cx, message, &report,
+ cx->debugHooks->debugErrorHookData)) {
+ onError = NULL;
+ }
+ }
+ if (onError)
+ (*onError)(cx, message, &report);
+
+ out:
+ if (linebytes)
+ JS_free(cx, linebytes);
+ if (linechars)
+ JS_free(cx, linechars);
+ if (message)
+ JS_free(cx, message);
+ if (report.ucmessage)
+ JS_free(cx, (void *)report.ucmessage);
+
+ if (report.messageArgs) {
+ if (!(flags & JSREPORT_UC)) {
+ i = 0;
+ while (report.messageArgs[i])
+ JS_free(cx, (void *)report.messageArgs[i++]);
+ }
+ JS_free(cx, (void *)report.messageArgs);
+ }
+
+ if (!JSREPORT_IS_WARNING(flags)) {
+ /* Set the error flag to suppress spurious reports. */
+ ts->flags |= TSF_ERROR;
+ }
+
+ return warning;
+}
+
+static JSBool
+GrowStringBuffer(JSStringBuffer *sb, size_t newlength)
+{
+ ptrdiff_t offset;
+ jschar *bp;
+
+ offset = PTRDIFF(sb->ptr, sb->base, jschar);
+ JS_ASSERT(offset >= 0);
+ newlength += offset + 1;
+ if ((size_t)offset < newlength && newlength < ~(size_t)0 / sizeof(jschar))
+ bp = (jschar *) realloc(sb->base, newlength * sizeof(jschar));
+ else
+ bp = NULL;
+ if (!bp) {
+ free(sb->base);
+ sb->base = STRING_BUFFER_ERROR_BASE;
+ return JS_FALSE;
+ }
+ sb->base = bp;
+ sb->ptr = bp + offset;
+ sb->limit = bp + newlength - 1;
+ return JS_TRUE;
+}
+
+static void
+FreeStringBuffer(JSStringBuffer *sb)
+{
+ JS_ASSERT(STRING_BUFFER_OK(sb));
+ if (sb->base)
+ free(sb->base);
+}
+
+void
+js_InitStringBuffer(JSStringBuffer *sb)
+{
+ sb->base = sb->limit = sb->ptr = NULL;
+ sb->data = NULL;
+ sb->grow = GrowStringBuffer;
+ sb->free = FreeStringBuffer;
+}
+
+void
+js_FinishStringBuffer(JSStringBuffer *sb)
+{
+ sb->free(sb);
+}
+
+#define ENSURE_STRING_BUFFER(sb,n) \
+ ((sb)->ptr + (n) <= (sb)->limit || sb->grow(sb, n))
+
+static void
+FastAppendChar(JSStringBuffer *sb, jschar c)
+{
+ if (!STRING_BUFFER_OK(sb))
+ return;
+ if (!ENSURE_STRING_BUFFER(sb, 1))
+ return;
+ *sb->ptr++ = c;
+}
+
+void
+js_AppendChar(JSStringBuffer *sb, jschar c)
+{
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb))
+ return;
+ if (!ENSURE_STRING_BUFFER(sb, 1))
+ return;
+ bp = sb->ptr;
+ *bp++ = c;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+void
+js_AppendUCString(JSStringBuffer *sb, const jschar *buf, uintN len)
+{
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb))
+ return;
+ if (len == 0 || !ENSURE_STRING_BUFFER(sb, len))
+ return;
+ bp = sb->ptr;
+ js_strncpy(bp, buf, len);
+ bp += len;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+#if JS_HAS_XML_SUPPORT
+
+void
+js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count)
+{
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb) || count == 0)
+ return;
+ if (!ENSURE_STRING_BUFFER(sb, count))
+ return;
+ for (bp = sb->ptr; count; --count)
+ *bp++ = c;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+void
+js_AppendCString(JSStringBuffer *sb, const char *asciiz)
+{
+ size_t length;
+ jschar *bp;
+
+ if (!STRING_BUFFER_OK(sb) || *asciiz == '\0')
+ return;
+ length = strlen(asciiz);
+ if (!ENSURE_STRING_BUFFER(sb, length))
+ return;
+ for (bp = sb->ptr; length; --length)
+ *bp++ = (jschar) *asciiz++;
+ *bp = 0;
+ sb->ptr = bp;
+}
+
+void
+js_AppendJSString(JSStringBuffer *sb, JSString *str)
+{
+ js_AppendUCString(sb, JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+}
+
+static JSBool
+GetXMLEntity(JSContext *cx, JSTokenStream *ts)
+{
+ ptrdiff_t offset, length, i;
+ int32 c, d;
+ JSBool ispair;
+ jschar *bp, digit;
+ char *bytes;
+ JSErrNum msg;
+
+ /* Put the entity, including the '&' already scanned, in ts->tokenbuf. */
+ offset = PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar);
+ FastAppendChar(&ts->tokenbuf, '&');
+ if (!STRING_BUFFER_OK(&ts->tokenbuf))
+ return JS_FALSE;
+ while ((c = GetChar(ts)) != ';') {
+ if (c == EOF || c == '\n') {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_END_OF_XML_ENTITY);
+ return JS_FALSE;
+ }
+ FastAppendChar(&ts->tokenbuf, (jschar) c);
+ if (!STRING_BUFFER_OK(&ts->tokenbuf))
+ return JS_FALSE;
+ }
+
+ /* Let length be the number of jschars after the '&', including the ';'. */
+ length = PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar) - offset;
+ bp = ts->tokenbuf.base + offset;
+ c = d = 0;
+ ispair = JS_FALSE;
+ if (length > 2 && bp[1] == '#') {
+ /* Match a well-formed XML Character Reference. */
+ i = 2;
+ if (length > 3 && JS_TOLOWER(bp[i]) == 'x') {
+ if (length > 9) /* at most 6 hex digits allowed */
+ goto badncr;
+ while (++i < length) {
+ digit = bp[i];
+ if (!JS7_ISHEX(digit))
+ goto badncr;
+ c = (c << 4) + JS7_UNHEX(digit);
+ }
+ } else {
+ while (i < length) {
+ digit = bp[i++];
+ if (!JS7_ISDEC(digit))
+ goto badncr;
+ c = (c * 10) + JS7_UNDEC(digit);
+ if (c < 0)
+ goto badncr;
+ }
+ }
+
+ if (0x10000 <= c && c <= 0x10FFFF) {
+ /* Form a surrogate pair (c, d) -- c is the high surrogate. */
+ d = 0xDC00 + (c & 0x3FF);
+ c = 0xD7C0 + (c >> 10);
+ ispair = JS_TRUE;
+ } else {
+ /* Enforce the http://www.w3.org/TR/REC-xml/#wf-Legalchar WFC. */
+ if (c != 0x9 && c != 0xA && c != 0xD &&
+ !(0x20 <= c && c <= 0xD7FF) &&
+ !(0xE000 <= c && c <= 0xFFFD)) {
+ goto badncr;
+ }
+ }
+ } else {
+ /* Try to match one of the five XML 1.0 predefined entities. */
+ switch (length) {
+ case 3:
+ if (bp[2] == 't') {
+ if (bp[1] == 'l')
+ c = '<';
+ else if (bp[1] == 'g')
+ c = '>';
+ }
+ break;
+ case 4:
+ if (bp[1] == 'a' && bp[2] == 'm' && bp[3] == 'p')
+ c = '&';
+ break;
+ case 5:
+ if (bp[3] == 'o') {
+ if (bp[1] == 'a' && bp[2] == 'p' && bp[4] == 's')
+ c = '\'';
+ else if (bp[1] == 'q' && bp[2] == 'u' && bp[4] == 't')
+ c = '"';
+ }
+ break;
+ }
+ if (c == 0) {
+ msg = JSMSG_UNKNOWN_XML_ENTITY;
+ goto bad;
+ }
+ }
+
+ /* If we matched, retract ts->tokenbuf and store the entity's value. */
+ *bp++ = (jschar) c;
+ if (ispair)
+ *bp++ = (jschar) d;
+ *bp = 0;
+ ts->tokenbuf.ptr = bp;
+ return JS_TRUE;
+
+badncr:
+ msg = JSMSG_BAD_XML_NCR;
+bad:
+ /* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
+ JS_ASSERT(STRING_BUFFER_OK(&ts->tokenbuf));
+ JS_ASSERT(PTRDIFF(ts->tokenbuf.ptr, bp, jschar) >= 1);
+ bytes = js_DeflateString(cx, bp + 1,
+ PTRDIFF(ts->tokenbuf.ptr, bp, jschar) - 1);
+ if (bytes) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ msg, bytes);
+ JS_free(cx, bytes);
+ }
+ return JS_FALSE;
+}
+
+#endif /* JS_HAS_XML_SUPPORT */
+
+JSTokenType
+js_PeekToken(JSContext *cx, JSTokenStream *ts)
+{
+ JSTokenType tt;
+
+ if (ts->lookahead != 0) {
+ tt = ts->tokens[(ts->cursor + ts->lookahead) & NTOKENS_MASK].type;
+ } else {
+ tt = js_GetToken(cx, ts);
+ js_UngetToken(ts);
+ }
+ return tt;
+}
+
+JSTokenType
+js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts)
+{
+ JSTokenType tt;
+
+ if (!ON_CURRENT_LINE(ts, CURRENT_TOKEN(ts).pos))
+ return TOK_EOL;
+ ts->flags |= TSF_NEWLINES;
+ tt = js_PeekToken(cx, ts);
+ ts->flags &= ~TSF_NEWLINES;
+ return tt;
+}
+
+/*
+ * We have encountered a '\': check for a Unicode escape sequence after it,
+ * returning the character code value if we found a Unicode escape sequence.
+ * Otherwise, non-destructively return the original '\'.
+ */
+static int32
+GetUnicodeEscape(JSTokenStream *ts)
+{
+ jschar cp[5];
+ int32 c;
+
+ if (PeekChars(ts, 5, cp) && cp[0] == 'u' &&
+ JS7_ISHEX(cp[1]) && JS7_ISHEX(cp[2]) &&
+ JS7_ISHEX(cp[3]) && JS7_ISHEX(cp[4]))
+ {
+ c = (((((JS7_UNHEX(cp[1]) << 4)
+ + JS7_UNHEX(cp[2])) << 4)
+ + JS7_UNHEX(cp[3])) << 4)
+ + JS7_UNHEX(cp[4]);
+ SkipChars(ts, 5);
+ return c;
+ }
+ return '\\';
+}
+
+static JSToken *
+NewToken(JSTokenStream *ts, ptrdiff_t adjust)
+{
+ JSToken *tp;
+
+ ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;
+ tp = &CURRENT_TOKEN(ts);
+ tp->ptr = ts->linebuf.ptr + adjust;
+ tp->pos.begin.index = ts->linepos +
+ PTRDIFF(tp->ptr, ts->linebuf.base, jschar) -
+ ts->ungetpos;
+ tp->pos.begin.lineno = tp->pos.end.lineno = (uint16)ts->lineno;
+ return tp;
+}
+
+static JS_ALWAYS_INLINE JSBool
+ScanAsSpace(jschar c)
+{
+ /* Treat little- and big-endian BOMs as whitespace for compatibility. */
+ if (JS_ISSPACE(c) || c == 0xfffe || c == 0xfeff)
+ return JS_TRUE;
+ return JS_FALSE;
+}
+
+JSTokenType
+js_GetToken(JSContext *cx, JSTokenStream *ts)
+{
+ JSTokenType tt;
+ int32 c, qc;
+ JSToken *tp;
+ JSAtom *atom;
+ JSBool hadUnicodeEscape;
+ const struct keyword *kw;
+#if JS_HAS_XML_SUPPORT
+ JSBool inTarget;
+ size_t targetLength;
+ ptrdiff_t contentIndex;
+#endif
+
+#define INIT_TOKENBUF() (ts->tokenbuf.ptr = ts->tokenbuf.base)
+#define TOKENBUF_LENGTH() PTRDIFF(ts->tokenbuf.ptr, ts->tokenbuf.base, jschar)
+#define TOKENBUF_OK() STRING_BUFFER_OK(&ts->tokenbuf)
+#define TOKENBUF_TO_ATOM() (TOKENBUF_OK() \
+ ? js_AtomizeChars(cx, \
+ TOKENBUF_BASE(), \
+ TOKENBUF_LENGTH(), \
+ 0) \
+ : NULL)
+#define ADD_TO_TOKENBUF(c) FastAppendChar(&ts->tokenbuf, (jschar) (c))
+
+/* The following 4 macros should only be used when TOKENBUF_OK() is true. */
+#define TOKENBUF_BASE() (ts->tokenbuf.base)
+#define TOKENBUF_END() (ts->tokenbuf.ptr)
+#define TOKENBUF_CHAR(i) (ts->tokenbuf.base[i])
+#define TRIM_TOKENBUF(i) (ts->tokenbuf.ptr = ts->tokenbuf.base + i)
+#define NUL_TERM_TOKENBUF() (*ts->tokenbuf.ptr = 0)
+
+ /* Check for a pushed-back token resulting from mismatching lookahead. */
+ while (ts->lookahead != 0) {
+ JS_ASSERT(!(ts->flags & TSF_XMLTEXTMODE));
+ ts->lookahead--;
+ ts->cursor = (ts->cursor + 1) & NTOKENS_MASK;
+ tt = CURRENT_TOKEN(ts).type;
+ if (tt != TOK_EOL || (ts->flags & TSF_NEWLINES))
+ return tt;
+ }
+
+ /* If there was a fatal error, keep returning TOK_ERROR. */
+ if (ts->flags & TSF_ERROR)
+ return TOK_ERROR;
+
+#if JS_HAS_XML_SUPPORT
+ if (ts->flags & TSF_XMLTEXTMODE) {
+ tt = TOK_XMLSPACE; /* veto if non-space, return TOK_XMLTEXT */
+ tp = NewToken(ts, 0);
+ INIT_TOKENBUF();
+ qc = (ts->flags & TSF_XMLONLYMODE) ? '<' : '{';
+
+ while ((c = GetChar(ts)) != qc && c != '<' && c != EOF) {
+ if (c == '&' && qc == '<') {
+ if (!GetXMLEntity(cx, ts))
+ goto error;
+ tt = TOK_XMLTEXT;
+ continue;
+ }
+
+ if (!JS_ISXMLSPACE(c))
+ tt = TOK_XMLTEXT;
+ ADD_TO_TOKENBUF(c);
+ }
+ UngetChar(ts, c);
+
+ if (TOKENBUF_LENGTH() == 0) {
+ atom = NULL;
+ } else {
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ }
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ goto out;
+ }
+
+ if (ts->flags & TSF_XMLTAGMODE) {
+ tp = NewToken(ts, 0);
+ c = GetChar(ts);
+ if (JS_ISXMLSPACE(c)) {
+ do {
+ c = GetChar(ts);
+ } while (JS_ISXMLSPACE(c));
+ UngetChar(ts, c);
+ tt = TOK_XMLSPACE;
+ goto out;
+ }
+
+ if (c == EOF) {
+ tt = TOK_EOF;
+ goto out;
+ }
+
+ INIT_TOKENBUF();
+ if (JS_ISXMLNSSTART(c)) {
+ JSBool sawColon = JS_FALSE;
+
+ ADD_TO_TOKENBUF(c);
+ while ((c = GetChar(ts)) != EOF && JS_ISXMLNAME(c)) {
+ if (c == ':') {
+ int nextc;
+
+ if (sawColon ||
+ (nextc = PeekChar(ts),
+ ((ts->flags & TSF_XMLONLYMODE) || nextc != '{') &&
+ !JS_ISXMLNAME(nextc))) {
+ js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_ERROR,
+ JSMSG_BAD_XML_QNAME);
+ goto error;
+ }
+ sawColon = JS_TRUE;
+ }
+
+ ADD_TO_TOKENBUF(c);
+ }
+
+ UngetChar(ts, c);
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ tt = TOK_XMLNAME;
+ goto out;
+ }
+
+ switch (c) {
+ case '{':
+ if (ts->flags & TSF_XMLONLYMODE)
+ goto bad_xml_char;
+ tt = TOK_LC;
+ goto out;
+
+ case '=':
+ tt = TOK_ASSIGN;
+ goto out;
+
+ case '"':
+ case '\'':
+ qc = c;
+ while ((c = GetChar(ts)) != qc) {
+ if (c == EOF) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_STRING);
+ goto error;
+ }
+
+ /*
+ * XML attribute values are double-quoted when pretty-printed,
+ * so escape " if it is expressed directly in a single-quoted
+ * attribute value.
+ */
+ if (c == '"' && !(ts->flags & TSF_XMLONLYMODE)) {
+ JS_ASSERT(qc == '\'');
+ js_AppendCString(&ts->tokenbuf, js_quot_entity_str);
+ continue;
+ }
+
+ if (c == '&' && (ts->flags & TSF_XMLONLYMODE)) {
+ if (!GetXMLEntity(cx, ts))
+ goto error;
+ continue;
+ }
+
+ ADD_TO_TOKENBUF(c);
+ }
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ tt = TOK_XMLATTR;
+ goto out;
+
+ case '>':
+ tt = TOK_XMLTAGC;
+ goto out;
+
+ case '/':
+ if (MatchChar(ts, '>')) {
+ tt = TOK_XMLPTAGC;
+ goto out;
+ }
+ /* FALL THROUGH */
+
+ bad_xml_char:
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_CHARACTER);
+ goto error;
+ }
+ /* NOTREACHED */
+ }
+#endif /* JS_HAS_XML_SUPPORT */
+
+retry:
+ do {
+ c = GetChar(ts);
+ if (c == '\n') {
+ ts->flags &= ~TSF_DIRTYLINE;
+ if (ts->flags & TSF_NEWLINES)
+ break;
+ }
+ } while (ScanAsSpace((jschar)c));
+
+ tp = NewToken(ts, -1);
+ if (c == EOF) {
+ tt = TOK_EOF;
+ goto out;
+ }
+
+ hadUnicodeEscape = JS_FALSE;
+ if (JS_ISIDSTART(c) ||
+ (c == '\\' &&
+ (qc = GetUnicodeEscape(ts),
+ hadUnicodeEscape = JS_ISIDSTART(qc)))) {
+ if (hadUnicodeEscape)
+ c = qc;
+ INIT_TOKENBUF();
+ for (;;) {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ if (c == '\\') {
+ qc = GetUnicodeEscape(ts);
+ if (!JS_ISIDENT(qc))
+ break;
+ c = qc;
+ hadUnicodeEscape = JS_TRUE;
+ } else {
+ if (!JS_ISIDENT(c))
+ break;
+ }
+ }
+ UngetChar(ts, c);
+
+ /*
+ * Check for keywords unless we saw Unicode escape or parser asks
+ * to ignore keywords.
+ */
+ if (!hadUnicodeEscape &&
+ !(ts->flags & TSF_KEYWORD_IS_NAME) &&
+ TOKENBUF_OK() &&
+ (kw = FindKeyword(TOKENBUF_BASE(), TOKENBUF_LENGTH()))) {
+ if (kw->tokentype == TOK_RESERVED) {
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_RESERVED_ID,
+ kw->chars)) {
+ goto error;
+ }
+ } else if (kw->version <= JSVERSION_NUMBER(cx)) {
+ tt = kw->tokentype;
+ tp->t_op = (JSOp) kw->op;
+ goto out;
+ }
+ }
+
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->t_op = JSOP_NAME;
+ tp->t_atom = atom;
+ tt = TOK_NAME;
+ goto out;
+ }
+
+ if (JS7_ISDEC(c) || (c == '.' && JS7_ISDEC(PeekChar(ts)))) {
+ jsint radix;
+ const jschar *endptr;
+ jsdouble dval;
+
+ radix = 10;
+ INIT_TOKENBUF();
+
+ if (c == '0') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ if (JS_TOLOWER(c) == 'x') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ radix = 16;
+ } else if (JS7_ISDEC(c)) {
+ radix = 8;
+ }
+ }
+
+ while (JS7_ISHEX(c)) {
+ if (radix < 16) {
+ if (JS7_ISLET(c))
+ break;
+
+ /*
+ * We permit 08 and 09 as decimal numbers, which makes our
+ * behaviour a superset of the ECMA numeric grammar. We might
+ * not always be so permissive, so we warn about it.
+ */
+ if (radix == 8 && c >= '8') {
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING,
+ JSMSG_BAD_OCTAL,
+ c == '8' ? "08" : "09")) {
+ goto error;
+ }
+ radix = 10;
+ }
+ }
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ }
+
+ if (radix == 10 && (c == '.' || JS_TOLOWER(c) == 'e')) {
+ if (c == '.') {
+ do {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ } while (JS7_ISDEC(c));
+ }
+ if (JS_TOLOWER(c) == 'e') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ if (c == '+' || c == '-') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ }
+ if (!JS7_ISDEC(c)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_MISSING_EXPONENT);
+ goto error;
+ }
+ do {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ } while (JS7_ISDEC(c));
+ }
+ }
+
+ /* Put back the next char and NUL-terminate tokenbuf for js_strto*. */
+ UngetChar(ts, c);
+ ADD_TO_TOKENBUF(0);
+
+ if (!TOKENBUF_OK())
+ goto error;
+ if (radix == 10) {
+ if (!js_strtod(cx, TOKENBUF_BASE(), TOKENBUF_END(),
+ &endptr, &dval)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_OUT_OF_MEMORY);
+ goto error;
+ }
+ } else {
+ if (!js_strtointeger(cx, TOKENBUF_BASE(), TOKENBUF_END(),
+ &endptr, radix, &dval)) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_OUT_OF_MEMORY);
+ goto error;
+ }
+ }
+ tp->t_dval = dval;
+ tt = TOK_NUMBER;
+ goto out;
+ }
+
+ if (c == '"' || c == '\'') {
+ qc = c;
+ INIT_TOKENBUF();
+ while ((c = GetChar(ts)) != qc) {
+ if (c == '\n' || c == EOF) {
+ UngetChar(ts, c);
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_STRING);
+ goto error;
+ }
+ if (c == '\\') {
+ switch (c = GetChar(ts)) {
+ case 'b': c = '\b'; break;
+ case 'f': c = '\f'; break;
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ case 'v': c = '\v'; break;
+
+ default:
+ if ('0' <= c && c < '8') {
+ int32 val = JS7_UNDEC(c);
+
+ c = PeekChar(ts);
+ if ('0' <= c && c < '8') {
+ val = 8 * val + JS7_UNDEC(c);
+ GetChar(ts);
+ c = PeekChar(ts);
+ if ('0' <= c && c < '8') {
+ int32 save = val;
+ val = 8 * val + JS7_UNDEC(c);
+ if (val <= 0377)
+ GetChar(ts);
+ else
+ val = save;
+ }
+ }
+
+ c = (jschar)val;
+ } else if (c == 'u') {
+ jschar cp[4];
+ if (PeekChars(ts, 4, cp) &&
+ JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1]) &&
+ JS7_ISHEX(cp[2]) && JS7_ISHEX(cp[3])) {
+ c = (((((JS7_UNHEX(cp[0]) << 4)
+ + JS7_UNHEX(cp[1])) << 4)
+ + JS7_UNHEX(cp[2])) << 4)
+ + JS7_UNHEX(cp[3]);
+ SkipChars(ts, 4);
+ }
+ } else if (c == 'x') {
+ jschar cp[2];
+ if (PeekChars(ts, 2, cp) &&
+ JS7_ISHEX(cp[0]) && JS7_ISHEX(cp[1])) {
+ c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
+ SkipChars(ts, 2);
+ }
+ } else if (c == '\n') {
+ /* ECMA follows C by removing escaped newlines. */
+ continue;
+ }
+ break;
+ }
+ }
+ ADD_TO_TOKENBUF(c);
+ }
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ tp->t_op = JSOP_STRING;
+ tp->t_atom = atom;
+ tt = TOK_STRING;
+ goto out;
+ }
+
+ switch (c) {
+ case '\n': tt = TOK_EOL; goto eol_out;
+ case ';': tt = TOK_SEMI; break;
+ case '[': tt = TOK_LB; break;
+ case ']': tt = TOK_RB; break;
+ case '{': tt = TOK_LC; break;
+ case '}': tt = TOK_RC; break;
+ case '(': tt = TOK_LP; break;
+ case ')': tt = TOK_RP; break;
+ case ',': tt = TOK_COMMA; break;
+ case '?': tt = TOK_HOOK; break;
+
+ case '.':
+#if JS_HAS_XML_SUPPORT
+ if (MatchChar(ts, c))
+ tt = TOK_DBLDOT;
+ else
+#endif
+ tt = TOK_DOT;
+ break;
+
+ case ':':
+#if JS_HAS_XML_SUPPORT
+ if (MatchChar(ts, c)) {
+ tt = TOK_DBLCOLON;
+ break;
+ }
+#endif
+ /*
+ * Default so compiler can modify to JSOP_GETTER if 'p getter: v' in an
+ * object initializer, likewise for setter.
+ */
+ tp->t_op = JSOP_NOP;
+ tt = TOK_COLON;
+ break;
+
+ case '|':
+ if (MatchChar(ts, c)) {
+ tt = TOK_OR;
+ } else if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_BITOR;
+ tt = TOK_ASSIGN;
+ } else {
+ tt = TOK_BITOR;
+ }
+ break;
+
+ case '^':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_BITXOR;
+ tt = TOK_ASSIGN;
+ } else {
+ tt = TOK_BITXOR;
+ }
+ break;
+
+ case '&':
+ if (MatchChar(ts, c)) {
+ tt = TOK_AND;
+ } else if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_BITAND;
+ tt = TOK_ASSIGN;
+ } else {
+ tt = TOK_BITAND;
+ }
+ break;
+
+ case '=':
+ if (MatchChar(ts, c)) {
+ tp->t_op = MatchChar(ts, c) ? JSOP_STRICTEQ : JSOP_EQ;
+ tt = TOK_EQOP;
+ } else {
+ tp->t_op = JSOP_NOP;
+ tt = TOK_ASSIGN;
+ }
+ break;
+
+ case '!':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = MatchChar(ts, '=') ? JSOP_STRICTNE : JSOP_NE;
+ tt = TOK_EQOP;
+ } else {
+ tp->t_op = JSOP_NOT;
+ tt = TOK_UNARYOP;
+ }
+ break;
+
+#if JS_HAS_XML_SUPPORT
+ case '@':
+ tt = TOK_AT;
+ break;
+#endif
+
+ case '<':
+#if JS_HAS_XML_SUPPORT
+ /*
+ * After much testing, it's clear that Postel's advice to protocol
+ * designers ("be liberal in what you accept, and conservative in what
+ * you send") invites a natural-law repercussion for JS as "protocol":
+ *
+ * "If you are liberal in what you accept, others will utterly fail to
+ * be conservative in what they send."
+ *
+ * Which means you will get <!-- comments to end of line in the middle
+ * of .js files, and after if conditions whose then statements are on
+ * the next line, and other wonders. See at least the following bugs:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=309242
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=309712
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=310993
+ *
+ * So without JSOPTION_XML, we never scan an XML comment or CDATA
+ * literal. We always scan <! as the start of an HTML comment hack
+ * to end of line, used since Netscape 2 to hide script tag content
+ * from script-unaware browsers.
+ */
+ if ((ts->flags & TSF_OPERAND) &&
+ (JS_HAS_XML_OPTION(cx) || PeekChar(ts) != '!')) {
+ /* Check for XML comment or CDATA section. */
+ if (MatchChar(ts, '!')) {
+ INIT_TOKENBUF();
+
+ /* Scan XML comment. */
+ if (MatchChar(ts, '-')) {
+ if (!MatchChar(ts, '-'))
+ goto bad_xml_markup;
+ while ((c = GetChar(ts)) != '-' || !MatchChar(ts, '-')) {
+ if (c == EOF)
+ goto bad_xml_markup;
+ ADD_TO_TOKENBUF(c);
+ }
+ tt = TOK_XMLCOMMENT;
+ tp->t_op = JSOP_XMLCOMMENT;
+ goto finish_xml_markup;
+ }
+
+ /* Scan CDATA section. */
+ if (MatchChar(ts, '[')) {
+ jschar cp[6];
+ if (PeekChars(ts, 6, cp) &&
+ cp[0] == 'C' &&
+ cp[1] == 'D' &&
+ cp[2] == 'A' &&
+ cp[3] == 'T' &&
+ cp[4] == 'A' &&
+ cp[5] == '[') {
+ SkipChars(ts, 6);
+ while ((c = GetChar(ts)) != ']' ||
+ !PeekChars(ts, 2, cp) ||
+ cp[0] != ']' ||
+ cp[1] != '>') {
+ if (c == EOF)
+ goto bad_xml_markup;
+ ADD_TO_TOKENBUF(c);
+ }
+ GetChar(ts); /* discard ] but not > */
+ tt = TOK_XMLCDATA;
+ tp->t_op = JSOP_XMLCDATA;
+ goto finish_xml_markup;
+ }
+ goto bad_xml_markup;
+ }
+ }
+
+ /* Check for processing instruction. */
+ if (MatchChar(ts, '?')) {
+ inTarget = JS_TRUE;
+ targetLength = 0;
+ contentIndex = -1;
+
+ INIT_TOKENBUF();
+ while ((c = GetChar(ts)) != '?' || PeekChar(ts) != '>') {
+ if (c == EOF)
+ goto bad_xml_markup;
+ if (inTarget) {
+ if (JS_ISXMLSPACE(c)) {
+ if (TOKENBUF_LENGTH() == 0)
+ goto bad_xml_markup;
+ inTarget = JS_FALSE;
+ } else {
+ if (!((TOKENBUF_LENGTH() == 0)
+ ? JS_ISXMLNSSTART(c)
+ : JS_ISXMLNS(c))) {
+ goto bad_xml_markup;
+ }
+ ++targetLength;
+ }
+ } else {
+ if (contentIndex < 0 && !JS_ISXMLSPACE(c))
+ contentIndex = TOKENBUF_LENGTH();
+ }
+ ADD_TO_TOKENBUF(c);
+ }
+ if (targetLength == 0)
+ goto bad_xml_markup;
+ if (!TOKENBUF_OK())
+ goto error;
+ if (contentIndex < 0) {
+ atom = cx->runtime->atomState.emptyAtom;
+ } else {
+ atom = js_AtomizeChars(cx,
+ &TOKENBUF_CHAR(contentIndex),
+ TOKENBUF_LENGTH() - contentIndex,
+ 0);
+ if (!atom)
+ goto error;
+ }
+ TRIM_TOKENBUF(targetLength);
+ tp->t_atom2 = atom;
+ tt = TOK_XMLPI;
+
+ finish_xml_markup:
+ if (!MatchChar(ts, '>'))
+ goto bad_xml_markup;
+ atom = TOKENBUF_TO_ATOM();
+ if (!atom)
+ goto error;
+ tp->t_atom = atom;
+ tp->pos.end.lineno = (uint16)ts->lineno;
+ goto out;
+ }
+
+ /* An XML start-of-tag character. */
+ tt = MatchChar(ts, '/') ? TOK_XMLETAGO : TOK_XMLSTAGO;
+ goto out;
+
+ bad_xml_markup:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_XML_MARKUP);
+ goto error;
+ }
+#endif /* JS_HAS_XML_SUPPORT */
+
+ /* NB: treat HTML begin-comment as comment-till-end-of-line */
+ if (MatchChar(ts, '!')) {
+ if (MatchChar(ts, '-')) {
+ if (MatchChar(ts, '-')) {
+ ts->flags |= TSF_IN_HTML_COMMENT;
+ goto skipline;
+ }
+ UngetChar(ts, '-');
+ }
+ UngetChar(ts, '!');
+ }
+ if (MatchChar(ts, c)) {
+ tp->t_op = JSOP_LSH;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;
+ } else {
+ tp->t_op = MatchChar(ts, '=') ? JSOP_LE : JSOP_LT;
+ tt = TOK_RELOP;
+ }
+ break;
+
+ case '>':
+ if (MatchChar(ts, c)) {
+ tp->t_op = MatchChar(ts, c) ? JSOP_URSH : JSOP_RSH;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_SHOP;
+ } else {
+ tp->t_op = MatchChar(ts, '=') ? JSOP_GE : JSOP_GT;
+ tt = TOK_RELOP;
+ }
+ break;
+
+ case '*':
+ tp->t_op = JSOP_MUL;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_STAR;
+ break;
+
+ case '/':
+ if (MatchChar(ts, '/')) {
+ /*
+ * Hack for source filters such as the Mozilla XUL preprocessor:
+ * "//@line 123\n" sets the number of the *next* line after the
+ * comment to 123.
+ */
+ if (JS_HAS_ATLINE_OPTION(cx)) {
+ jschar cp[5];
+ uintN i, line, temp;
+ char filename[1024];
+
+ if (PeekChars(ts, 5, cp) &&
+ cp[0] == '@' &&
+ cp[1] == 'l' &&
+ cp[2] == 'i' &&
+ cp[3] == 'n' &&
+ cp[4] == 'e') {
+ SkipChars(ts, 5);
+ while ((c = GetChar(ts)) != '\n' && ScanAsSpace((jschar)c))
+ continue;
+ if (JS7_ISDEC(c)) {
+ line = JS7_UNDEC(c);
+ while ((c = GetChar(ts)) != EOF && JS7_ISDEC(c)) {
+ temp = 10 * line + JS7_UNDEC(c);
+ if (temp < line) {
+ /* Ignore overlarge line numbers. */
+ goto skipline;
+ }
+ line = temp;
+ }
+ while (c != '\n' && ScanAsSpace((jschar)c))
+ c = GetChar(ts);
+ i = 0;
+ if (c == '"') {
+ while ((c = GetChar(ts)) != EOF && c != '"') {
+ if (c == '\n') {
+ UngetChar(ts, c);
+ goto skipline;
+ }
+ if ((c >> 8) != 0 || i >= sizeof filename - 1)
+ goto skipline;
+ filename[i++] = (char) c;
+ }
+ if (c == '"') {
+ while ((c = GetChar(ts)) != '\n' &&
+ ScanAsSpace((jschar)c)) {
+ continue;
+ }
+ }
+ }
+ filename[i] = '\0';
+ if (c == '\n') {
+ if (i > 0) {
+ if (ts->flags & TSF_OWNFILENAME)
+ JS_free(cx, (void *) ts->filename);
+ ts->filename = JS_strdup(cx, filename);
+ if (!ts->filename)
+ goto error;
+ ts->flags |= TSF_OWNFILENAME;
+ }
+ ts->lineno = line;
+ }
+ }
+ UngetChar(ts, c);
+ }
+ }
+
+skipline:
+ /* Optimize line skipping if we are not in an HTML comment. */
+ if (ts->flags & TSF_IN_HTML_COMMENT) {
+ while ((c = GetChar(ts)) != EOF && c != '\n') {
+ if (c == '-' && MatchChar(ts, '-') && MatchChar(ts, '>'))
+ ts->flags &= ~TSF_IN_HTML_COMMENT;
+ }
+ } else {
+ while ((c = GetChar(ts)) != EOF && c != '\n')
+ continue;
+ }
+ UngetChar(ts, c);
+ ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
+ goto retry;
+ }
+
+ if (MatchChar(ts, '*')) {
+ while ((c = GetChar(ts)) != EOF &&
+ !(c == '*' && MatchChar(ts, '/'))) {
+ /* Ignore all characters until comment close. */
+ }
+ if (c == EOF) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_COMMENT);
+ goto error;
+ }
+ ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
+ goto retry;
+ }
+
+ if (ts->flags & TSF_OPERAND) {
+ uintN flags;
+ JSBool inCharClass = JS_FALSE;
+
+ INIT_TOKENBUF();
+ for (;;) {
+ c = GetChar(ts);
+ if (c == '\n' || c == EOF) {
+ UngetChar(ts, c);
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_UNTERMINATED_REGEXP);
+ goto error;
+ }
+ if (c == '\\') {
+ ADD_TO_TOKENBUF(c);
+ c = GetChar(ts);
+ } else if (c == '[') {
+ inCharClass = JS_TRUE;
+ } else if (c == ']') {
+ inCharClass = JS_FALSE;
+ } else if (c == '/' && !inCharClass) {
+ /* For compat with IE, allow unescaped / in char classes. */
+ break;
+ }
+ ADD_TO_TOKENBUF(c);
+ }
+ for (flags = 0; ; ) {
+ c = PeekChar(ts);
+ if (c == 'g')
+ flags |= JSREG_GLOB;
+ else if (c == 'i')
+ flags |= JSREG_FOLD;
+ else if (c == 'm')
+ flags |= JSREG_MULTILINE;
+ else if (c == 'y')
+ flags |= JSREG_STICKY;
+ else
+ break;
+ GetChar(ts);
+ }
+ c = PeekChar(ts);
+ if (JS7_ISLET(c)) {
+ tp->ptr = ts->linebuf.ptr - 1;
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_BAD_REGEXP_FLAG);
+ (void) GetChar(ts);
+ goto error;
+ }
+ /* XXXbe fix jsregexp.c so it doesn't depend on NUL termination */
+ if (!TOKENBUF_OK())
+ goto error;
+ NUL_TERM_TOKENBUF();
+ tp->t_reflags = flags;
+ tt = TOK_REGEXP;
+ break;
+ }
+
+ tp->t_op = JSOP_DIV;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;
+ break;
+
+ case '%':
+ tp->t_op = JSOP_MOD;
+ tt = MatchChar(ts, '=') ? TOK_ASSIGN : TOK_DIVOP;
+ break;
+
+ case '~':
+ tp->t_op = JSOP_BITNOT;
+ tt = TOK_UNARYOP;
+ break;
+
+ case '+':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_ADD;
+ tt = TOK_ASSIGN;
+ } else if (MatchChar(ts, c)) {
+ tt = TOK_INC;
+ } else {
+ tp->t_op = JSOP_POS;
+ tt = TOK_PLUS;
+ }
+ break;
+
+ case '-':
+ if (MatchChar(ts, '=')) {
+ tp->t_op = JSOP_SUB;
+ tt = TOK_ASSIGN;
+ } else if (MatchChar(ts, c)) {
+ if (PeekChar(ts) == '>' && !(ts->flags & TSF_DIRTYLINE)) {
+ ts->flags &= ~TSF_IN_HTML_COMMENT;
+ goto skipline;
+ }
+ tt = TOK_DEC;
+ } else {
+ tp->t_op = JSOP_NEG;
+ tt = TOK_MINUS;
+ }
+ break;
+
+#if JS_HAS_SHARP_VARS
+ case '#':
+ {
+ uint32 n;
+
+ c = GetChar(ts);
+ if (!JS7_ISDEC(c)) {
+ UngetChar(ts, c);
+ goto badchar;
+ }
+ n = (uint32)JS7_UNDEC(c);
+ for (;;) {
+ c = GetChar(ts);
+ if (!JS7_ISDEC(c))
+ break;
+ n = 10 * n + JS7_UNDEC(c);
+ if (n >= UINT16_LIMIT) {
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_SHARPVAR_TOO_BIG);
+ goto error;
+ }
+ }
+ tp->t_dval = (jsdouble) n;
+ if (JS_HAS_STRICT_OPTION(cx) &&
+ (c == '=' || c == '#')) {
+ char buf[20];
+ JS_snprintf(buf, sizeof buf, "#%u%c", n, c);
+ if (!js_ReportCompileErrorNumber(cx, ts, NULL,
+ JSREPORT_WARNING |
+ JSREPORT_STRICT,
+ JSMSG_DEPRECATED_USAGE,
+ buf)) {
+ goto error;
+ }
+ }
+ if (c == '=')
+ tt = TOK_DEFSHARP;
+ else if (c == '#')
+ tt = TOK_USESHARP;
+ else
+ goto badchar;
+ break;
+ }
+#endif /* JS_HAS_SHARP_VARS */
+
+#if JS_HAS_SHARP_VARS || JS_HAS_XML_SUPPORT
+ badchar:
+#endif
+
+ default:
+ js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
+ JSMSG_ILLEGAL_CHARACTER);
+ goto error;
+ }
+
+out:
+ JS_ASSERT(tt != TOK_EOL);
+ ts->flags |= TSF_DIRTYLINE;
+
+eol_out:
+ if (!STRING_BUFFER_OK(&ts->tokenbuf))
+ tt = TOK_ERROR;
+ JS_ASSERT(tt < TOK_LIMIT);
+ tp->pos.end.index = ts->linepos +
+ PTRDIFF(ts->linebuf.ptr, ts->linebuf.base, jschar) -
+ ts->ungetpos;
+ tp->type = tt;
+ return tt;
+
+error:
+ tt = TOK_ERROR;
+ ts->flags |= TSF_ERROR;
+ goto out;
+
+#undef INIT_TOKENBUF
+#undef TOKENBUF_LENGTH
+#undef TOKENBUF_OK
+#undef TOKENBUF_TO_ATOM
+#undef ADD_TO_TOKENBUF
+#undef TOKENBUF_BASE
+#undef TOKENBUF_CHAR
+#undef TRIM_TOKENBUF
+#undef NUL_TERM_TOKENBUF
+}
+
+void
+js_UngetToken(JSTokenStream *ts)
+{
+ JS_ASSERT(ts->lookahead < NTOKENS_MASK);
+ ts->lookahead++;
+ ts->cursor = (ts->cursor - 1) & NTOKENS_MASK;
+}
+
+JSBool
+js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt)
+{
+ if (js_GetToken(cx, ts) == tt)
+ return JS_TRUE;
+ js_UngetToken(ts);
+ return JS_FALSE;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscan.h b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.h
new file mode 100644
index 0000000..259aa8a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscan.h
@@ -0,0 +1,389 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsscan_h___
+#define jsscan_h___
+/*
+ * JS lexical scanner interface.
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include "jsversion.h"
+#include "jsopcode.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+#define JS_KEYWORD(keyword, type, op, version) \
+ extern const char js_##keyword##_str[];
+#include "jskeyword.tbl"
+#undef JS_KEYWORD
+
+typedef enum JSTokenType {
+ TOK_ERROR = -1, /* well-known as the only code < EOF */
+ TOK_EOF = 0, /* end of file */
+ TOK_EOL = 1, /* end of line */
+ TOK_SEMI = 2, /* semicolon */
+ TOK_COMMA = 3, /* comma operator */
+ TOK_ASSIGN = 4, /* assignment ops (= += -= etc.) */
+ TOK_HOOK = 5, TOK_COLON = 6, /* conditional (?:) */
+ TOK_OR = 7, /* logical or (||) */
+ TOK_AND = 8, /* logical and (&&) */
+ TOK_BITOR = 9, /* bitwise-or (|) */
+ TOK_BITXOR = 10, /* bitwise-xor (^) */
+ TOK_BITAND = 11, /* bitwise-and (&) */
+ TOK_EQOP = 12, /* equality ops (== !=) */
+ TOK_RELOP = 13, /* relational ops (< <= > >=) */
+ TOK_SHOP = 14, /* shift ops (<< >> >>>) */
+ TOK_PLUS = 15, /* plus */
+ TOK_MINUS = 16, /* minus */
+ TOK_STAR = 17, TOK_DIVOP = 18, /* multiply/divide ops (* / %) */
+ TOK_UNARYOP = 19, /* unary prefix operator */
+ TOK_INC = 20, TOK_DEC = 21, /* increment/decrement (++ --) */
+ TOK_DOT = 22, /* member operator (.) */
+ TOK_LB = 23, TOK_RB = 24, /* left and right brackets */
+ TOK_LC = 25, TOK_RC = 26, /* left and right curlies (braces) */
+ TOK_LP = 27, TOK_RP = 28, /* left and right parentheses */
+ TOK_NAME = 29, /* identifier */
+ TOK_NUMBER = 30, /* numeric constant */
+ TOK_STRING = 31, /* string constant */
+ TOK_REGEXP = 32, /* RegExp constant */
+ TOK_PRIMARY = 33, /* true, false, null, this, super */
+ TOK_FUNCTION = 34, /* function keyword */
+ TOK_IF = 35, /* if keyword */
+ TOK_ELSE = 36, /* else keyword */
+ TOK_SWITCH = 37, /* switch keyword */
+ TOK_CASE = 38, /* case keyword */
+ TOK_DEFAULT = 39, /* default keyword */
+ TOK_WHILE = 40, /* while keyword */
+ TOK_DO = 41, /* do keyword */
+ TOK_FOR = 42, /* for keyword */
+ TOK_BREAK = 43, /* break keyword */
+ TOK_CONTINUE = 44, /* continue keyword */
+ TOK_IN = 45, /* in keyword */
+ TOK_VAR = 46, /* var keyword */
+ TOK_WITH = 47, /* with keyword */
+ TOK_RETURN = 48, /* return keyword */
+ TOK_NEW = 49, /* new keyword */
+ TOK_DELETE = 50, /* delete keyword */
+ TOK_DEFSHARP = 51, /* #n= for object/array initializers */
+ TOK_USESHARP = 52, /* #n# for object/array initializers */
+ TOK_TRY = 53, /* try keyword */
+ TOK_CATCH = 54, /* catch keyword */
+ TOK_FINALLY = 55, /* finally keyword */
+ TOK_THROW = 56, /* throw keyword */
+ TOK_INSTANCEOF = 57, /* instanceof keyword */
+ TOK_DEBUGGER = 58, /* debugger keyword */
+ TOK_XMLSTAGO = 59, /* XML start tag open (<) */
+ TOK_XMLETAGO = 60, /* XML end tag open (</) */
+ TOK_XMLPTAGC = 61, /* XML point tag close (/>) */
+ TOK_XMLTAGC = 62, /* XML start or end tag close (>) */
+ TOK_XMLNAME = 63, /* XML start-tag non-final fragment */
+ TOK_XMLATTR = 64, /* XML quoted attribute value */
+ TOK_XMLSPACE = 65, /* XML whitespace */
+ TOK_XMLTEXT = 66, /* XML text */
+ TOK_XMLCOMMENT = 67, /* XML comment */
+ TOK_XMLCDATA = 68, /* XML CDATA section */
+ TOK_XMLPI = 69, /* XML processing instruction */
+ TOK_AT = 70, /* XML attribute op (@) */
+ TOK_DBLCOLON = 71, /* namespace qualified name op (::) */
+ TOK_ANYNAME = 72, /* XML AnyName singleton (*) */
+ TOK_DBLDOT = 73, /* XML descendant op (..) */
+ TOK_FILTER = 74, /* XML filtering predicate op (.()) */
+ TOK_XMLELEM = 75, /* XML element node type (no token) */
+ TOK_XMLLIST = 76, /* XML list node type (no token) */
+ TOK_YIELD = 77, /* yield from generator function */
+ TOK_ARRAYCOMP = 78, /* array comprehension initialiser */
+ TOK_ARRAYPUSH = 79, /* array push within comprehension */
+ TOK_LEXICALSCOPE = 80, /* block scope AST node label */
+ TOK_LET = 81, /* let keyword */
+ TOK_SEQ = 82, /* synthetic sequence of statements,
+ not a block */
+ TOK_FORHEAD = 83, /* head of for(;;)-style loop */
+ TOK_RESERVED, /* reserved keywords */
+ TOK_LIMIT /* domain size */
+} JSTokenType;
+
+#define IS_PRIMARY_TOKEN(tt) \
+ ((uintN)((tt) - TOK_NAME) <= (uintN)(TOK_PRIMARY - TOK_NAME))
+
+#define TOKEN_TYPE_IS_XML(tt) \
+ (tt == TOK_AT || tt == TOK_DBLCOLON || tt == TOK_ANYNAME)
+
+#if JS_HAS_BLOCK_SCOPE
+# define TOKEN_TYPE_IS_DECL(tt) ((tt) == TOK_VAR || (tt) == TOK_LET)
+#else
+# define TOKEN_TYPE_IS_DECL(tt) ((tt) == TOK_VAR)
+#endif
+
+struct JSStringBuffer {
+ jschar *base;
+ jschar *limit; /* length limit for quick bounds check */
+ jschar *ptr; /* slot for next non-NUL char to store */
+ void *data;
+ JSBool (*grow)(JSStringBuffer *sb, size_t newlength);
+ void (*free)(JSStringBuffer *sb);
+};
+
+#define STRING_BUFFER_ERROR_BASE ((jschar *) 1)
+#define STRING_BUFFER_OK(sb) ((sb)->base != STRING_BUFFER_ERROR_BASE)
+#define STRING_BUFFER_OFFSET(sb) ((sb)->ptr -(sb)->base)
+
+extern void
+js_InitStringBuffer(JSStringBuffer *sb);
+
+extern void
+js_FinishStringBuffer(JSStringBuffer *sb);
+
+extern void
+js_AppendChar(JSStringBuffer *sb, jschar c);
+
+extern void
+js_RepeatChar(JSStringBuffer *sb, jschar c, uintN count);
+
+extern void
+js_AppendCString(JSStringBuffer *sb, const char *asciiz);
+
+extern void
+js_AppendUCString(JSStringBuffer *sb, const jschar *buf, uintN len);
+
+extern void
+js_AppendJSString(JSStringBuffer *sb, JSString *str);
+
+struct JSTokenPtr {
+ uint16 index; /* index of char in physical line */
+ uint16 lineno; /* physical line number */
+};
+
+struct JSTokenPos {
+ JSTokenPtr begin; /* first character and line of token */
+ JSTokenPtr end; /* index 1 past last char, last line */
+};
+
+struct JSToken {
+ JSTokenType type; /* char value or above enumerator */
+ JSTokenPos pos; /* token position in file */
+ jschar *ptr; /* beginning of token in line buffer */
+ union {
+ struct { /* name or string literal */
+ JSOp op; /* operator, for minimal parser */
+ JSAtom *atom; /* atom table entry */
+ } s;
+ uintN reflags; /* regexp flags, use tokenbuf to access
+ regexp chars */
+ struct { /* atom pair, for XML PIs */
+ JSAtom *atom2; /* auxiliary atom table entry */
+ JSAtom *atom; /* main atom table entry */
+ } p;
+ jsdouble dval; /* floating point number */
+ } u;
+};
+
+#define t_op u.s.op
+#define t_reflags u.reflags
+#define t_atom u.s.atom
+#define t_atom2 u.p.atom2
+#define t_dval u.dval
+
+typedef struct JSTokenBuf {
+ jschar *base; /* base of line or stream buffer */
+ jschar *limit; /* limit for quick bounds check */
+ jschar *ptr; /* next char to get, or slot to use */
+} JSTokenBuf;
+
+#define JS_LINE_LIMIT 256 /* logical line buffer size limit --
+ physical line length is unlimited */
+#define NTOKENS 4 /* 1 current + 2 lookahead, rounded */
+#define NTOKENS_MASK (NTOKENS-1) /* to power of 2 to avoid divmod by 3 */
+
+struct JSTokenStream {
+ JSToken tokens[NTOKENS];/* circular token buffer */
+ uintN cursor; /* index of last parsed token */
+ uintN lookahead; /* count of lookahead tokens */
+ uintN lineno; /* current line number */
+ uintN ungetpos; /* next free char slot in ungetbuf */
+ jschar ungetbuf[6]; /* at most 6, for \uXXXX lookahead */
+ uintN flags; /* flags -- see below */
+ ptrdiff_t linelen; /* physical linebuf segment length */
+ ptrdiff_t linepos; /* linebuf offset in physical line */
+ JSTokenBuf linebuf; /* line buffer for diagnostics */
+ JSTokenBuf userbuf; /* user input buffer if !file */
+ JSStringBuffer tokenbuf; /* current token string buffer */
+ const char *filename; /* input filename or null */
+ FILE *file; /* stdio stream if reading from file */
+ JSSourceHandler listener; /* callback for source; eg debugger */
+ void *listenerData; /* listener 'this' data */
+ void *listenerTSData;/* listener data for this TokenStream */
+ jschar *saveEOL; /* save next end of line in userbuf, to
+ optimize for very long lines */
+};
+
+#define CURRENT_TOKEN(ts) ((ts)->tokens[(ts)->cursor])
+#define ON_CURRENT_LINE(ts,pos) ((uint16)(ts)->lineno == (pos).end.lineno)
+
+/* JSTokenStream flags */
+#define TSF_ERROR 0x01 /* fatal error while compiling */
+#define TSF_EOF 0x02 /* hit end of file */
+#define TSF_NEWLINES 0x04 /* tokenize newlines */
+#define TSF_OPERAND 0x08 /* looking for operand, not operator */
+#define TSF_NLFLAG 0x20 /* last linebuf ended with \n */
+#define TSF_CRFLAG 0x40 /* linebuf would have ended with \r */
+#define TSF_DIRTYLINE 0x80 /* non-whitespace since start of line */
+#define TSF_OWNFILENAME 0x100 /* ts->filename is malloc'd */
+#define TSF_XMLTAGMODE 0x200 /* scanning within an XML tag in E4X */
+#define TSF_XMLTEXTMODE 0x400 /* scanning XMLText terminal from E4X */
+#define TSF_XMLONLYMODE 0x800 /* don't scan {expr} within text/tag */
+
+/* Flag indicating unexpected end of input, i.e. TOK_EOF not at top-level. */
+#define TSF_UNEXPECTED_EOF 0x1000
+
+/*
+ * To handle the hard case of contiguous HTML comments, we want to clear the
+ * TSF_DIRTYINPUT flag at the end of each such comment. But we'd rather not
+ * scan for --> within every //-style comment unless we have to. So we set
+ * TSF_IN_HTML_COMMENT when a <!-- is scanned as an HTML begin-comment, and
+ * clear it (and TSF_DIRTYINPUT) when we scan --> either on a clean line, or
+ * only if (ts->flags & TSF_IN_HTML_COMMENT), in a //-style comment.
+ *
+ * This still works as before given a malformed comment hiding hack such as:
+ *
+ * <script>
+ * <!-- comment hiding hack #1
+ * code goes here
+ * // --> oops, markup for script-unaware browsers goes here!
+ * </script>
+ *
+ * It does not cope with malformed comment hiding hacks where --> is hidden
+ * by C-style comments, or on a dirty line. Such cases are already broken.
+ */
+#define TSF_IN_HTML_COMMENT 0x2000
+
+/* Ignore keywords and return TOK_NAME instead to the parser. */
+#define TSF_KEYWORD_IS_NAME 0x4000
+
+/* Unicode separators that are treated as line terminators, in addition to \n, \r */
+#define LINE_SEPARATOR 0x2028
+#define PARA_SEPARATOR 0x2029
+
+/*
+ * Create a new token stream, either from an input buffer or from a file.
+ * Return null on file-open or memory-allocation failure.
+ *
+ * The function uses JSContext.tempPool to allocate internal buffers. The
+ * caller should release them using JS_ARENA_RELEASE after it has finished
+ * with the token stream and has called js_CloseTokenStream.
+ */
+extern JSBool
+js_InitTokenStream(JSContext *cx, JSTokenStream *ts,
+ const jschar *base, size_t length,
+ FILE *fp, const char *filename, uintN lineno);
+
+extern void
+js_CloseTokenStream(JSContext *cx, JSTokenStream *ts);
+
+extern JS_FRIEND_API(int)
+js_fgets(char *buf, int size, FILE *file);
+
+/*
+ * If the given char array forms JavaScript keyword, return corresponding
+ * token. Otherwise return TOK_EOF.
+ */
+extern JSTokenType
+js_CheckKeyword(const jschar *chars, size_t length);
+
+/*
+ * Friend-exported API entry point to call a mapping function on each reserved
+ * identifier in the scanner's keyword table.
+ */
+extern JS_FRIEND_API(void)
+js_MapKeywords(void (*mapfun)(const char *));
+
+/*
+ * Check that str forms a valid JS identifier name. The function does not
+ * check if str is a JS keyword.
+ */
+extern JSBool
+js_IsIdentifier(JSString *str);
+
+/*
+ * Report a compile-time error by its number. Return true for a warning, false
+ * for an error. When pn is not null, use it to report error's location.
+ * Otherwise use ts, which must not be null.
+ */
+JSBool
+js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts, JSParseNode *pn,
+ uintN flags, uintN errorNumber, ...);
+
+/*
+ * Steal one JSREPORT_* bit (see jsapi.h) to tell that arguments to the error
+ * message have const jschar* type, not const char*.
+ */
+#define JSREPORT_UC 0x100
+
+/*
+ * Look ahead one token and return its type.
+ */
+extern JSTokenType
+js_PeekToken(JSContext *cx, JSTokenStream *ts);
+
+extern JSTokenType
+js_PeekTokenSameLine(JSContext *cx, JSTokenStream *ts);
+
+/*
+ * Get the next token from ts.
+ */
+extern JSTokenType
+js_GetToken(JSContext *cx, JSTokenStream *ts);
+
+/*
+ * Push back the last scanned token onto ts.
+ */
+extern void
+js_UngetToken(JSTokenStream *ts);
+
+/*
+ * Get the next token from ts if its type is tt.
+ */
+extern JSBool
+js_MatchToken(JSContext *cx, JSTokenStream *ts, JSTokenType tt);
+
+JS_END_EXTERN_C
+
+#endif /* jsscan_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp
new file mode 100644
index 0000000..1f9bc0c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.cpp
@@ -0,0 +1,1955 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS symbol tables.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsarena.h"
+#include "jsbit.h"
+#include "jsclist.h"
+#include "jsdhash.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsscope.h"
+#include "jsstr.h"
+
+JSScope *
+js_GetMutableScope(JSContext *cx, JSObject *obj)
+{
+ JSScope *scope, *newscope;
+ JSClass *clasp;
+ uint32 freeslot;
+
+ scope = OBJ_SCOPE(obj);
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
+ if (scope->object == obj)
+ return scope;
+ newscope = js_NewScope(cx, 0, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj),
+ obj);
+ if (!newscope)
+ return NULL;
+ JS_LOCK_SCOPE(cx, newscope);
+ obj->map = js_HoldObjectMap(cx, &newscope->map);
+ JS_ASSERT(newscope->map.freeslot == JSSLOT_FREE(STOBJ_GET_CLASS(obj)));
+ clasp = STOBJ_GET_CLASS(obj);
+ if (clasp->reserveSlots) {
+ freeslot = JSSLOT_FREE(clasp) + clasp->reserveSlots(cx, obj);
+ if (freeslot > STOBJ_NSLOTS(obj))
+ freeslot = STOBJ_NSLOTS(obj);
+ if (newscope->map.freeslot < freeslot)
+ newscope->map.freeslot = freeslot;
+ }
+ scope = (JSScope *) js_DropObjectMap(cx, &scope->map, obj);
+ JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);
+ return newscope;
+}
+
+/*
+ * JSScope uses multiplicative hashing, _a la_ jsdhash.[ch], but specialized
+ * to minimize footprint. But if a scope has fewer than SCOPE_HASH_THRESHOLD
+ * entries, we use linear search and avoid allocating scope->table.
+ */
+#define SCOPE_HASH_THRESHOLD 6
+#define MIN_SCOPE_SIZE_LOG2 4
+#define MIN_SCOPE_SIZE JS_BIT(MIN_SCOPE_SIZE_LOG2)
+#define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *))
+
+static void
+InitMinimalScope(JSScope *scope)
+{
+ scope->shape = 0;
+ scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
+ scope->entryCount = scope->removedCount = 0;
+ scope->table = NULL;
+ scope->lastProp = NULL;
+}
+
+static JSBool
+CreateScopeTable(JSContext *cx, JSScope *scope, JSBool report)
+{
+ int sizeLog2;
+ JSScopeProperty *sprop, **spp;
+
+ JS_ASSERT(!scope->table);
+ JS_ASSERT(scope->lastProp);
+
+ if (scope->entryCount > SCOPE_HASH_THRESHOLD) {
+ /*
+ * Either we're creating a table for a large scope that was populated
+ * via property cache hit logic under JSOP_INITPROP, JSOP_SETNAME, or
+ * JSOP_SETPROP; or else calloc failed at least once already. In any
+ * event, let's try to grow, overallocating to hold at least twice the
+ * current population.
+ */
+ sizeLog2 = JS_CeilingLog2(2 * scope->entryCount);
+ scope->hashShift = JS_DHASH_BITS - sizeLog2;
+ } else {
+ JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);
+ sizeLog2 = MIN_SCOPE_SIZE_LOG2;
+ }
+
+ scope->table = (JSScopeProperty **)
+ calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *));
+ if (!scope->table) {
+ if (report)
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ js_UpdateMallocCounter(cx, JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));
+
+ scope->hashShift = JS_DHASH_BITS - sizeLog2;
+ for (sprop = scope->lastProp; sprop; sprop = sprop->parent) {
+ spp = js_SearchScope(scope, sprop->id, JS_TRUE);
+ SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
+ }
+ return JS_TRUE;
+}
+
+JSScope *
+js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
+ JSObject *obj)
+{
+ JSScope *scope;
+
+ scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));
+ if (!scope)
+ return NULL;
+
+ js_InitObjectMap(&scope->map, nrefs, ops, clasp);
+ scope->object = obj;
+ scope->flags = 0;
+ InitMinimalScope(scope);
+
+#ifdef JS_THREADSAFE
+ js_InitTitle(cx, &scope->title);
+#endif
+ JS_RUNTIME_METER(cx->runtime, liveScopes);
+ JS_RUNTIME_METER(cx->runtime, totalScopes);
+ return scope;
+}
+
+#ifdef DEBUG_SCOPE_COUNT
+extern void
+js_unlog_scope(JSScope *scope);
+#endif
+
+#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
+# include "jsprf.h"
+# define LIVE_SCOPE_METER(cx,expr) JS_LOCK_RUNTIME_VOID(cx->runtime,expr)
+#else
+# define LIVE_SCOPE_METER(cx,expr) /* nothing */
+#endif
+
+void
+js_DestroyScope(JSContext *cx, JSScope *scope)
+{
+#ifdef DEBUG_SCOPE_COUNT
+ js_unlog_scope(scope);
+#endif
+
+#ifdef JS_THREADSAFE
+ js_FinishTitle(cx, &scope->title);
+#endif
+ if (scope->table)
+ JS_free(cx, scope->table);
+
+ LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
+ JS_RUNTIME_UNMETER(cx->runtime, liveScopes);
+ JS_free(cx, scope);
+}
+
+#ifdef JS_DUMP_PROPTREE_STATS
+typedef struct JSScopeStats {
+ jsrefcount searches;
+ jsrefcount hits;
+ jsrefcount misses;
+ jsrefcount hashes;
+ jsrefcount steps;
+ jsrefcount stepHits;
+ jsrefcount stepMisses;
+ jsrefcount adds;
+ jsrefcount redundantAdds;
+ jsrefcount addFailures;
+ jsrefcount changeFailures;
+ jsrefcount compresses;
+ jsrefcount grows;
+ jsrefcount removes;
+ jsrefcount removeFrees;
+ jsrefcount uselessRemoves;
+ jsrefcount shrinks;
+} JSScopeStats;
+
+JS_FRIEND_DATA(JSScopeStats) js_scope_stats = {0};
+
+# define METER(x) JS_ATOMIC_INCREMENT(&js_scope_stats.x)
+#else
+# define METER(x) /* nothing */
+#endif
+
+JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
+JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
+
+#if JS_BYTES_PER_WORD == 4
+# define HASH_ID(id) ((JSHashNumber)(id))
+#elif JS_BYTES_PER_WORD == 8
+# define HASH_ID(id) ((JSHashNumber)(id) ^ (JSHashNumber)((id) >> 32))
+#else
+# error "Unsupported configuration"
+#endif
+
+/*
+ * Double hashing needs the second hash code to be relatively prime to table
+ * size, so we simply make hash2 odd. The inputs to multiplicative hash are
+ * the golden ratio, expressed as a fixed-point 32 bit fraction, and the id
+ * itself.
+ */
+#define SCOPE_HASH0(id) (HASH_ID(id) * JS_GOLDEN_RATIO)
+#define SCOPE_HASH1(hash0,shift) ((hash0) >> (shift))
+#define SCOPE_HASH2(hash0,log2,shift) ((((hash0) << (log2)) >> (shift)) | 1)
+
+JS_FRIEND_API(JSScopeProperty **)
+js_SearchScope(JSScope *scope, jsid id, JSBool adding)
+{
+ JSHashNumber hash0, hash1, hash2;
+ int hashShift, sizeLog2;
+ JSScopeProperty *stored, *sprop, **spp, **firstRemoved;
+ uint32 sizeMask;
+
+ METER(searches);
+ if (!scope->table) {
+ /* Not enough properties to justify hashing: search from lastProp. */
+ JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));
+ for (spp = &scope->lastProp; (sprop = *spp); spp = &sprop->parent) {
+ if (sprop->id == id) {
+ METER(hits);
+ return spp;
+ }
+ }
+ METER(misses);
+ return spp;
+ }
+
+ /* Compute the primary hash address. */
+ METER(hashes);
+ hash0 = SCOPE_HASH0(id);
+ hashShift = scope->hashShift;
+ hash1 = SCOPE_HASH1(hash0, hashShift);
+ spp = scope->table + hash1;
+
+ /* Miss: return space for a new entry. */
+ stored = *spp;
+ if (SPROP_IS_FREE(stored)) {
+ METER(misses);
+ return spp;
+ }
+
+ /* Hit: return entry. */
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ if (sprop && sprop->id == id) {
+ METER(hits);
+ return spp;
+ }
+
+ /* Collision: double hash. */
+ sizeLog2 = JS_DHASH_BITS - hashShift;
+ hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift);
+ sizeMask = JS_BITMASK(sizeLog2);
+
+ /* Save the first removed entry pointer so we can recycle it if adding. */
+ if (SPROP_IS_REMOVED(stored)) {
+ firstRemoved = spp;
+ } else {
+ firstRemoved = NULL;
+ if (adding && !SPROP_HAD_COLLISION(stored))
+ SPROP_FLAG_COLLISION(spp, sprop);
+ }
+
+ for (;;) {
+ METER(steps);
+ hash1 -= hash2;
+ hash1 &= sizeMask;
+ spp = scope->table + hash1;
+
+ stored = *spp;
+ if (SPROP_IS_FREE(stored)) {
+ METER(stepMisses);
+ return (adding && firstRemoved) ? firstRemoved : spp;
+ }
+
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ if (sprop && sprop->id == id) {
+ METER(stepHits);
+ return spp;
+ }
+
+ if (SPROP_IS_REMOVED(stored)) {
+ if (!firstRemoved)
+ firstRemoved = spp;
+ } else {
+ if (adding && !SPROP_HAD_COLLISION(stored))
+ SPROP_FLAG_COLLISION(spp, sprop);
+ }
+ }
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+static JSBool
+ChangeScope(JSContext *cx, JSScope *scope, int change)
+{
+ int oldlog2, newlog2;
+ uint32 oldsize, newsize, nbytes;
+ JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop;
+
+ if (!scope->table)
+ return CreateScopeTable(cx, scope, JS_TRUE);
+
+ /* Grow, shrink, or compress by changing scope->table. */
+ oldlog2 = JS_DHASH_BITS - scope->hashShift;
+ newlog2 = oldlog2 + change;
+ oldsize = JS_BIT(oldlog2);
+ newsize = JS_BIT(newlog2);
+ nbytes = SCOPE_TABLE_NBYTES(newsize);
+ table = (JSScopeProperty **) calloc(nbytes, 1);
+ if (!table) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+
+ /* Now that we have a new table allocated, update scope members. */
+ scope->hashShift = JS_DHASH_BITS - newlog2;
+ scope->removedCount = 0;
+ oldtable = scope->table;
+ scope->table = table;
+
+ /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */
+ cx->runtime->gcMallocBytes += nbytes;
+
+ /* Copy only live entries, leaving removed and free ones behind. */
+ for (oldspp = oldtable; oldsize != 0; oldspp++) {
+ sprop = SPROP_FETCH(oldspp);
+ if (sprop) {
+ spp = js_SearchScope(scope, sprop->id, JS_TRUE);
+ JS_ASSERT(SPROP_IS_FREE(*spp));
+ *spp = sprop;
+ }
+ oldsize--;
+ }
+
+ /* Finally, free the old table storage. */
+ JS_free(cx, oldtable);
+ return JS_TRUE;
+}
+
+/*
+ * Take care to exclude the mark bits in case we're called from the GC.
+ */
+#define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_FLAG_SHAPE_REGEN)
+
+static JSDHashNumber
+js_HashScopeProperty(JSDHashTable *table, const void *key)
+{
+ const JSScopeProperty *sprop = (const JSScopeProperty *)key;
+ JSDHashNumber hash;
+ JSPropertyOp gsop;
+
+ /* Accumulate from least to most random so the low bits are most random. */
+ hash = 0;
+ gsop = sprop->getter;
+ if (gsop)
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop;
+ gsop = sprop->setter;
+ if (gsop)
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop;
+
+ hash = JS_ROTATE_LEFT32(hash, 4)
+ ^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED);
+
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->attrs;
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->shortid;
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->slot;
+ hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->id;
+ return hash;
+}
+
+#define SPROP_MATCH(sprop, child) \
+ SPROP_MATCH_PARAMS(sprop, (child)->id, (child)->getter, (child)->setter, \
+ (child)->slot, (child)->attrs, (child)->flags, \
+ (child)->shortid)
+
+#define SPROP_MATCH_PARAMS(sprop, aid, agetter, asetter, aslot, aattrs, \
+ aflags, ashortid) \
+ ((sprop)->id == (aid) && \
+ SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
+ aflags, ashortid))
+
+#define SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs, \
+ aflags, ashortid) \
+ ((sprop)->getter == (agetter) && \
+ (sprop)->setter == (asetter) && \
+ (sprop)->slot == (aslot) && \
+ (sprop)->attrs == (aattrs) && \
+ (((sprop)->flags ^ (aflags)) & ~SPROP_FLAGS_NOT_MATCHED) == 0 && \
+ (sprop)->shortid == (ashortid))
+
+static JSBool
+js_MatchScopeProperty(JSDHashTable *table,
+ const JSDHashEntryHdr *hdr,
+ const void *key)
+{
+ const JSPropertyTreeEntry *entry = (const JSPropertyTreeEntry *)hdr;
+ const JSScopeProperty *sprop = entry->child;
+ const JSScopeProperty *kprop = (const JSScopeProperty *)key;
+
+ return SPROP_MATCH(sprop, kprop);
+}
+
+static const JSDHashTableOps PropertyTreeHashOps = {
+ JS_DHashAllocTable,
+ JS_DHashFreeTable,
+ js_HashScopeProperty,
+ js_MatchScopeProperty,
+ JS_DHashMoveEntryStub,
+ JS_DHashClearEntryStub,
+ JS_DHashFinalizeStub,
+ NULL
+};
+
+/*
+ * A property tree node on rt->propertyFreeList overlays the following prefix
+ * struct on JSScopeProperty.
+ */
+typedef struct FreeNode {
+ jsid id;
+ JSScopeProperty *next;
+ JSScopeProperty **prevp;
+} FreeNode;
+
+#define FREENODE(sprop) ((FreeNode *) (sprop))
+
+#define FREENODE_INSERT(list, sprop) \
+ JS_BEGIN_MACRO \
+ FREENODE(sprop)->next = (list); \
+ FREENODE(sprop)->prevp = &(list); \
+ if (list) \
+ FREENODE(list)->prevp = &FREENODE(sprop)->next; \
+ (list) = (sprop); \
+ JS_END_MACRO
+
+#define FREENODE_REMOVE(sprop) \
+ JS_BEGIN_MACRO \
+ *FREENODE(sprop)->prevp = FREENODE(sprop)->next; \
+ if (FREENODE(sprop)->next) \
+ FREENODE(FREENODE(sprop)->next)->prevp = FREENODE(sprop)->prevp; \
+ JS_END_MACRO
+
+/* NB: Called with rt->gcLock held. */
+static JSScopeProperty *
+NewScopeProperty(JSRuntime *rt)
+{
+ JSScopeProperty *sprop;
+
+ sprop = rt->propertyFreeList;
+ if (sprop) {
+ FREENODE_REMOVE(sprop);
+ } else {
+ JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *,
+ &rt->propertyArenaPool,
+ sizeof(JSScopeProperty));
+ if (!sprop)
+ return NULL;
+ }
+
+ JS_RUNTIME_METER(rt, livePropTreeNodes);
+ JS_RUNTIME_METER(rt, totalPropTreeNodes);
+ return sprop;
+}
+
+#define CHUNKY_KIDS_TAG ((jsuword)1)
+#define KIDS_IS_CHUNKY(kids) ((jsuword)(kids) & CHUNKY_KIDS_TAG)
+#define KIDS_TO_CHUNK(kids) ((PropTreeKidsChunk *) \
+ ((jsuword)(kids) & ~CHUNKY_KIDS_TAG))
+#define CHUNK_TO_KIDS(chunk) ((JSScopeProperty *) \
+ ((jsuword)(chunk) | CHUNKY_KIDS_TAG))
+#define MAX_KIDS_PER_CHUNK 10
+#define CHUNK_HASH_THRESHOLD 30
+
+typedef struct PropTreeKidsChunk PropTreeKidsChunk;
+
+struct PropTreeKidsChunk {
+ JSScopeProperty *kids[MAX_KIDS_PER_CHUNK];
+ JSDHashTable *table;
+ PropTreeKidsChunk *next;
+};
+
+static PropTreeKidsChunk *
+NewPropTreeKidsChunk(JSRuntime *rt)
+{
+ PropTreeKidsChunk *chunk;
+
+ chunk = (PropTreeKidsChunk *) calloc(1, sizeof *chunk);
+ if (!chunk)
+ return NULL;
+ JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0);
+ JS_RUNTIME_METER(rt, propTreeKidsChunks);
+ return chunk;
+}
+
+static void
+DestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk)
+{
+ JS_RUNTIME_UNMETER(rt, propTreeKidsChunks);
+ if (chunk->table)
+ JS_DHashTableDestroy(chunk->table);
+ free(chunk);
+}
+
+/* NB: Called with rt->gcLock held. */
+static JSBool
+InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
+ JSScopeProperty *child, PropTreeKidsChunk *sweptChunk)
+{
+ JSDHashTable *table;
+ JSPropertyTreeEntry *entry;
+ JSScopeProperty **childp, *kids, *sprop;
+ PropTreeKidsChunk *chunk, **chunkp;
+ uintN i;
+
+ JS_ASSERT(!parent || child->parent != parent);
+
+ if (!parent) {
+ table = &rt->propertyTreeHash;
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
+ if (!entry)
+ return JS_FALSE;
+ childp = &entry->child;
+ sprop = *childp;
+ if (!sprop) {
+ *childp = child;
+ } else {
+ /*
+ * A "Duplicate child" case.
+ *
+ * We can't do away with child, as at least one live scope entry
+ * still points at it. What's more, that scope's lastProp chains
+ * through an ancestor line to reach child, and js_Enumerate and
+ * others count on this linkage. We must leave child out of the
+ * hash table, and not require it to be there when we eventually
+ * GC it (see RemovePropertyTreeChild, below).
+ *
+ * It is necessary to leave the duplicate child out of the hash
+ * table to preserve entry uniqueness. It is safe to leave the
+ * child out of the hash table (unlike the duplicate child cases
+ * below), because the child's parent link will be null, which
+ * can't dangle.
+ */
+ JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child));
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
+ }
+ } else {
+ childp = &parent->kids;
+ kids = *childp;
+ if (kids) {
+ if (KIDS_IS_CHUNKY(kids)) {
+ chunk = KIDS_TO_CHUNK(kids);
+
+ table = chunk->table;
+ if (table) {
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
+ if (!entry)
+ return JS_FALSE;
+ if (!entry->child) {
+ entry->child = child;
+ while (chunk->next)
+ chunk = chunk->next;
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ childp = &chunk->kids[i];
+ sprop = *childp;
+ if (!sprop)
+ goto insert;
+ }
+ chunkp = &chunk->next;
+ goto new_chunk;
+ }
+ }
+
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ childp = &chunk->kids[i];
+ sprop = *childp;
+ if (!sprop)
+ goto insert;
+
+ JS_ASSERT(sprop != child);
+ if (SPROP_MATCH(sprop, child)) {
+ /*
+ * Duplicate child, see comment above. In this
+ * case, we must let the duplicate be inserted at
+ * this level in the tree, so we keep iterating,
+ * looking for an empty slot in which to insert.
+ */
+ JS_ASSERT(sprop != child);
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
+ }
+ }
+ chunkp = &chunk->next;
+ } while ((chunk = *chunkp) != NULL);
+
+ new_chunk:
+ if (sweptChunk) {
+ chunk = sweptChunk;
+ } else {
+ chunk = NewPropTreeKidsChunk(rt);
+ if (!chunk)
+ return JS_FALSE;
+ }
+ *chunkp = chunk;
+ childp = &chunk->kids[0];
+ } else {
+ sprop = kids;
+ JS_ASSERT(sprop != child);
+ if (SPROP_MATCH(sprop, child)) {
+ /*
+ * Duplicate child, see comment above. Once again, we
+ * must let duplicates created by deletion pile up in a
+ * kids-chunk-list, in order to find them when sweeping
+ * and thereby avoid dangling parent pointers.
+ */
+ JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
+ }
+ if (sweptChunk) {
+ chunk = sweptChunk;
+ } else {
+ chunk = NewPropTreeKidsChunk(rt);
+ if (!chunk)
+ return JS_FALSE;
+ }
+ parent->kids = CHUNK_TO_KIDS(chunk);
+ chunk->kids[0] = sprop;
+ childp = &chunk->kids[1];
+ }
+ }
+ insert:
+ *childp = child;
+ }
+
+ child->parent = parent;
+ return JS_TRUE;
+}
+
+/* NB: Called with rt->gcLock held. */
+static PropTreeKidsChunk *
+RemovePropertyTreeChild(JSRuntime *rt, JSScopeProperty *child)
+{
+ PropTreeKidsChunk *freeChunk;
+ JSScopeProperty *parent, *kids, *kid;
+ JSDHashTable *table;
+ PropTreeKidsChunk *list, *chunk, **chunkp, *lastChunk;
+ uintN i, j;
+ JSPropertyTreeEntry *entry;
+
+ freeChunk = NULL;
+ parent = child->parent;
+ if (!parent) {
+ /*
+ * Don't remove child if it is not in rt->propertyTreeHash, but only
+ * matches a root child in the table that has compatible members. See
+ * the "Duplicate child" comments in InsertPropertyTreeChild, above.
+ */
+ table = &rt->propertyTreeHash;
+ } else {
+ kids = parent->kids;
+ if (KIDS_IS_CHUNKY(kids)) {
+ list = chunk = KIDS_TO_CHUNK(kids);
+ chunkp = &list;
+ table = chunk->table;
+
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ if (chunk->kids[i] == child) {
+ lastChunk = chunk;
+ if (!lastChunk->next) {
+ j = i + 1;
+ } else {
+ j = 0;
+ do {
+ chunkp = &lastChunk->next;
+ lastChunk = *chunkp;
+ } while (lastChunk->next);
+ }
+ for (; j < MAX_KIDS_PER_CHUNK; j++) {
+ if (!lastChunk->kids[j])
+ break;
+ }
+ --j;
+ if (chunk != lastChunk || j > i)
+ chunk->kids[i] = lastChunk->kids[j];
+ lastChunk->kids[j] = NULL;
+ if (j == 0) {
+ *chunkp = NULL;
+ if (!list)
+ parent->kids = NULL;
+ freeChunk = lastChunk;
+ }
+ goto out;
+ }
+ }
+
+ chunkp = &chunk->next;
+ } while ((chunk = *chunkp) != NULL);
+ } else {
+ table = NULL;
+ kid = kids;
+ if (kid == child)
+ parent->kids = NULL;
+ }
+ }
+
+out:
+ if (table) {
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP);
+
+ if (entry->child == child)
+ JS_DHashTableRawRemove(table, &entry->hdr);
+ }
+ return freeChunk;
+}
+
+static JSDHashTable *
+HashChunks(PropTreeKidsChunk *chunk, uintN n)
+{
+ JSDHashTable *table;
+ uintN i;
+ JSScopeProperty *sprop;
+ JSPropertyTreeEntry *entry;
+
+ table = JS_NewDHashTable(&PropertyTreeHashOps, NULL,
+ sizeof(JSPropertyTreeEntry),
+ JS_DHASH_DEFAULT_CAPACITY(n + 1));
+ if (!table)
+ return NULL;
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ sprop = chunk->kids[i];
+ if (!sprop)
+ break;
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, sprop, JS_DHASH_ADD);
+ entry->child = sprop;
+ }
+ } while ((chunk = chunk->next) != NULL);
+ return table;
+}
+
+/*
+ * Called without cx->runtime->gcLock held. This function acquires that lock
+ * only when inserting a new child. Thus there may be races to find or add a
+ * node that result in duplicates. We expect such races to be rare!
+ *
+ * We use rt->gcLock, not rt->rtLock, to allow the GC potentially to nest here
+ * under js_GenerateShape.
+ */
+static JSScopeProperty *
+GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
+ JSScopeProperty *child)
+{
+ JSRuntime *rt;
+ JSDHashTable *table;
+ JSPropertyTreeEntry *entry;
+ JSScopeProperty *sprop;
+ PropTreeKidsChunk *chunk;
+ uintN i, n;
+ uint32 shape;
+
+ rt = cx->runtime;
+ if (!parent) {
+ JS_LOCK_GC(rt);
+
+ table = &rt->propertyTreeHash;
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_ADD);
+ if (!entry)
+ goto out_of_memory;
+
+ sprop = entry->child;
+ if (sprop)
+ goto out;
+ } else {
+ /*
+ * Because chunks are appended at the end and never deleted except by
+ * the GC, we can search without taking the runtime's GC lock. We may
+ * miss a matching sprop added by another thread, and make a duplicate
+ * one, but that is an unlikely, therefore small, cost. The property
+ * tree has extremely low fan-out below its root in popular embeddings
+ * with real-world workloads.
+ *
+ * Patterns such as defining closures that capture a constructor's
+ * environment as getters or setters on the new object that is passed
+ * in as |this| can significantly increase fan-out below the property
+ * tree root -- see bug 335700 for details.
+ */
+ entry = NULL;
+ sprop = parent->kids;
+ if (sprop) {
+ if (KIDS_IS_CHUNKY(sprop)) {
+ chunk = KIDS_TO_CHUNK(sprop);
+
+ table = chunk->table;
+ if (table) {
+ JS_LOCK_GC(rt);
+ entry = (JSPropertyTreeEntry *)
+ JS_DHashTableOperate(table, child, JS_DHASH_LOOKUP);
+ sprop = entry->child;
+ if (sprop) {
+ JS_UNLOCK_GC(rt);
+ return sprop;
+ }
+ goto locked_not_found;
+ }
+
+ n = 0;
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ sprop = chunk->kids[i];
+ if (!sprop) {
+ n += i;
+ if (n >= CHUNK_HASH_THRESHOLD) {
+ chunk = KIDS_TO_CHUNK(parent->kids);
+ if (!chunk->table) {
+ table = HashChunks(chunk, n);
+ JS_LOCK_GC(rt);
+ if (!table)
+ goto out_of_memory;
+ if (chunk->table)
+ JS_DHashTableDestroy(table);
+ else
+ chunk->table = table;
+ goto locked_not_found;
+ }
+ }
+ goto not_found;
+ }
+
+ if (SPROP_MATCH(sprop, child))
+ return sprop;
+ }
+ n += MAX_KIDS_PER_CHUNK;
+ } while ((chunk = chunk->next) != NULL);
+ } else {
+ if (SPROP_MATCH(sprop, child))
+ return sprop;
+ }
+ }
+
+ not_found:
+ JS_LOCK_GC(rt);
+ }
+
+locked_not_found:
+ /*
+ * Call js_GenerateShape before the allocation to prevent collecting the
+ * new property when the shape generation triggers the GC.
+ */
+ shape = js_GenerateShape(cx, JS_TRUE, NULL);
+
+ sprop = NewScopeProperty(rt);
+ if (!sprop)
+ goto out_of_memory;
+
+ sprop->id = child->id;
+ sprop->getter = child->getter;
+ sprop->setter = child->setter;
+ sprop->slot = child->slot;
+ sprop->attrs = child->attrs;
+ sprop->flags = child->flags;
+ sprop->shortid = child->shortid;
+ sprop->parent = sprop->kids = NULL;
+ sprop->shape = shape;
+
+ if (!parent) {
+ entry->child = sprop;
+ } else {
+ if (!InsertPropertyTreeChild(rt, parent, sprop, NULL))
+ goto out_of_memory;
+ }
+
+out:
+ JS_UNLOCK_GC(rt);
+ return sprop;
+
+out_of_memory:
+ JS_UNLOCK_GC(rt);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+}
+
+#ifdef DEBUG_notbrendan
+#define CHECK_ANCESTOR_LINE(scope, sparse) \
+ JS_BEGIN_MACRO \
+ if ((scope)->table) CheckAncestorLine(scope, sparse); \
+ JS_END_MACRO
+
+static void
+CheckAncestorLine(JSScope *scope, JSBool sparse)
+{
+ uint32 size;
+ JSScopeProperty **spp, **start, **end, *ancestorLine, *sprop, *aprop;
+ uint32 entryCount, ancestorCount;
+
+ ancestorLine = SCOPE_LAST_PROP(scope);
+ if (ancestorLine)
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, ancestorLine));
+
+ entryCount = 0;
+ size = SCOPE_CAPACITY(scope);
+ start = scope->table;
+ for (spp = start, end = start + size; spp < end; spp++) {
+ sprop = SPROP_FETCH(spp);
+ if (sprop) {
+ entryCount++;
+ for (aprop = ancestorLine; aprop; aprop = aprop->parent) {
+ if (aprop == sprop)
+ break;
+ }
+ JS_ASSERT(aprop);
+ }
+ }
+ JS_ASSERT(entryCount == scope->entryCount);
+
+ ancestorCount = 0;
+ for (sprop = ancestorLine; sprop; sprop = sprop->parent) {
+ if (SCOPE_HAD_MIDDLE_DELETE(scope) &&
+ !SCOPE_HAS_PROPERTY(scope, sprop)) {
+ JS_ASSERT(sparse);
+ continue;
+ }
+ ancestorCount++;
+ }
+ JS_ASSERT(ancestorCount == scope->entryCount);
+}
+#else
+#define CHECK_ANCESTOR_LINE(scope, sparse) /* nothing */
+#endif
+
+static void
+ReportReadOnlyScope(JSContext *cx, JSScope *scope)
+{
+ JSString *str;
+ const char *bytes;
+
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(scope->object));
+ if (!str)
+ return;
+ bytes = js_GetStringBytes(cx, str);
+ if (!bytes)
+ return;
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY, bytes);
+}
+
+JSScopeProperty *
+js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid)
+{
+ JSScopeProperty **spp, *sprop, *overwriting, **spvec, **spp2, child;
+ uint32 size, splen, i;
+ int change;
+ JSTempValueRooter tvr;
+
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ /*
+ * You can't add properties to a sealed scope. But note well that you can
+ * change property attributes in a sealed scope, even though that replaces
+ * a JSScopeProperty * in the scope's hash table -- but no id is added, so
+ * the scope remains sealed.
+ */
+ if (SCOPE_IS_SEALED(scope)) {
+ ReportReadOnlyScope(cx, scope);
+ return NULL;
+ }
+
+ /*
+ * Normalize stub getter and setter values for faster is-stub testing in
+ * the SPROP_CALL_[GS]ETTER macros.
+ */
+ if (getter == JS_PropertyStub)
+ getter = NULL;
+ if (setter == JS_PropertyStub)
+ setter = NULL;
+
+ /*
+ * Search for id in order to claim its entry, allocating a property tree
+ * node if one doesn't already exist for our parameters.
+ */
+ spp = js_SearchScope(scope, id, JS_TRUE);
+ sprop = overwriting = SPROP_FETCH(spp);
+ if (!sprop) {
+ JS_COUNT_OPERATION(cx, JSOW_NEW_PROPERTY);
+
+ /* Check whether we need to grow, if the load factor is >= .75. */
+ size = SCOPE_CAPACITY(scope);
+ if (scope->entryCount + scope->removedCount >= size - (size >> 2)) {
+ if (scope->removedCount >= size >> 2) {
+ METER(compresses);
+ change = 0;
+ } else {
+ METER(grows);
+ change = 1;
+ }
+ if (!ChangeScope(cx, scope, change) &&
+ scope->entryCount + scope->removedCount == size - 1) {
+ METER(addFailures);
+ return NULL;
+ }
+ spp = js_SearchScope(scope, id, JS_TRUE);
+ JS_ASSERT(!SPROP_FETCH(spp));
+ }
+ } else {
+ /* Property exists: js_SearchScope must have returned a valid entry. */
+ JS_ASSERT(!SPROP_IS_REMOVED(*spp));
+
+ /*
+ * If all property members match, this is a redundant add and we can
+ * return early. If the caller wants to allocate a slot, but doesn't
+ * care which slot, copy sprop->slot into slot so we can match sprop,
+ * if all other members match.
+ */
+ if (!(attrs & JSPROP_SHARED) &&
+ slot == SPROP_INVALID_SLOT &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ slot = sprop->slot;
+ }
+ if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs,
+ flags, shortid)) {
+ METER(redundantAdds);
+ return sprop;
+ }
+
+ /*
+ * If we are clearing sprop to force an existing property to be
+ * overwritten (apart from a duplicate formal parameter), we must
+ * unlink it from the ancestor line at scope->lastProp, lazily if
+ * sprop is not lastProp. And we must remove the entry at *spp,
+ * precisely so the lazy "middle delete" fixup code further below
+ * won't find sprop in scope->table, in spite of sprop being on
+ * the ancestor line.
+ *
+ * When we finally succeed in finding or creating a new sprop
+ * and storing its pointer at *spp, we'll use the |overwriting|
+ * local saved when we first looked up id to decide whether we're
+ * indeed creating a new entry, or merely overwriting an existing
+ * property.
+ */
+ if (sprop == SCOPE_LAST_PROP(scope)) {
+ do {
+ SCOPE_REMOVE_LAST_PROP(scope);
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
+ break;
+ sprop = SCOPE_LAST_PROP(scope);
+ } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
+ } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
+ /*
+ * If we have no hash table yet, we need one now. The middle
+ * delete code is simple-minded that way!
+ */
+ if (!scope->table) {
+ if (!CreateScopeTable(cx, scope, JS_TRUE))
+ return NULL;
+ spp = js_SearchScope(scope, id, JS_TRUE);
+ sprop = overwriting = SPROP_FETCH(spp);
+ }
+ SCOPE_SET_MIDDLE_DELETE(scope);
+ }
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+
+ /*
+ * If we fail later on trying to find or create a new sprop, we will
+ * goto fail_overwrite and restore *spp from |overwriting|. Note that
+ * we don't bother to keep scope->removedCount in sync, because we'll
+ * fix up *spp and scope->entryCount shortly, no matter how control
+ * flow returns from this function.
+ */
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, NULL);
+ scope->entryCount--;
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ sprop = NULL;
+ }
+
+ if (!sprop) {
+ /*
+ * If properties were deleted from the middle of the list starting at
+ * scope->lastProp, we may need to fork the property tree and squeeze
+ * all deleted properties out of scope's ancestor line. Otherwise we
+ * risk adding a node with the same id as a "middle" node, violating
+ * the rule that properties along an ancestor line have distinct ids.
+ */
+ if (SCOPE_HAD_MIDDLE_DELETE(scope)) {
+ JS_ASSERT(scope->table);
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ splen = scope->entryCount;
+ if (splen == 0) {
+ JS_ASSERT(scope->lastProp == NULL);
+ } else {
+ /*
+ * Enumerate live entries in scope->table using a temporary
+ * vector, by walking the (possibly sparse, due to deletions)
+ * ancestor line from scope->lastProp.
+ */
+ spvec = (JSScopeProperty **)
+ JS_malloc(cx, SCOPE_TABLE_NBYTES(splen));
+ if (!spvec)
+ goto fail_overwrite;
+ i = splen;
+ sprop = SCOPE_LAST_PROP(scope);
+ JS_ASSERT(sprop);
+ do {
+ /*
+ * NB: test SCOPE_GET_PROPERTY, not SCOPE_HAS_PROPERTY --
+ * the latter insists that sprop->id maps to sprop, while
+ * the former simply tests whether sprop->id is bound in
+ * scope. We must allow for duplicate formal parameters
+ * along the ancestor line, and fork them as needed.
+ */
+ if (!SCOPE_GET_PROPERTY(scope, sprop->id))
+ continue;
+
+ JS_ASSERT(sprop != overwriting);
+ if (i == 0) {
+ /*
+ * If our original splen estimate, scope->entryCount,
+ * is less than the ancestor line height, there must
+ * be duplicate formal parameters in this (function
+ * object) scope. Count remaining ancestors in order
+ * to realloc spvec.
+ */
+ JSScopeProperty *tmp = sprop;
+ do {
+ if (SCOPE_GET_PROPERTY(scope, tmp->id))
+ i++;
+ } while ((tmp = tmp->parent) != NULL);
+ spp2 = (JSScopeProperty **)
+ JS_realloc(cx, spvec, SCOPE_TABLE_NBYTES(splen+i));
+ if (!spp2) {
+ JS_free(cx, spvec);
+ goto fail_overwrite;
+ }
+
+ spvec = spp2;
+ memmove(spvec + i, spvec, SCOPE_TABLE_NBYTES(splen));
+ splen += i;
+ }
+
+ spvec[--i] = sprop;
+ } while ((sprop = sprop->parent) != NULL);
+ JS_ASSERT(i == 0);
+
+ /*
+ * Now loop forward through spvec, forking the property tree
+ * whenever we see a "parent gap" due to deletions from scope.
+ * NB: sprop is null on first entry to the loop body.
+ */
+ do {
+ if (spvec[i]->parent == sprop) {
+ sprop = spvec[i];
+ } else {
+ sprop = GetPropertyTreeChild(cx, sprop, spvec[i]);
+ if (!sprop) {
+ JS_free(cx, spvec);
+ goto fail_overwrite;
+ }
+
+ spp2 = js_SearchScope(scope, sprop->id, JS_FALSE);
+ JS_ASSERT(SPROP_FETCH(spp2) == spvec[i]);
+ SPROP_STORE_PRESERVING_COLLISION(spp2, sprop);
+ }
+ } while (++i < splen);
+ JS_free(cx, spvec);
+
+ /*
+ * Now sprop points to the last property in scope, where the
+ * ancestor line from sprop to the root is dense w.r.t. scope:
+ * it contains no nodes not mapped by scope->table, apart from
+ * any stinking ECMA-mandated duplicate formal parameters.
+ */
+ scope->lastProp = sprop;
+ CHECK_ANCESTOR_LINE(scope, JS_FALSE);
+ JS_RUNTIME_METER(cx->runtime, middleDeleteFixups);
+ }
+
+ SCOPE_CLR_MIDDLE_DELETE(scope);
+ }
+
+ /*
+ * Aliases share another property's slot, passed in the |slot| param.
+ * Shared properties have no slot. Unshared properties that do not
+ * alias another property's slot get one here, but may lose it due to
+ * a JS_ClearScope call.
+ */
+ if (!(flags & SPROP_IS_ALIAS)) {
+ if (attrs & JSPROP_SHARED) {
+ slot = SPROP_INVALID_SLOT;
+ } else {
+ /*
+ * We may have set slot from a nearly-matching sprop, above.
+ * If so, we're overwriting that nearly-matching sprop, so we
+ * can reuse its slot -- we don't need to allocate a new one.
+ * Similarly, we use a specific slot if provided by the caller.
+ */
+ if (slot == SPROP_INVALID_SLOT &&
+ !js_AllocSlot(cx, scope->object, &slot)) {
+ goto fail_overwrite;
+ }
+ }
+ }
+
+ /*
+ * Check for a watchpoint on a deleted property; if one exists, change
+ * setter to js_watch_set.
+ * XXXbe this could get expensive with lots of watchpoints...
+ */
+ if (!JS_CLIST_IS_EMPTY(&cx->runtime->watchPointList) &&
+ js_FindWatchPoint(cx->runtime, scope, id)) {
+ JS_PUSH_TEMP_ROOT_SPROP(cx, overwriting, &tvr);
+ setter = js_WrapWatchedSetter(cx, id, attrs, setter);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!setter)
+ goto fail_overwrite;
+ }
+
+ /* Find or create a property tree node labeled by our arguments. */
+ child.id = id;
+ child.getter = getter;
+ child.setter = setter;
+ child.slot = slot;
+ child.attrs = attrs;
+ child.flags = flags;
+ child.shortid = shortid;
+ sprop = GetPropertyTreeChild(cx, scope->lastProp, &child);
+ if (!sprop)
+ goto fail_overwrite;
+
+ /*
+ * The scope's shape defaults to its last property's shape, but may
+ * be regenerated later as the scope diverges (from the property cache
+ * point of view) from the structural type associated with sprop.
+ */
+ SCOPE_EXTEND_SHAPE(cx, scope, sprop);
+
+ /* Store the tree node pointer in the table entry for id. */
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, sprop);
+ scope->entryCount++;
+ scope->lastProp = sprop;
+ CHECK_ANCESTOR_LINE(scope, JS_FALSE);
+#ifdef DEBUG
+ if (!overwriting) {
+ LIVE_SCOPE_METER(cx, ++cx->runtime->liveScopeProps);
+ JS_RUNTIME_METER(cx->runtime, totalScopeProps);
+ }
+#endif
+
+ /*
+ * If we reach the hashing threshold, try to allocate scope->table.
+ * If we can't (a rare event, preceded by swapping to death on most
+ * modern OSes), stick with linear search rather than whining about
+ * this little set-back. Therefore we must test !scope->table and
+ * scope->entryCount >= SCOPE_HASH_THRESHOLD, not merely whether the
+ * entry count just reached the threshold.
+ */
+ if (!scope->table && scope->entryCount >= SCOPE_HASH_THRESHOLD)
+ (void) CreateScopeTable(cx, scope, JS_FALSE);
+ }
+
+ METER(adds);
+ return sprop;
+
+fail_overwrite:
+ if (overwriting) {
+ /*
+ * We may or may not have forked overwriting out of scope's ancestor
+ * line, so we must check (the alternative is to set a flag above, but
+ * that hurts the common, non-error case). If we did fork overwriting
+ * out, we'll add it back at scope->lastProp. This means enumeration
+ * order can change due to a failure to overwrite an id.
+ * XXXbe very minor incompatibility
+ */
+ for (sprop = SCOPE_LAST_PROP(scope); ; sprop = sprop->parent) {
+ if (!sprop) {
+ sprop = SCOPE_LAST_PROP(scope);
+ if (overwriting->parent == sprop) {
+ scope->lastProp = overwriting;
+ } else {
+ sprop = GetPropertyTreeChild(cx, sprop, overwriting);
+ if (sprop) {
+ JS_ASSERT(sprop != overwriting);
+ scope->lastProp = sprop;
+ }
+ overwriting = sprop;
+ }
+ break;
+ }
+ if (sprop == overwriting)
+ break;
+ }
+ if (overwriting) {
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, overwriting);
+ scope->entryCount++;
+ }
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ }
+ METER(addFailures);
+ return NULL;
+}
+
+JSScopeProperty *
+js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter)
+{
+ JSScopeProperty child, *newsprop, **spp;
+
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ /* Allow only shared (slot-less) => unshared (slot-full) transition. */
+ attrs |= sprop->attrs & mask;
+ JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) ||
+ !(attrs & JSPROP_SHARED));
+ if (getter == JS_PropertyStub)
+ getter = NULL;
+ if (setter == JS_PropertyStub)
+ setter = NULL;
+ if (sprop->attrs == attrs &&
+ sprop->getter == getter &&
+ sprop->setter == setter) {
+ return sprop;
+ }
+
+ child.id = sprop->id;
+ child.getter = getter;
+ child.setter = setter;
+ child.slot = sprop->slot;
+ child.attrs = attrs;
+ child.flags = sprop->flags;
+ child.shortid = sprop->shortid;
+
+ if (SCOPE_LAST_PROP(scope) == sprop) {
+ /*
+ * Optimize the case where the last property added to scope is changed
+ * to have a different attrs, getter, or setter. In the last property
+ * case, we need not fork the property tree. But since we do not call
+ * js_AddScopeProperty, we may need to allocate a new slot directly.
+ */
+ if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) {
+ JS_ASSERT(child.slot == SPROP_INVALID_SLOT);
+ if (!js_AllocSlot(cx, scope->object, &child.slot))
+ return NULL;
+ }
+
+ newsprop = GetPropertyTreeChild(cx, sprop->parent, &child);
+ if (newsprop) {
+ spp = js_SearchScope(scope, sprop->id, JS_FALSE);
+ JS_ASSERT(SPROP_FETCH(spp) == sprop);
+
+ if (scope->table)
+ SPROP_STORE_PRESERVING_COLLISION(spp, newsprop);
+ scope->lastProp = newsprop;
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ }
+ } else {
+ /*
+ * Let js_AddScopeProperty handle this |overwriting| case, including
+ * the conservation of sprop->slot (if it's valid). We must not call
+ * js_RemoveScopeProperty here, it will free a valid sprop->slot and
+ * js_AddScopeProperty won't re-allocate it.
+ */
+ newsprop = js_AddScopeProperty(cx, scope, child.id,
+ child.getter, child.setter, child.slot,
+ child.attrs, child.flags, child.shortid);
+ }
+
+ if (newsprop) {
+ if (scope->shape == sprop->shape)
+ scope->shape = newsprop->shape;
+ else
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ }
+#ifdef JS_DUMP_PROPTREE_STATS
+ else
+ METER(changeFailures);
+#endif
+ return newsprop;
+}
+
+JSBool
+js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id)
+{
+ JSScopeProperty **spp, *stored, *sprop;
+ uint32 size;
+
+ JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ if (SCOPE_IS_SEALED(scope)) {
+ ReportReadOnlyScope(cx, scope);
+ return JS_FALSE;
+ }
+ METER(removes);
+
+ spp = js_SearchScope(scope, id, JS_FALSE);
+ stored = *spp;
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ if (!sprop) {
+ METER(uselessRemoves);
+ return JS_TRUE;
+ }
+
+ /* Convert from a list to a hash so we can handle "middle deletes". */
+ if (!scope->table && sprop != scope->lastProp) {
+ if (!CreateScopeTable(cx, scope, JS_TRUE))
+ return JS_FALSE;
+ spp = js_SearchScope(scope, id, JS_FALSE);
+ stored = *spp;
+ sprop = SPROP_CLEAR_COLLISION(stored);
+ }
+
+ /* First, if sprop is unshared and not cleared, free its slot number. */
+ if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ js_FreeSlot(cx, scope->object, sprop->slot);
+ JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
+ }
+
+ /* Next, remove id by setting its entry to a removed or free sentinel. */
+ if (SPROP_HAD_COLLISION(stored)) {
+ JS_ASSERT(scope->table);
+ *spp = SPROP_REMOVED;
+ scope->removedCount++;
+ } else {
+ METER(removeFrees);
+ if (scope->table)
+ *spp = NULL;
+ }
+ scope->entryCount--;
+ LIVE_SCOPE_METER(cx, --cx->runtime->liveScopeProps);
+
+ /* Update scope->lastProp directly, or set its deferred update flag. */
+ if (sprop == SCOPE_LAST_PROP(scope)) {
+ do {
+ SCOPE_REMOVE_LAST_PROP(scope);
+ if (!SCOPE_HAD_MIDDLE_DELETE(scope))
+ break;
+ sprop = SCOPE_LAST_PROP(scope);
+ } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));
+ } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {
+ SCOPE_SET_MIDDLE_DELETE(scope);
+ }
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+
+ /* Last, consider shrinking scope's table if its load factor is <= .25. */
+ size = SCOPE_CAPACITY(scope);
+ if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) {
+ METER(shrinks);
+ (void) ChangeScope(cx, scope, -1);
+ }
+
+ return JS_TRUE;
+}
+
+void
+js_ClearScope(JSContext *cx, JSScope *scope)
+{
+ CHECK_ANCESTOR_LINE(scope, JS_TRUE);
+ LIVE_SCOPE_METER(cx, cx->runtime->liveScopeProps -= scope->entryCount);
+
+ if (scope->table)
+ free(scope->table);
+ SCOPE_CLR_MIDDLE_DELETE(scope);
+ InitMinimalScope(scope);
+ JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
+}
+
+void
+js_TraceId(JSTracer *trc, jsid id)
+{
+ jsval v;
+
+ v = ID_TO_VALUE(id);
+ JS_CALL_VALUE_TRACER(trc, v, "id");
+}
+
+#ifdef DEBUG
+static void
+PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
+{
+ JSScopeProperty *sprop;
+ jsid id;
+ size_t n;
+ const char *name;
+
+ JS_ASSERT(trc->debugPrinter == PrintPropertyGetterOrSetter);
+ sprop = (JSScopeProperty *)trc->debugPrintArg;
+ id = sprop->id;
+ name = trc->debugPrintIndex ? js_setter_str : js_getter_str;
+
+ if (JSID_IS_ATOM(id)) {
+ n = js_PutEscapedString(buf, bufsize - 1,
+ ATOM_TO_STRING(JSID_TO_ATOM(id)), 0);
+ if (n < bufsize - 1)
+ JS_snprintf(buf + n, bufsize - n, " %s", name);
+ } else if (JSID_IS_INT(sprop->id)) {
+ JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(id), name);
+ } else {
+ JS_snprintf(buf, bufsize, "<object> %s", name);
+ }
+}
+#endif
+
+
+void
+js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop)
+{
+ if (IS_GC_MARKING_TRACER(trc))
+ sprop->flags |= SPROP_MARK;
+ TRACE_ID(trc, sprop->id);
+
+#if JS_HAS_GETTER_SETTER
+ if (sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
+ if (sprop->attrs & JSPROP_GETTER) {
+ JS_ASSERT(JSVAL_IS_OBJECT((jsval) sprop->getter));
+ JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, sprop, 0);
+ JS_CallTracer(trc, JSVAL_TO_OBJECT((jsval) sprop->getter),
+ JSTRACE_OBJECT);
+ }
+ if (sprop->attrs & JSPROP_SETTER) {
+ JS_ASSERT(JSVAL_IS_OBJECT((jsval) sprop->setter));
+ JS_SET_TRACING_DETAILS(trc, PrintPropertyGetterOrSetter, sprop, 1);
+ JS_CallTracer(trc, JSVAL_TO_OBJECT((jsval) sprop->setter),
+ JSTRACE_OBJECT);
+ }
+ }
+#endif /* JS_HAS_GETTER_SETTER */
+}
+
+#ifdef JS_DUMP_PROPTREE_STATS
+
+#include <stdio.h>
+
+static void
+MeterKidCount(JSBasicStats *bs, uintN nkids)
+{
+ JS_BASIC_STATS_ACCUM(bs, nkids);
+ bs->hist[JS_MIN(nkids, 10)]++;
+}
+
+static void
+MeterPropertyTree(JSBasicStats *bs, JSScopeProperty *node)
+{
+ uintN i, nkids;
+ JSScopeProperty *kids, *kid;
+ PropTreeKidsChunk *chunk;
+
+ nkids = 0;
+ kids = node->kids;
+ if (kids) {
+ if (KIDS_IS_CHUNKY(kids)) {
+ for (chunk = KIDS_TO_CHUNK(kids); chunk; chunk = chunk->next) {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ kid = chunk->kids[i];
+ if (!kid)
+ break;
+ MeterPropertyTree(bs, kid);
+ nkids++;
+ }
+ }
+ } else {
+ MeterPropertyTree(bs, kids);
+ nkids = 1;
+ }
+ }
+
+ MeterKidCount(bs, nkids);
+}
+
+static JSDHashOperator
+js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
+ void *arg)
+{
+ JSPropertyTreeEntry *entry = (JSPropertyTreeEntry *)hdr;
+ JSBasicStats *bs = (JSBasicStats *)arg;
+
+ MeterPropertyTree(bs, entry->child);
+ return JS_DHASH_NEXT;
+}
+
+static void
+DumpSubtree(JSContext *cx, JSScopeProperty *sprop, int level, FILE *fp)
+{
+ jsval v;
+ JSString *str;
+ JSScopeProperty *kids, *kid;
+ PropTreeKidsChunk *chunk;
+ uintN i;
+
+ fprintf(fp, "%*sid ", level, "");
+ v = ID_TO_VALUE(sprop->id);
+ if (JSID_IS_INT(sprop->id)) {
+ fprintf(fp, "%d", JSVAL_TO_INT(v));
+ } else {
+ if (JSID_IS_ATOM(sprop->id)) {
+ str = JSVAL_TO_STRING(v);
+ } else {
+ JS_ASSERT(JSID_IS_OBJECT(sprop->id));
+ str = js_ValueToString(cx, v);
+ fputs("object ", fp);
+ }
+ if (!str)
+ fputs("<error>", fp);
+ else
+ js_FileEscapedString(fp, str, '"');
+ }
+
+ fprintf(fp, " g/s %p/%p slot %u attrs %x flags %x shortid %d\n",
+ (void *) sprop->getter, (void *) sprop->setter, sprop->slot,
+ sprop->attrs, sprop->flags, sprop->shortid);
+ kids = sprop->kids;
+ if (kids) {
+ ++level;
+ if (KIDS_IS_CHUNKY(kids)) {
+ chunk = KIDS_TO_CHUNK(kids);
+ do {
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ kid = chunk->kids[i];
+ if (!kid)
+ break;
+ JS_ASSERT(kid->parent == sprop);
+ DumpSubtree(cx, kid, level, fp);
+ }
+ } while ((chunk = chunk->next) != NULL);
+ } else {
+ kid = kids;
+ DumpSubtree(cx, kid, level, fp);
+ }
+ }
+}
+
+#endif /* JS_DUMP_PROPTREE_STATS */
+
+void
+js_SweepScopeProperties(JSContext *cx)
+{
+ JSRuntime *rt = cx->runtime;
+ JSArena **ap, *a;
+ JSScopeProperty *limit, *sprop, *parent, *kids, *kid;
+ uintN liveCount;
+ PropTreeKidsChunk *chunk, *nextChunk, *freeChunk;
+ uintN i;
+
+#ifdef JS_DUMP_PROPTREE_STATS
+ JSBasicStats bs;
+ uint32 livePropCapacity = 0, totalLiveCount = 0;
+ static FILE *logfp;
+ if (!logfp)
+ logfp = fopen("/tmp/proptree.stats", "w");
+
+ JS_BASIC_STATS_INIT(&bs);
+ MeterKidCount(&bs, rt->propertyTreeHash.entryCount);
+ JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, &bs);
+
+ {
+ double props, nodes, mean, sigma;
+
+ props = rt->liveScopePropsPreSweep;
+ nodes = rt->livePropTreeNodes;
+ JS_ASSERT(nodes == bs.sum);
+ mean = JS_MeanAndStdDevBS(&bs, &sigma);
+
+ fprintf(logfp,
+ "props %g nodes %g beta %g meankids %g sigma %g max %u\n",
+ props, nodes, nodes / props, mean, sigma, bs.max);
+ }
+
+ JS_DumpHistogram(&bs, logfp);
+#endif
+
+ ap = &rt->propertyArenaPool.first.next;
+ while ((a = *ap) != NULL) {
+ limit = (JSScopeProperty *) a->avail;
+ liveCount = 0;
+ for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) {
+ /* If the id is null, sprop is already on the freelist. */
+ if (sprop->id == JSVAL_NULL)
+ continue;
+
+ /*
+ * If the mark bit is set, sprop is alive, so clear the mark bit
+ * and continue the while loop.
+ *
+ * Regenerate sprop->shape if it hasn't already been refreshed
+ * during the mark phase, when live scopes' lastProp members are
+ * followed to update both scope->shape and lastProp->shape.
+ */
+ if (sprop->flags & SPROP_MARK) {
+ sprop->flags &= ~SPROP_MARK;
+ if (sprop->flags & SPROP_FLAG_SHAPE_REGEN) {
+ sprop->flags &= ~SPROP_FLAG_SHAPE_REGEN;
+ } else {
+ sprop->shape = ++cx->runtime->shapeGen;
+ JS_ASSERT(sprop->shape != 0);
+ }
+ liveCount++;
+ continue;
+ }
+
+ /* Ok, sprop is garbage to collect: unlink it from its parent. */
+ freeChunk = RemovePropertyTreeChild(rt, sprop);
+
+ /*
+ * Take care to reparent all sprop's kids to their grandparent.
+ * InsertPropertyTreeChild can potentially fail for two reasons:
+ *
+ * 1. If parent is null, insertion into the root property hash
+ * table may fail. We are forced to leave the kid out of the
+ * table (as can already happen with duplicates) but ensure
+ * that the kid's parent pointer is set to null.
+ *
+ * 2. If parent is non-null, allocation of a new KidsChunk can
+ * fail. To prevent this from happening, we allow sprops's own
+ * chunks to be reused by the grandparent, which removes the
+ * need for InsertPropertyTreeChild to malloc a new KidsChunk.
+ *
+ * If sprop does not have chunky kids, then we rely on the
+ * RemovePropertyTreeChild call above (which removed sprop from
+ * its parent) either leaving one free entry, or else returning
+ * the now-unused chunk to us so we can reuse it.
+ *
+ * We also require the grandparent to have either no kids or else
+ * chunky kids. A single non-chunky kid would force a new chunk to
+ * be malloced in some cases (if sprop had a single non-chunky
+ * kid, or a multiple of MAX_KIDS_PER_CHUNK kids). Note that
+ * RemovePropertyTreeChild never converts a single-entry chunky
+ * kid back to a non-chunky kid, so we are assured of correct
+ * behaviour.
+ */
+ kids = sprop->kids;
+ if (kids) {
+ sprop->kids = NULL;
+ parent = sprop->parent;
+
+ /* Assert that grandparent has no kids or chunky kids. */
+ JS_ASSERT(!parent || !parent->kids ||
+ KIDS_IS_CHUNKY(parent->kids));
+ if (KIDS_IS_CHUNKY(kids)) {
+ chunk = KIDS_TO_CHUNK(kids);
+ do {
+ nextChunk = chunk->next;
+ chunk->next = NULL;
+ for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
+ kid = chunk->kids[i];
+ if (!kid)
+ break;
+ JS_ASSERT(kid->parent == sprop);
+
+ /*
+ * Clear a space in the kids array for possible
+ * re-use by InsertPropertyTreeChild.
+ */
+ chunk->kids[i] = NULL;
+ if (!InsertPropertyTreeChild(rt, parent, kid,
+ chunk)) {
+ /*
+ * This can happen only if we failed to add an
+ * entry to the root property hash table.
+ */
+ JS_ASSERT(!parent);
+ kid->parent = NULL;
+ }
+ }
+ if (!chunk->kids[0]) {
+ /* The chunk wasn't reused, so we must free it. */
+ DestroyPropTreeKidsChunk(rt, chunk);
+ }
+ } while ((chunk = nextChunk) != NULL);
+ } else {
+ kid = kids;
+ if (!InsertPropertyTreeChild(rt, parent, kid, freeChunk)) {
+ /*
+ * This can happen only if we failed to add an entry
+ * to the root property hash table.
+ */
+ JS_ASSERT(!parent);
+ kid->parent = NULL;
+ }
+ }
+ }
+
+ if (freeChunk && !freeChunk->kids[0]) {
+ /* The chunk wasn't reused, so we must free it. */
+ DestroyPropTreeKidsChunk(rt, freeChunk);
+ }
+
+ /* Clear id so we know (above) that sprop is on the freelist. */
+ sprop->id = JSVAL_NULL;
+ FREENODE_INSERT(rt->propertyFreeList, sprop);
+ JS_RUNTIME_UNMETER(rt, livePropTreeNodes);
+ }
+
+ /* If a contains no live properties, return it to the malloc heap. */
+ if (liveCount == 0) {
+ for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++)
+ FREENODE_REMOVE(sprop);
+ JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap);
+ } else {
+#ifdef JS_DUMP_PROPTREE_STATS
+ livePropCapacity += limit - (JSScopeProperty *) a->base;
+ totalLiveCount += liveCount;
+#endif
+ ap = &a->next;
+ }
+ }
+
+#ifdef JS_DUMP_PROPTREE_STATS
+ fprintf(logfp, "arenautil %g%%\n",
+ (totalLiveCount && livePropCapacity)
+ ? (totalLiveCount * 100.0) / livePropCapacity
+ : 0.0);
+
+#define RATE(f1, f2) (((double)js_scope_stats.f1 / js_scope_stats.f2) * 100.0)
+
+ fprintf(logfp, "Scope search stats:\n"
+ " searches: %6u\n"
+ " hits: %6u %5.2f%% of searches\n"
+ " misses: %6u %5.2f%%\n"
+ " hashes: %6u %5.2f%%\n"
+ " steps: %6u %5.2f%% %5.2f%% of hashes\n"
+ " stepHits: %6u %5.2f%% %5.2f%%\n"
+ " stepMisses: %6u %5.2f%% %5.2f%%\n"
+ " adds: %6u\n"
+ " redundantAdds: %6u\n"
+ " addFailures: %6u\n"
+ " changeFailures: %6u\n"
+ " compresses: %6u\n"
+ " grows: %6u\n"
+ " removes: %6u\n"
+ " removeFrees: %6u\n"
+ " uselessRemoves: %6u\n"
+ " shrinks: %6u\n",
+ js_scope_stats.searches,
+ js_scope_stats.hits, RATE(hits, searches),
+ js_scope_stats.misses, RATE(misses, searches),
+ js_scope_stats.hashes, RATE(hashes, searches),
+ js_scope_stats.steps, RATE(steps, searches), RATE(steps, hashes),
+ js_scope_stats.stepHits,
+ RATE(stepHits, searches), RATE(stepHits, hashes),
+ js_scope_stats.stepMisses,
+ RATE(stepMisses, searches), RATE(stepMisses, hashes),
+ js_scope_stats.adds,
+ js_scope_stats.redundantAdds,
+ js_scope_stats.addFailures,
+ js_scope_stats.changeFailures,
+ js_scope_stats.compresses,
+ js_scope_stats.grows,
+ js_scope_stats.removes,
+ js_scope_stats.removeFrees,
+ js_scope_stats.uselessRemoves,
+ js_scope_stats.shrinks);
+
+#undef RATE
+
+ fflush(logfp);
+#endif
+
+#ifdef DUMP_PROPERTY_TREE
+ {
+ FILE *dumpfp = fopen("/tmp/proptree.dump", "w");
+ if (dumpfp) {
+ JSPropertyTreeEntry *pte, *end;
+
+ pte = (JSPropertyTreeEntry *) rt->propertyTreeHash.entryStore;
+ end = pte + JS_DHASH_TABLE_SIZE(&rt->propertyTreeHash);
+ while (pte < end) {
+ if (pte->child)
+ DumpSubtree(cx, pte->child, 0, dumpfp);
+ pte++;
+ }
+ fclose(dumpfp);
+ }
+ }
+#endif
+}
+
+JSBool
+js_InitPropertyTree(JSRuntime *rt)
+{
+ if (!JS_DHashTableInit(&rt->propertyTreeHash, &PropertyTreeHashOps, NULL,
+ sizeof(JSPropertyTreeEntry), JS_DHASH_MIN_SIZE)) {
+ rt->propertyTreeHash.ops = NULL;
+ return JS_FALSE;
+ }
+ JS_INIT_ARENA_POOL(&rt->propertyArenaPool, "properties",
+ 256 * sizeof(JSScopeProperty), sizeof(void *), NULL);
+ return JS_TRUE;
+}
+
+void
+js_FinishPropertyTree(JSRuntime *rt)
+{
+ if (rt->propertyTreeHash.ops) {
+ JS_DHashTableFinish(&rt->propertyTreeHash);
+ rt->propertyTreeHash.ops = NULL;
+ }
+ JS_FinishArenaPool(&rt->propertyArenaPool);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscope.h b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.h
new file mode 100644
index 0000000..b7d8455
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscope.h
@@ -0,0 +1,419 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsscope_h___
+#define jsscope_h___
+/*
+ * JS symbol tables.
+ */
+#include "jstypes.h"
+#include "jslock.h"
+#include "jsobj.h"
+#include "jsprvtd.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Given P independent, non-unique properties each of size S words mapped by
+ * all scopes in a runtime, construct a property tree of N nodes each of size
+ * S+L words (L for tree linkage). A nominal L value is 2 for leftmost-child
+ * and right-sibling links. We hope that the N < P by enough that the space
+ * overhead of L, and the overhead of scope entries pointing at property tree
+ * nodes, is worth it.
+ *
+ * The tree construction goes as follows. If any empty scope in the runtime
+ * has a property X added to it, find or create a node under the tree root
+ * labeled X, and set scope->lastProp to point at that node. If any non-empty
+ * scope whose most recently added property is labeled Y has another property
+ * labeled Z added, find or create a node for Z under the node that was added
+ * for Y, and set scope->lastProp to point at that node.
+ *
+ * A property is labeled by its members' values: id, getter, setter, slot,
+ * attributes, tiny or short id, and a field telling for..in order. Note that
+ * labels are not unique in the tree, but they are unique among a node's kids
+ * (barring rare and benign multi-threaded race condition outcomes, see below)
+ * and along any ancestor line from the tree root to a given leaf node (except
+ * for the hard case of duplicate formal parameters to a function).
+ *
+ * Thus the root of the tree represents all empty scopes, and the first ply
+ * of the tree represents all scopes containing one property, etc. Each node
+ * in the tree can stand for any number of scopes having the same ordered set
+ * of properties, where that node was the last added to the scope. (We need
+ * not store the root of the tree as a node, and do not -- all we need are
+ * links to its kids.)
+ *
+ * Sidebar on for..in loop order: ECMA requires no particular order, but this
+ * implementation has promised and delivered property definition order, and
+ * compatibility is king. We could use an order number per property, which
+ * would require a sort in js_Enumerate, and an entry order generation number
+ * per scope. An order number beats a list, which should be doubly-linked for
+ * O(1) delete. An even better scheme is to use a parent link in the property
+ * tree, so that the ancestor line can be iterated from scope->lastProp when
+ * filling in a JSIdArray from back to front. This parent link also helps the
+ * GC to sweep properties iteratively.
+ *
+ * What if a property Y is deleted from a scope? If Y is the last property in
+ * the scope, we simply adjust the scope's lastProp member after we remove the
+ * scope's hash-table entry pointing at that property node. The parent link
+ * mentioned in the for..in sidebar above makes this adjustment O(1). But if
+ * Y comes between X and Z in the scope, then we might have to "fork" the tree
+ * at X, leaving X->Y->Z in case other scopes have those properties added in
+ * that order; and to finish the fork, we'd add a node labeled Z with the path
+ * X->Z, if it doesn't exist. This could lead to lots of extra nodes, and to
+ * O(n^2) growth when deleting lots of properties.
+ *
+ * Rather, for O(1) growth all around, we should share the path X->Y->Z among
+ * scopes having those three properties added in that order, and among scopes
+ * having only X->Z where Y was deleted. All such scopes have a lastProp that
+ * points to the Z child of Y. But a scope in which Y was deleted does not
+ * have a table entry for Y, and when iterating that scope by traversing the
+ * ancestor line from Z, we will have to test for a table entry for each node,
+ * skipping nodes that lack entries.
+ *
+ * What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
+ * Therefore we must fork in such a case, if not earlier. Because delete is
+ * "bursty", we should not fork eagerly. Delaying a fork till we are at risk
+ * of adding Y after it was deleted already requires a flag in the JSScope, to
+ * wit, SCOPE_MIDDLE_DELETE.
+ *
+ * What about thread safety? If the property tree operations done by requests
+ * are find-node and insert-node, then the only hazard is duplicate insertion.
+ * This is harmless except for minor bloat. When all requests have ended or
+ * been suspended, the GC is free to sweep the tree after marking all nodes
+ * reachable from scopes, performing remove-node operations as needed.
+ *
+ * Is the property tree worth it compared to property storage in each table's
+ * entries? To decide, we must find the relation <> between the words used
+ * with a property tree and the words required without a tree.
+ *
+ * Model all scopes as one super-scope of capacity T entries (T a power of 2).
+ * Let alpha be the load factor of this double hash-table. With the property
+ * tree, each entry in the table is a word-sized pointer to a node that can be
+ * shared by many scopes. But all such pointers are overhead compared to the
+ * situation without the property tree, where the table stores property nodes
+ * directly, as entries each of size S words. With the property tree, we need
+ * L=2 extra words per node for siblings and kids pointers. Without the tree,
+ * (1-alpha)*S*T words are wasted on free or removed sentinel-entries required
+ * by double hashing.
+ *
+ * Therefore,
+ *
+ * (property tree) <> (no property tree)
+ * N*(S+L) + T <> S*T
+ * N*(S+L) + T <> P*S + (1-alpha)*S*T
+ * N*(S+L) + alpha*T + (1-alpha)*T <> P*S + (1-alpha)*S*T
+ *
+ * Note that P is alpha*T by definition, so
+ *
+ * N*(S+L) + P + (1-alpha)*T <> P*S + (1-alpha)*S*T
+ * N*(S+L) <> P*S - P + (1-alpha)*S*T - (1-alpha)*T
+ * N*(S+L) <> (P + (1-alpha)*T) * (S-1)
+ * N*(S+L) <> (P + (1-alpha)*P/alpha) * (S-1)
+ * N*(S+L) <> P * (1/alpha) * (S-1)
+ *
+ * Let N = P*beta for a compression ratio beta, beta <= 1:
+ *
+ * P*beta*(S+L) <> P * (1/alpha) * (S-1)
+ * beta*(S+L) <> (S-1)/alpha
+ * beta <> (S-1)/((S+L)*alpha)
+ *
+ * For S = 6 (32-bit architectures) and L = 2, the property tree wins iff
+ *
+ * beta < 5/(8*alpha)
+ *
+ * We ensure that alpha <= .75, so the property tree wins if beta < .83_. An
+ * average beta from recent Mozilla browser startups was around .6.
+ *
+ * Can we reduce L? Observe that the property tree degenerates into a list of
+ * lists if at most one property Y follows X in all scopes. In or near such a
+ * case, we waste a word on the right-sibling link outside of the root ply of
+ * the tree. Note also that the root ply tends to be large, so O(n^2) growth
+ * searching it is likely, indicating the need for hashing (but with increased
+ * thread safety costs).
+ *
+ * If only K out of N nodes in the property tree have more than one child, we
+ * could eliminate the sibling link and overlay a children list or hash-table
+ * pointer on the leftmost-child link (which would then be either null or an
+ * only-child link; the overlay could be tagged in the low bit of the pointer,
+ * or flagged elsewhere in the property tree node, although such a flag must
+ * not be considered when comparing node labels during tree search).
+ *
+ * For such a system, L = 1 + (K * averageChildrenTableSize) / N instead of 2.
+ * If K << N, L approaches 1 and the property tree wins if beta < .95.
+ *
+ * We observe that fan-out below the root ply of the property tree appears to
+ * have extremely low degree (see the MeterPropertyTree code that histograms
+ * child-counts in jsscope.c), so instead of a hash-table we use a linked list
+ * of child node pointer arrays ("kid chunks"). The details are isolated in
+ * jsscope.c; others must treat JSScopeProperty.kids as opaque. We leave it
+ * strongly typed for debug-ability of the common (null or one-kid) cases.
+ *
+ * One final twist (can you stand it?): the mean number of entries per scope
+ * in Mozilla is < 5, with a large standard deviation (~8). Instead of always
+ * allocating scope->table, we leave it null while initializing all the other
+ * scope members as if it were non-null and minimal-length. Until a property
+ * is added that crosses the threshold of 6 or more entries for hashing, or
+ * until a "middle delete" occurs, we use linear search from scope->lastProp
+ * to find a given id, and save on the space overhead of a hash table.
+ */
+
+struct JSScope {
+ JSObjectMap map; /* base class state */
+#ifdef JS_THREADSAFE
+ JSTitle title; /* lock state */
+#endif
+ JSObject *object; /* object that owns this scope */
+ uint32 shape; /* property cache shape identifier */
+ uint8 flags; /* flags, see below */
+ int8 hashShift; /* multiplicative hash shift */
+ uint16 spare; /* reserved */
+ uint32 entryCount; /* number of entries in table */
+ uint32 removedCount; /* removed entry sentinels in table */
+ JSScopeProperty **table; /* table of ptrs to shared tree nodes */
+ JSScopeProperty *lastProp; /* pointer to last property added */
+};
+
+#ifdef JS_THREADSAFE
+JS_STATIC_ASSERT(offsetof(JSScope, title) == sizeof(JSObjectMap));
+#endif
+
+#define JS_IS_SCOPE_LOCKED(cx, scope) JS_IS_TITLE_LOCKED(cx, &(scope)->title)
+
+#define OBJ_SCOPE(obj) ((JSScope *)(obj)->map)
+#define OBJ_SHAPE(obj) (OBJ_SCOPE(obj)->shape)
+
+#define SCOPE_MAKE_UNIQUE_SHAPE(cx,scope) \
+ ((scope)->shape = js_GenerateShape((cx), JS_FALSE, NULL))
+
+#define SCOPE_EXTEND_SHAPE(cx,scope,sprop) \
+ JS_BEGIN_MACRO \
+ if (!(scope)->lastProp || \
+ (scope)->shape == (scope)->lastProp->shape) { \
+ (scope)->shape = (sprop)->shape; \
+ } else { \
+ (scope)->shape = js_GenerateShape((cx), JS_FALSE, sprop); \
+ } \
+ JS_END_MACRO
+
+/* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
+#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
+
+/* Scope flags and some macros to hide them from other files than jsscope.c. */
+#define SCOPE_MIDDLE_DELETE 0x0001
+#define SCOPE_SEALED 0x0002
+#define SCOPE_BRANDED 0x0004
+
+#define SCOPE_HAD_MIDDLE_DELETE(scope) ((scope)->flags & SCOPE_MIDDLE_DELETE)
+#define SCOPE_SET_MIDDLE_DELETE(scope) ((scope)->flags |= SCOPE_MIDDLE_DELETE)
+#define SCOPE_CLR_MIDDLE_DELETE(scope) ((scope)->flags &= ~SCOPE_MIDDLE_DELETE)
+
+#define SCOPE_IS_SEALED(scope) ((scope)->flags & SCOPE_SEALED)
+#define SCOPE_SET_SEALED(scope) ((scope)->flags |= SCOPE_SEALED)
+#if 0
+/*
+ * Don't define this, it can't be done safely because JS_LOCK_OBJ will avoid
+ * taking the lock if the object owns its scope and the scope is sealed.
+ */
+#undef SCOPE_CLR_SEALED(scope) ((scope)->flags &= ~SCOPE_SEALED)
+#endif
+
+/*
+ * A branded scope's object contains plain old methods (function-valued
+ * properties without magic getters and setters), and its scope->shape
+ * evolves whenever a function value changes.
+ */
+#define SCOPE_IS_BRANDED(scope) ((scope)->flags & SCOPE_BRANDED)
+#define SCOPE_SET_BRANDED(scope) ((scope)->flags |= SCOPE_BRANDED)
+#define SCOPE_CLR_BRANDED(scope) ((scope)->flags &= ~SCOPE_BRANDED)
+
+/*
+ * A little information hiding for scope->lastProp, in case it ever becomes
+ * a tagged pointer again.
+ */
+#define SCOPE_LAST_PROP(scope) ((scope)->lastProp)
+#define SCOPE_REMOVE_LAST_PROP(scope) ((scope)->lastProp = \
+ (scope)->lastProp->parent)
+
+struct JSScopeProperty {
+ jsid id; /* int-tagged jsval/untagged JSAtom* */
+ JSPropertyOp getter; /* getter and setter hooks or objects */
+ JSPropertyOp setter;
+ uint32 slot; /* abstract index in object slots */
+ uint8 attrs; /* attributes, see jsapi.h JSPROP_* */
+ uint8 flags; /* flags, see below for defines */
+ int16 shortid; /* tinyid, or local arg/var index */
+ JSScopeProperty *parent; /* parent node, reverse for..in order */
+ JSScopeProperty *kids; /* null, single child, or a tagged ptr
+ to many-kids data structure */
+ uint32 shape; /* property cache shape identifier */
+};
+
+/* JSScopeProperty pointer tag bit indicating a collision. */
+#define SPROP_COLLISION ((jsuword)1)
+#define SPROP_REMOVED ((JSScopeProperty *) SPROP_COLLISION)
+
+/* Macros to get and set sprop pointer values and collision flags. */
+#define SPROP_IS_FREE(sprop) ((sprop) == NULL)
+#define SPROP_IS_REMOVED(sprop) ((sprop) == SPROP_REMOVED)
+#define SPROP_IS_LIVE(sprop) ((sprop) > SPROP_REMOVED)
+#define SPROP_FLAG_COLLISION(spp,sprop) (*(spp) = (JSScopeProperty *) \
+ ((jsuword)(sprop) | SPROP_COLLISION))
+#define SPROP_HAD_COLLISION(sprop) ((jsuword)(sprop) & SPROP_COLLISION)
+#define SPROP_FETCH(spp) SPROP_CLEAR_COLLISION(*(spp))
+
+#define SPROP_CLEAR_COLLISION(sprop) \
+ ((JSScopeProperty *) ((jsuword)(sprop) & ~SPROP_COLLISION))
+
+#define SPROP_STORE_PRESERVING_COLLISION(spp, sprop) \
+ (*(spp) = (JSScopeProperty *) ((jsuword)(sprop) \
+ | SPROP_HAD_COLLISION(*(spp))))
+
+/* Bits stored in sprop->flags. */
+#define SPROP_MARK 0x01
+#define SPROP_IS_ALIAS 0x02
+#define SPROP_HAS_SHORTID 0x04
+#define SPROP_FLAG_SHAPE_REGEN 0x08
+
+/*
+ * If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
+ * than id when calling sprop's getter or setter.
+ */
+#define SPROP_USERID(sprop) \
+ (((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
+ : ID_TO_VALUE((sprop)->id))
+
+#define SPROP_INVALID_SLOT 0xffffffff
+
+#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->map.freeslot)
+#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
+
+#define SPROP_HAS_STUB_GETTER(sprop) (!(sprop)->getter)
+#define SPROP_HAS_STUB_SETTER(sprop) (!(sprop)->setter)
+
+/*
+ * NB: SPROP_GET must not be called if SPROP_HAS_STUB_GETTER(sprop).
+ */
+#define SPROP_GET(cx,sprop,obj,obj2,vp) \
+ (((sprop)->attrs & JSPROP_GETTER) \
+ ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
+ OBJECT_TO_JSVAL((sprop)->getter), JSACC_READ, \
+ 0, 0, vp) \
+ : (sprop)->getter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
+
+/*
+ * NB: SPROP_SET must not be called if (SPROP_HAS_STUB_SETTER(sprop) &&
+ * !(sprop->attrs & JSPROP_GETTER)).
+ */
+#define SPROP_SET(cx,sprop,obj,obj2,vp) \
+ (((sprop)->attrs & JSPROP_SETTER) \
+ ? js_InternalGetOrSet(cx, obj, (sprop)->id, \
+ OBJECT_TO_JSVAL((sprop)->setter), JSACC_WRITE, \
+ 1, vp, vp) \
+ : ((sprop)->attrs & JSPROP_GETTER) \
+ ? (JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, \
+ JSMSG_GETTER_ONLY, NULL), JS_FALSE) \
+ : (sprop)->setter(cx, OBJ_THIS_OBJECT(cx,obj), SPROP_USERID(sprop), vp))
+
+/* Macro for common expression to test for shared permanent attributes. */
+#define SPROP_IS_SHARED_PERMANENT(sprop) \
+ ((~(sprop)->attrs & (JSPROP_SHARED | JSPROP_PERMANENT)) == 0)
+
+extern JSScope *
+js_GetMutableScope(JSContext *cx, JSObject *obj);
+
+extern JSScope *
+js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
+ JSObject *obj);
+
+extern void
+js_DestroyScope(JSContext *cx, JSScope *scope);
+
+extern JS_FRIEND_API(JSScopeProperty **)
+js_SearchScope(JSScope *scope, jsid id, JSBool adding);
+
+#define SCOPE_GET_PROPERTY(scope, id) \
+ SPROP_FETCH(js_SearchScope(scope, id, JS_FALSE))
+
+#define SCOPE_HAS_PROPERTY(scope, sprop) \
+ (SCOPE_GET_PROPERTY(scope, (sprop)->id) == (sprop))
+
+extern JSScopeProperty *
+js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
+ JSPropertyOp getter, JSPropertyOp setter, uint32 slot,
+ uintN attrs, uintN flags, intN shortid);
+
+extern JSScopeProperty *
+js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
+ JSScopeProperty *sprop, uintN attrs, uintN mask,
+ JSPropertyOp getter, JSPropertyOp setter);
+
+extern JSBool
+js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id);
+
+extern void
+js_ClearScope(JSContext *cx, JSScope *scope);
+
+/*
+ * These macros used to inline short code sequences, but they grew over time.
+ * We retain them for internal backward compatibility, and in case one or both
+ * ever shrink to inline-able size.
+ */
+#define TRACE_ID(trc, id) js_TraceId(trc, id)
+#define TRACE_SCOPE_PROPERTY(trc, sprop) js_TraceScopeProperty(trc, sprop)
+
+extern void
+js_TraceId(JSTracer *trc, jsid id);
+
+extern void
+js_TraceScopeProperty(JSTracer *trc, JSScopeProperty *sprop);
+
+extern void
+js_SweepScopeProperties(JSContext *cx);
+
+extern JSBool
+js_InitPropertyTree(JSRuntime *rt);
+
+extern void
+js_FinishPropertyTree(JSRuntime *rt);
+
+JS_END_EXTERN_C
+
+#endif /* jsscope_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp
new file mode 100644
index 0000000..fba6a60
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.cpp
@@ -0,0 +1,1891 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS script operations.
+ */
+#include "jsstddef.h"
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsatom.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#if JS_HAS_XDR
+#include "jsxdrapi.h"
+#endif
+
+#if JS_HAS_SCRIPT_OBJECT
+
+static const char js_script_exec_str[] = "Script.prototype.exec";
+static const char js_script_compile_str[] = "Script.prototype.compile";
+
+/*
+ * This routine requires that obj has been locked previously.
+ */
+static jsint
+GetScriptExecDepth(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
+ v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_START(&js_ScriptClass));
+ return JSVAL_TO_INT(v);
+}
+
+static void
+AdjustScriptExecDepth(JSContext *cx, JSObject *obj, jsint delta)
+{
+ jsint execDepth;
+
+ JS_LOCK_OBJ(cx, obj);
+ execDepth = GetScriptExecDepth(cx, obj);
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_START(&js_ScriptClass),
+ INT_TO_JSVAL(execDepth + delta));
+ JS_UNLOCK_OBJ(cx, obj);
+}
+
+#if JS_HAS_TOSOURCE
+static JSBool
+script_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ uint32 indent;
+ JSScript *script;
+ size_t i, j, k, n;
+ char buf[16];
+ jschar *s, *t;
+ JSString *str;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+
+ indent = 0;
+ if (argc != 0) {
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ }
+
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+
+ /* Let n count the source string length, j the "front porch" length. */
+ j = JS_snprintf(buf, sizeof buf, "(new %s(", js_ScriptClass.name);
+ n = j + 2;
+ if (!script) {
+ /* Let k count the constructor argument string length. */
+ k = 0;
+ s = NULL; /* quell GCC overwarning */
+ } else {
+ str = JS_DecompileScript(cx, script, "Script.prototype.toSource",
+ (uintN)indent);
+ if (!str)
+ return JS_FALSE;
+ str = js_QuoteString(cx, str, '\'');
+ if (!str)
+ return JS_FALSE;
+ JSSTRING_CHARS_AND_LENGTH(str, s, k);
+ n += k;
+ }
+
+ /* Allocate the source string and copy into it. */
+ t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!t)
+ return JS_FALSE;
+ for (i = 0; i < j; i++)
+ t[i] = buf[i];
+ for (j = 0; j < k; i++, j++)
+ t[i] = s[j];
+ t[i++] = ')';
+ t[i++] = ')';
+ t[i] = 0;
+
+ /* Create and return a JS string for t. */
+ str = JS_NewUCString(cx, t, n);
+ if (!str) {
+ JS_free(cx, t);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif /* JS_HAS_TOSOURCE */
+
+static JSBool
+script_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 indent;
+ JSObject *obj;
+ JSScript *script;
+ JSString *str;
+
+ indent = 0;
+ if (argc != 0) {
+ indent = js_ValueToECMAUint32(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ }
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (!script) {
+ *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ str = JS_DecompileScript(cx, script, "Script.prototype.toString",
+ (uintN)indent);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+script_compile_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSString *str;
+ JSObject *scopeobj;
+ jsval v;
+ JSScript *script, *oldscript;
+ JSStackFrame *caller;
+ const char *file;
+ uintN line;
+ JSPrincipals *principals;
+ uint32 tcflags;
+ jsint execDepth;
+
+ /* Make sure obj is a Script object. */
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
+ return JS_FALSE;
+
+ /* If no args, leave private undefined and return early. */
+ if (argc == 0)
+ goto out;
+
+ /* Otherwise, the first arg is the script source to compile. */
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+
+ scopeobj = NULL;
+ if (argc >= 2) {
+ if (!js_ValueToObject(cx, argv[1], &scopeobj))
+ return JS_FALSE;
+ argv[1] = OBJECT_TO_JSVAL(scopeobj);
+ }
+
+ /* Compile using the caller's scope chain, which js_Invoke passes to fp. */
+ caller = JS_GetScriptedCaller(cx, cx->fp);
+ JS_ASSERT(!caller || cx->fp->scopeChain == caller->scopeChain);
+
+ if (caller) {
+ if (!scopeobj) {
+ scopeobj = js_GetScopeChain(cx, caller);
+ if (!scopeobj)
+ return JS_FALSE;
+ }
+
+ principals = JS_EvalFramePrincipals(cx, cx->fp, caller);
+ file = js_ComputeFilename(cx, caller, principals, &line);
+ } else {
+ file = NULL;
+ line = 0;
+ principals = NULL;
+ }
+
+ /* Ensure we compile this script with the right (inner) principals. */
+ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_compile_str);
+ if (!scopeobj)
+ return JS_FALSE;
+
+ /*
+ * Compile the new script using the caller's scope chain, a la eval().
+ * Unlike jsobj.c:obj_eval, however, we do not pass TCF_COMPILE_N_GO in
+ * tcflags and use NULL for the callerFrame argument, because compilation
+ * is here separated from execution, and the run-time scope chain may not
+ * match the compile-time. TCF_COMPILE_N_GO is tested in jsemit.c and
+ * jsparse.c to optimize based on identity of run- and compile-time scope.
+ */
+ tcflags = 0;
+ script = js_CompileScript(cx, scopeobj, NULL, principals, tcflags,
+ JSSTRING_CHARS(str), JSSTRING_LENGTH(str),
+ NULL, file, line);
+ if (!script)
+ return JS_FALSE;
+
+ JS_LOCK_OBJ(cx, obj);
+ execDepth = GetScriptExecDepth(cx, obj);
+
+ /*
+ * execDepth must be 0 to allow compilation here, otherwise the JSScript
+ * struct can be released while running.
+ */
+ if (execDepth > 0) {
+ JS_UNLOCK_OBJ(cx, obj);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_COMPILE_EXECED_SCRIPT);
+ return JS_FALSE;
+ }
+
+ /* Swap script for obj's old script, if any. */
+ v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+ oldscript = (JSScript*) (!JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL);
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
+ JS_UNLOCK_OBJ(cx, obj);
+
+ if (oldscript)
+ js_DestroyScript(cx, oldscript);
+
+ script->u.object = obj;
+ js_CallNewScriptHook(cx, script, NULL);
+
+out:
+ /* Return the object. */
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+script_compile(JSContext *cx, uintN argc, jsval *vp)
+{
+ return script_compile_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
+}
+
+static JSBool
+script_exec_sub(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ JSObject *scopeobj, *parent;
+ JSStackFrame *fp, *caller;
+ JSPrincipals *principals;
+ JSScript *script;
+ JSBool ok;
+
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
+ return JS_FALSE;
+
+ scopeobj = NULL;
+ if (argc != 0) {
+ if (!js_ValueToObject(cx, argv[0], &scopeobj))
+ return JS_FALSE;
+ argv[0] = OBJECT_TO_JSVAL(scopeobj);
+ }
+
+ /*
+ * Emulate eval() by using caller's this, var object, sharp array, etc.,
+ * all propagated by js_Execute via a non-null fourth (down) argument to
+ * js_Execute. If there is no scripted caller, js_Execute uses its second
+ * (chain) argument to set the exec frame's varobj, thisp, and scopeChain.
+ *
+ * Unlike eval, which the compiler detects, Script.prototype.exec may be
+ * called from a lightweight function, or even from native code (in which
+ * case fp->varobj and fp->scopeChain are null). If exec is called from
+ * a lightweight function, we will need to get a Call object representing
+ * its frame, to act as the var object and scope chain head.
+ */
+ fp = cx->fp;
+ caller = JS_GetScriptedCaller(cx, fp);
+ if (caller && !caller->varobj) {
+ /* Called from a lightweight function. */
+ JS_ASSERT(caller->fun && !JSFUN_HEAVYWEIGHT_TEST(caller->fun->flags));
+
+ /* Scope chain links from Call object to callee's parent. */
+ parent = OBJ_GET_PARENT(cx, caller->callee);
+ if (!js_GetCallObject(cx, caller, parent))
+ return JS_FALSE;
+ }
+
+ if (!scopeobj) {
+ /* No scope object passed in: try to use the caller's scope chain. */
+ if (caller) {
+ /*
+ * Load caller->scopeChain after the conditional js_GetCallObject
+ * call above, which resets scopeChain as well as varobj.
+ */
+ scopeobj = js_GetScopeChain(cx, caller);
+ if (!scopeobj)
+ return JS_FALSE;
+ } else {
+ /*
+ * Called from native code, so we don't know what scope object to
+ * use. We could use parent (see above), but Script.prototype.exec
+ * might be a shared/sealed "superglobal" method. A more general
+ * approach would use cx->globalObject, which will be the same as
+ * exec.__parent__ in the non-superglobal case. In the superglobal
+ * case it's the right object: the global, not the superglobal.
+ */
+ scopeobj = cx->globalObject;
+ }
+ }
+
+ scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_script_exec_str);
+ if (!scopeobj)
+ return JS_FALSE;
+
+ /* Keep track of nesting depth for the script. */
+ AdjustScriptExecDepth(cx, obj, 1);
+
+ /* Must get to out label after this */
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (!script) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ /* Belt-and-braces: check that this script object has access to scopeobj. */
+ principals = script->principals;
+ ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
+ CLASS_ATOM(cx, Script));
+ if (!ok)
+ goto out;
+
+ ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
+
+out:
+ AdjustScriptExecDepth(cx, obj, -1);
+ return ok;
+}
+
+static JSBool
+script_exec(JSContext *cx, uintN argc, jsval *vp)
+{
+ return script_exec_sub(cx, JS_THIS_OBJECT(cx, vp), argc, vp + 2, vp);
+}
+
+#endif /* JS_HAS_SCRIPT_OBJECT */
+
+#if JS_HAS_XDR
+
+JSBool
+js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
+{
+ JSContext *cx;
+ JSScript *script, *oldscript;
+ JSBool ok;
+ jsbytecode *code;
+ uint32 length, lineno, nslots, magic;
+ uint32 natoms, nsrcnotes, ntrynotes, nobjects, nupvars, nregexps, i;
+ uint32 prologLength, version;
+ JSTempValueRooter tvr;
+ JSPrincipals *principals;
+ uint32 encodeable;
+ JSBool filenameWasSaved;
+ jssrcnote *notes, *sn;
+ JSSecurityCallbacks *callbacks;
+
+ cx = xdr->cx;
+ script = *scriptp;
+ nsrcnotes = ntrynotes = natoms = nobjects = nupvars = nregexps = 0;
+ filenameWasSaved = JS_FALSE;
+ notes = NULL;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ magic = JSXDR_MAGIC_SCRIPT_CURRENT;
+ if (!JS_XDRUint32(xdr, &magic))
+ return JS_FALSE;
+ if (magic != JSXDR_MAGIC_SCRIPT_CURRENT) {
+ /* We do not provide binary compatibility with older scripts. */
+ if (!hasMagic) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_SCRIPT_MAGIC);
+ return JS_FALSE;
+ }
+ *hasMagic = JS_FALSE;
+ return JS_TRUE;
+ }
+ if (hasMagic)
+ *hasMagic = JS_TRUE;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ length = script->length;
+ prologLength = PTRDIFF(script->main, script->code, jsbytecode);
+ JS_ASSERT((int16)script->version != JSVERSION_UNKNOWN);
+ version = (uint32)script->version | (script->nfixed << 16);
+ lineno = (uint32)script->lineno;
+ nslots = (uint32)script->nslots;
+ nslots = (uint32)((script->staticDepth << 16) | script->nslots);
+ natoms = (uint32)script->atomMap.length;
+
+ /* Count the srcnotes, keeping notes pointing at the first one. */
+ notes = SCRIPT_NOTES(script);
+ for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
+ continue;
+ nsrcnotes = PTRDIFF(sn, notes, jssrcnote);
+ nsrcnotes++; /* room for the terminator */
+
+ if (script->objectsOffset != 0)
+ nobjects = JS_SCRIPT_OBJECTS(script)->length;
+ if (script->upvarsOffset != 0)
+ nupvars = JS_SCRIPT_UPVARS(script)->length;
+ if (script->regexpsOffset != 0)
+ nregexps = JS_SCRIPT_REGEXPS(script)->length;
+ if (script->trynotesOffset != 0)
+ ntrynotes = JS_SCRIPT_TRYNOTES(script)->length;
+ }
+
+ if (!JS_XDRUint32(xdr, &length))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &prologLength))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &version))
+ return JS_FALSE;
+
+ /*
+ * To fuse allocations, we need srcnote, atom, objects, upvar, regexp,
+ * and trynote counts early.
+ */
+ if (!JS_XDRUint32(xdr, &natoms))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nsrcnotes))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &ntrynotes))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nobjects))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nupvars))
+ return JS_FALSE;
+ if (!JS_XDRUint32(xdr, &nregexps))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ script = js_NewScript(cx, length, nsrcnotes, natoms, nobjects, nupvars,
+ nregexps, ntrynotes);
+ if (!script)
+ return JS_FALSE;
+
+ script->main += prologLength;
+ script->version = (JSVersion) (version & 0xffff);
+ script->nfixed = (uint16) (version >> 16);
+
+ /* If we know nsrcnotes, we allocated space for notes in script. */
+ notes = SCRIPT_NOTES(script);
+ *scriptp = script;
+ JS_PUSH_TEMP_ROOT_SCRIPT(cx, script, &tvr);
+ }
+
+ /*
+ * Control hereafter must goto error on failure, in order for the
+ * DECODE case to destroy script.
+ */
+ oldscript = xdr->script;
+ code = script->code;
+ if (xdr->mode == JSXDR_ENCODE) {
+ code = js_UntrapScriptCode(cx, script);
+ if (!code)
+ goto error;
+ }
+
+ xdr->script = script;
+ ok = JS_XDRBytes(xdr, (char *) code, length * sizeof(jsbytecode));
+
+ if (code != script->code)
+ JS_free(cx, code);
+
+ if (!ok)
+ goto error;
+
+ if (!JS_XDRBytes(xdr, (char *)notes, nsrcnotes * sizeof(jssrcnote)) ||
+ !JS_XDRCStringOrNull(xdr, (char **)&script->filename) ||
+ !JS_XDRUint32(xdr, &lineno) ||
+ !JS_XDRUint32(xdr, &nslots)) {
+ goto error;
+ }
+
+ callbacks = JS_GetSecurityCallbacks(cx);
+ if (xdr->mode == JSXDR_ENCODE) {
+ principals = script->principals;
+ encodeable = callbacks && callbacks->principalsTranscoder;
+ if (!JS_XDRUint32(xdr, &encodeable))
+ goto error;
+ if (encodeable &&
+ !callbacks->principalsTranscoder(xdr, &principals)) {
+ goto error;
+ }
+ } else {
+ if (!JS_XDRUint32(xdr, &encodeable))
+ goto error;
+ if (encodeable) {
+ if (!(callbacks && callbacks->principalsTranscoder)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_DECODE_PRINCIPALS);
+ goto error;
+ }
+ if (!callbacks->principalsTranscoder(xdr, &principals))
+ goto error;
+ script->principals = principals;
+ }
+ }
+
+ if (xdr->mode == JSXDR_DECODE) {
+ const char *filename = script->filename;
+ if (filename) {
+ filename = js_SaveScriptFilename(cx, filename);
+ if (!filename)
+ goto error;
+ JS_free(cx, (void *) script->filename);
+ script->filename = filename;
+ filenameWasSaved = JS_TRUE;
+ }
+ script->lineno = (uintN)lineno;
+ script->nslots = (uint16)nslots;
+ script->staticDepth = nslots >> 16;
+ }
+
+ for (i = 0; i != natoms; ++i) {
+ if (!js_XDRAtom(xdr, &script->atomMap.vector[i]))
+ goto error;
+ }
+
+ /*
+ * Here looping from 0-to-length to xdr objects is essential. It ensures
+ * that block objects from the script->objects array will be written and
+ * restored in the outer-to-inner order. block_xdrObject relies on this to
+ * restore the parent chain.
+ */
+ for (i = 0; i != nobjects; ++i) {
+ if (!js_XDRObject(xdr, &JS_SCRIPT_OBJECTS(script)->vector[i]))
+ goto error;
+ }
+ for (i = 0; i != nupvars; ++i) {
+ if (!JS_XDRUint32(xdr, &JS_SCRIPT_UPVARS(script)->vector[i]))
+ goto error;
+ }
+ for (i = 0; i != nregexps; ++i) {
+ if (!js_XDRObject(xdr, &JS_SCRIPT_REGEXPS(script)->vector[i]))
+ goto error;
+ }
+
+ if (ntrynotes != 0) {
+ /*
+ * We combine tn->kind and tn->stackDepth when serializing as XDR is not
+ * efficient when serializing small integer types.
+ */
+ JSTryNote *tn, *tnfirst;
+ uint32 kindAndDepth;
+ JS_STATIC_ASSERT(sizeof(tn->kind) == sizeof(uint8));
+ JS_STATIC_ASSERT(sizeof(tn->stackDepth) == sizeof(uint16));
+
+ tnfirst = JS_SCRIPT_TRYNOTES(script)->vector;
+ JS_ASSERT(JS_SCRIPT_TRYNOTES(script)->length == ntrynotes);
+ tn = tnfirst + ntrynotes;
+ do {
+ --tn;
+ if (xdr->mode == JSXDR_ENCODE) {
+ kindAndDepth = ((uint32)tn->kind << 16)
+ | (uint32)tn->stackDepth;
+ }
+ if (!JS_XDRUint32(xdr, &kindAndDepth) ||
+ !JS_XDRUint32(xdr, &tn->start) ||
+ !JS_XDRUint32(xdr, &tn->length)) {
+ goto error;
+ }
+ if (xdr->mode == JSXDR_DECODE) {
+ tn->kind = (uint8)(kindAndDepth >> 16);
+ tn->stackDepth = (uint16)kindAndDepth;
+ }
+ } while (tn != tnfirst);
+ }
+
+ xdr->script = oldscript;
+ if (xdr->mode == JSXDR_DECODE)
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return JS_TRUE;
+
+ error:
+ if (xdr->mode == JSXDR_DECODE) {
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (script->filename && !filenameWasSaved) {
+ JS_free(cx, (void *) script->filename);
+ script->filename = NULL;
+ }
+ js_DestroyScript(cx, script);
+ *scriptp = NULL;
+ }
+ xdr->script = oldscript;
+ return JS_FALSE;
+}
+
+#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
+/*
+ * These cannot be exposed to web content, and chrome does not need them, so
+ * we take them out of the Mozilla client altogether. Fortunately, there is
+ * no way to serialize a native function (see fun_xdrObject in jsfun.c).
+ */
+
+static JSBool
+script_freeze(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSXDRState *xdr;
+ JSScript *script;
+ JSBool ok, hasMagic;
+ uint32 len;
+ void *buf;
+ JSString *str;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (!script)
+ return JS_TRUE;
+
+ /* create new XDR */
+ xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
+ if (!xdr)
+ return JS_FALSE;
+
+ /* write */
+ ok = js_XDRScript(xdr, &script, &hasMagic);
+ if (!ok)
+ goto out;
+ if (!hasMagic) {
+ *vp = JSVAL_VOID;
+ goto out;
+ }
+
+ buf = JS_XDRMemGetData(xdr, &len);
+ if (!buf) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ JS_ASSERT((jsword)buf % sizeof(jschar) == 0);
+ len /= sizeof(jschar);
+#if IS_BIG_ENDIAN
+ {
+ jschar *chars;
+ uint32 i;
+
+ /* Swap bytes in Unichars to keep frozen strings machine-independent. */
+ chars = (jschar *)buf;
+ for (i = 0; i < len; i++)
+ chars[i] = JSXDR_SWAB16(chars[i]);
+ }
+#endif
+ str = JS_NewUCStringCopyN(cx, (jschar *)buf, len);
+ if (!str) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+
+out:
+ JS_XDRDestroy(xdr);
+ return ok;
+}
+
+static JSBool
+script_thaw(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSXDRState *xdr;
+ JSString *str;
+ void *buf;
+ uint32 len;
+ jsval v;
+ JSScript *script, *oldscript;
+ JSBool ok, hasMagic;
+ jsint execDepth;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_ScriptClass, vp + 2))
+ return JS_FALSE;
+
+ if (argc == 0)
+ return JS_TRUE;
+ str = js_ValueToString(cx, vp[2]);
+ if (!str)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str);
+
+ /* create new XDR */
+ xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
+ if (!xdr)
+ return JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, buf, len);
+#if IS_BIG_ENDIAN
+ {
+ jschar *from, *to;
+ uint32 i;
+
+ /* Swap bytes in Unichars to keep frozen strings machine-independent. */
+ from = (jschar *)buf;
+ to = (jschar *) JS_malloc(cx, len * sizeof(jschar));
+ if (!to) {
+ JS_XDRDestroy(xdr);
+ return JS_FALSE;
+ }
+ for (i = 0; i < len; i++)
+ to[i] = JSXDR_SWAB16(from[i]);
+ buf = (char *)to;
+ }
+#endif
+ len *= sizeof(jschar);
+ JS_XDRMemSetData(xdr, buf, len);
+
+ /* XXXbe should magic mismatch be error, or false return value? */
+ ok = js_XDRScript(xdr, &script, &hasMagic);
+ if (!ok)
+ goto out;
+ if (!hasMagic) {
+ *vp = JSVAL_FALSE;
+ goto out;
+ }
+
+ JS_LOCK_OBJ(cx, obj);
+ execDepth = GetScriptExecDepth(cx, obj);
+
+ /*
+ * execDepth must be 0 to allow compilation here, otherwise the JSScript
+ * struct can be released while running.
+ */
+ if (execDepth > 0) {
+ JS_UNLOCK_OBJ(cx, obj);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_COMPILE_EXECED_SCRIPT);
+ goto out;
+ }
+
+ /* Swap script for obj's old script, if any. */
+ v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
+ oldscript = !JSVAL_IS_VOID(v) ? JSVAL_TO_PRIVATE(v) : NULL;
+ LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
+ JS_UNLOCK_OBJ(cx, obj);
+
+ if (oldscript)
+ js_DestroyScript(cx, oldscript);
+
+ script->u.object = obj;
+ js_CallNewScriptHook(cx, script, NULL);
+
+out:
+ /*
+ * We reset the buffer to be NULL so that it doesn't free the chars
+ * memory owned by str (vp[2]).
+ */
+ JS_XDRMemSetData(xdr, NULL, 0);
+ JS_XDRDestroy(xdr);
+#if IS_BIG_ENDIAN
+ JS_free(cx, buf);
+#endif
+ *vp = JSVAL_TRUE;
+ return ok;
+}
+
+static const char js_thaw_str[] = "thaw";
+
+#endif /* JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW */
+#endif /* JS_HAS_XDR */
+
+#if JS_HAS_SCRIPT_OBJECT
+
+static JSFunctionSpec script_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, script_toSource, 0,0),
+#endif
+ JS_FN(js_toString_str, script_toString, 0,0),
+ JS_FN("compile", script_compile, 2,0),
+ JS_FN("exec", script_exec, 1,0),
+#if JS_HAS_XDR_FREEZE_THAW
+ JS_FN("freeze", script_freeze, 0,0),
+ JS_FN(js_thaw_str, script_thaw, 1,0),
+#endif /* JS_HAS_XDR_FREEZE_THAW */
+ JS_FS_END
+};
+
+#endif /* JS_HAS_SCRIPT_OBJECT */
+
+static void
+script_finalize(JSContext *cx, JSObject *obj)
+{
+ JSScript *script;
+
+ script = (JSScript *) JS_GetPrivate(cx, obj);
+ if (script)
+ js_DestroyScript(cx, script);
+}
+
+static JSBool
+script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+#if JS_HAS_SCRIPT_OBJECT
+ return script_exec_sub(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval);
+#else
+ return JS_FALSE;
+#endif
+}
+
+static void
+script_trace(JSTracer *trc, JSObject *obj)
+{
+ JSScript *script;
+
+ script = (JSScript *) JS_GetPrivate(trc->context, obj);
+ if (script)
+ js_TraceScript(trc, script);
+}
+
+#if !JS_HAS_SCRIPT_OBJECT
+#define JSProto_Script JSProto_Object
+#endif
+
+JS_FRIEND_DATA(JSClass) js_ScriptClass = {
+ js_Script_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(1) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Script),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
+ NULL, NULL, script_call, NULL,/*XXXbe xdr*/
+ NULL, NULL, JS_CLASS_TRACE(script_trace), NULL
+};
+
+#if JS_HAS_SCRIPT_OBJECT
+
+static JSBool
+Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ /* If not constructing, replace obj with a new Script object. */
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * script_compile_sub does not use rval to root its temporaries so we
+ * can use it to root obj.
+ */
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+
+ if (!JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(0)))
+ return JS_FALSE;
+
+ return script_compile_sub(cx, obj, argc, argv, rval);
+}
+
+#if JS_HAS_SCRIPT_OBJECT && JS_HAS_XDR_FREEZE_THAW
+
+static JSBool
+script_static_thaw(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_ScriptClass, NULL, NULL);
+ if (!obj)
+ return JS_FALSE;
+ vp[1] = OBJECT_TO_JSVAL(obj);
+ if (!script_thaw(cx, argc, vp))
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSFunctionSpec script_static_methods[] = {
+ JS_FN(js_thaw_str, script_static_thaw, 1,0),
+ JS_FS_END
+};
+
+#else /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
+
+#define script_static_methods NULL
+
+#endif /* !JS_HAS_SCRIPT_OBJECT || !JS_HAS_XDR_FREEZE_THAW */
+
+JSObject *
+js_InitScriptClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_ScriptClass, Script, 1,
+ NULL, script_methods, NULL, script_static_methods);
+}
+
+#endif /* JS_HAS_SCRIPT_OBJECT */
+
+/*
+ * Shared script filename management.
+ */
+static int
+js_compare_strings(const void *k1, const void *k2)
+{
+ return strcmp((const char *) k1, (const char *) k2) == 0;
+}
+
+/* NB: This struct overlays JSHashEntry -- see jshash.h, do not reorganize. */
+typedef struct ScriptFilenameEntry {
+ JSHashEntry *next; /* hash chain linkage */
+ JSHashNumber keyHash; /* key hash function result */
+ const void *key; /* ptr to filename, below */
+ uint32 flags; /* user-defined filename prefix flags */
+ JSPackedBool mark; /* GC mark flag */
+ char filename[3]; /* two or more bytes, NUL-terminated */
+} ScriptFilenameEntry;
+
+static void *
+js_alloc_table_space(void *priv, size_t size)
+{
+ return malloc(size);
+}
+
+static void
+js_free_table_space(void *priv, void *item)
+{
+ free(item);
+}
+
+static JSHashEntry *
+js_alloc_sftbl_entry(void *priv, const void *key)
+{
+ size_t nbytes = offsetof(ScriptFilenameEntry, filename) +
+ strlen((const char *) key) + 1;
+
+ return (JSHashEntry *) malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
+}
+
+static void
+js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag)
+{
+ if (flag != HT_FREE_ENTRY)
+ return;
+ free(he);
+}
+
+static JSHashAllocOps sftbl_alloc_ops = {
+ js_alloc_table_space, js_free_table_space,
+ js_alloc_sftbl_entry, js_free_sftbl_entry
+};
+
+JSBool
+js_InitRuntimeScriptState(JSRuntime *rt)
+{
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->scriptFilenameTableLock);
+ rt->scriptFilenameTableLock = JS_NEW_LOCK();
+ if (!rt->scriptFilenameTableLock)
+ return JS_FALSE;
+#endif
+ JS_ASSERT(!rt->scriptFilenameTable);
+ rt->scriptFilenameTable =
+ JS_NewHashTable(16, JS_HashString, js_compare_strings, NULL,
+ &sftbl_alloc_ops, NULL);
+ if (!rt->scriptFilenameTable) {
+ js_FinishRuntimeScriptState(rt); /* free lock if threadsafe */
+ return JS_FALSE;
+ }
+ JS_INIT_CLIST(&rt->scriptFilenamePrefixes);
+ return JS_TRUE;
+}
+
+typedef struct ScriptFilenamePrefix {
+ JSCList links; /* circular list linkage for easy deletion */
+ const char *name; /* pointer to pinned ScriptFilenameEntry string */
+ size_t length; /* prefix string length, precomputed */
+ uint32 flags; /* user-defined flags to inherit from this prefix */
+} ScriptFilenamePrefix;
+
+void
+js_FinishRuntimeScriptState(JSRuntime *rt)
+{
+ if (rt->scriptFilenameTable) {
+ JS_HashTableDestroy(rt->scriptFilenameTable);
+ rt->scriptFilenameTable = NULL;
+ }
+#ifdef JS_THREADSAFE
+ if (rt->scriptFilenameTableLock) {
+ JS_DESTROY_LOCK(rt->scriptFilenameTableLock);
+ rt->scriptFilenameTableLock = NULL;
+ }
+#endif
+}
+
+void
+js_FreeRuntimeScriptState(JSRuntime *rt)
+{
+ ScriptFilenamePrefix *sfp;
+
+ if (!rt->scriptFilenameTable)
+ return;
+
+ while (!JS_CLIST_IS_EMPTY(&rt->scriptFilenamePrefixes)) {
+ sfp = (ScriptFilenamePrefix *) rt->scriptFilenamePrefixes.next;
+ JS_REMOVE_LINK(&sfp->links);
+ free(sfp);
+ }
+ js_FinishRuntimeScriptState(rt);
+}
+
+#ifdef DEBUG_brendan
+#define DEBUG_SFTBL
+#endif
+#ifdef DEBUG_SFTBL
+size_t sftbl_savings = 0;
+#endif
+
+static ScriptFilenameEntry *
+SaveScriptFilename(JSRuntime *rt, const char *filename, uint32 flags)
+{
+ JSHashTable *table;
+ JSHashNumber hash;
+ JSHashEntry **hep;
+ ScriptFilenameEntry *sfe;
+ size_t length;
+ JSCList *head, *link;
+ ScriptFilenamePrefix *sfp;
+
+ table = rt->scriptFilenameTable;
+ hash = JS_HashString(filename);
+ hep = JS_HashTableRawLookup(table, hash, filename);
+ sfe = (ScriptFilenameEntry *) *hep;
+#ifdef DEBUG_SFTBL
+ if (sfe)
+ sftbl_savings += strlen(sfe->filename);
+#endif
+
+ if (!sfe) {
+ sfe = (ScriptFilenameEntry *)
+ JS_HashTableRawAdd(table, hep, hash, filename, NULL);
+ if (!sfe)
+ return NULL;
+ sfe->key = strcpy(sfe->filename, filename);
+ sfe->flags = 0;
+ sfe->mark = JS_FALSE;
+ }
+
+ /* If saving a prefix, add it to the set in rt->scriptFilenamePrefixes. */
+ if (flags != 0) {
+ /* Search in case filename was saved already; we must be idempotent. */
+ sfp = NULL;
+ length = strlen(filename);
+ for (head = link = &rt->scriptFilenamePrefixes;
+ link->next != head;
+ link = link->next) {
+ /* Lag link behind sfp to insert in non-increasing length order. */
+ sfp = (ScriptFilenamePrefix *) link->next;
+ if (!strcmp(sfp->name, filename))
+ break;
+ if (sfp->length <= length) {
+ sfp = NULL;
+ break;
+ }
+ sfp = NULL;
+ }
+
+ if (!sfp) {
+ /* No such prefix: add one now. */
+ sfp = (ScriptFilenamePrefix *) malloc(sizeof(ScriptFilenamePrefix));
+ if (!sfp)
+ return NULL;
+ JS_INSERT_AFTER(&sfp->links, link);
+ sfp->name = sfe->filename;
+ sfp->length = length;
+ sfp->flags = 0;
+ }
+
+ /*
+ * Accumulate flags in both sfe and sfp: sfe for later access from the
+ * JS_GetScriptedCallerFilenameFlags debug-API, and sfp so that longer
+ * filename entries can inherit by prefix.
+ */
+ sfe->flags |= flags;
+ sfp->flags |= flags;
+ }
+
+ return sfe;
+}
+
+const char *
+js_SaveScriptFilename(JSContext *cx, const char *filename)
+{
+ JSRuntime *rt;
+ ScriptFilenameEntry *sfe;
+ JSCList *head, *link;
+ ScriptFilenamePrefix *sfp;
+
+ rt = cx->runtime;
+ JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock);
+ sfe = SaveScriptFilename(rt, filename, 0);
+ if (!sfe) {
+ JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+
+ /*
+ * Try to inherit flags by prefix. We assume there won't be more than a
+ * few (dozen! ;-) prefixes, so linear search is tolerable.
+ * XXXbe every time I've assumed that in the JS engine, I've been wrong!
+ */
+ for (head = &rt->scriptFilenamePrefixes, link = head->next;
+ link != head;
+ link = link->next) {
+ sfp = (ScriptFilenamePrefix *) link;
+ if (!strncmp(sfp->name, filename, sfp->length)) {
+ sfe->flags |= sfp->flags;
+ break;
+ }
+ }
+ JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
+ return sfe->filename;
+}
+
+const char *
+js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags)
+{
+ ScriptFilenameEntry *sfe;
+
+ /* This may be called very early, via the jsdbgapi.h entry point. */
+ if (!rt->scriptFilenameTable && !js_InitRuntimeScriptState(rt))
+ return NULL;
+
+ JS_ACQUIRE_LOCK(rt->scriptFilenameTableLock);
+ sfe = SaveScriptFilename(rt, filename, flags);
+ JS_RELEASE_LOCK(rt->scriptFilenameTableLock);
+ if (!sfe)
+ return NULL;
+
+ return sfe->filename;
+}
+
+/*
+ * Back up from a saved filename by its offset within its hash table entry.
+ */
+#define FILENAME_TO_SFE(fn) \
+ ((ScriptFilenameEntry *) ((fn) - offsetof(ScriptFilenameEntry, filename)))
+
+/*
+ * The sfe->key member, redundant given sfe->filename but required by the old
+ * jshash.c code, here gives us a useful sanity check. This assertion will
+ * very likely botch if someone tries to mark a string that wasn't allocated
+ * as an sfe->filename.
+ */
+#define ASSERT_VALID_SFE(sfe) JS_ASSERT((sfe)->key == (sfe)->filename)
+
+uint32
+js_GetScriptFilenameFlags(const char *filename)
+{
+ ScriptFilenameEntry *sfe;
+
+ sfe = FILENAME_TO_SFE(filename);
+ ASSERT_VALID_SFE(sfe);
+ return sfe->flags;
+}
+
+void
+js_MarkScriptFilename(const char *filename)
+{
+ ScriptFilenameEntry *sfe;
+
+ sfe = FILENAME_TO_SFE(filename);
+ ASSERT_VALID_SFE(sfe);
+ sfe->mark = JS_TRUE;
+}
+
+static intN
+js_script_filename_marker(JSHashEntry *he, intN i, void *arg)
+{
+ ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;
+
+ sfe->mark = JS_TRUE;
+ return HT_ENUMERATE_NEXT;
+}
+
+void
+js_MarkScriptFilenames(JSRuntime *rt, JSBool keepAtoms)
+{
+ JSCList *head, *link;
+ ScriptFilenamePrefix *sfp;
+
+ if (!rt->scriptFilenameTable)
+ return;
+
+ if (keepAtoms) {
+ JS_HashTableEnumerateEntries(rt->scriptFilenameTable,
+ js_script_filename_marker,
+ rt);
+ }
+ for (head = &rt->scriptFilenamePrefixes, link = head->next;
+ link != head;
+ link = link->next) {
+ sfp = (ScriptFilenamePrefix *) link;
+ js_MarkScriptFilename(sfp->name);
+ }
+}
+
+static intN
+js_script_filename_sweeper(JSHashEntry *he, intN i, void *arg)
+{
+ ScriptFilenameEntry *sfe = (ScriptFilenameEntry *) he;
+
+ if (!sfe->mark)
+ return HT_ENUMERATE_REMOVE;
+ sfe->mark = JS_FALSE;
+ return HT_ENUMERATE_NEXT;
+}
+
+void
+js_SweepScriptFilenames(JSRuntime *rt)
+{
+ if (!rt->scriptFilenameTable)
+ return;
+
+ JS_HashTableEnumerateEntries(rt->scriptFilenameTable,
+ js_script_filename_sweeper,
+ rt);
+#ifdef DEBUG_notme
+#ifdef DEBUG_SFTBL
+ printf("script filename table savings so far: %u\n", sftbl_savings);
+#endif
+#endif
+}
+
+/*
+ * JSScript data structures memory alignment:
+ *
+ * JSScript
+ * JSObjectArray script objects' descriptor if JSScript.objectsOffset != 0,
+ * use JS_SCRIPT_OBJECTS(script) macro to access it.
+ * JSObjectArray script regexps' descriptor if JSScript.regexpsOffset != 0,
+ * use JS_SCRIPT_REGEXPS(script) macro to access it.
+ * JSTryNoteArray script try notes' descriptor if JSScript.tryNotesOffset
+ * != 0, use JS_SCRIPT_TRYNOTES(script) macro to access it.
+ * JSAtom *a[] array of JSScript.atomMap.length atoms pointed by
+ * JSScript.atomMap.vector if any.
+ * JSObject *o[] array of JS_SCRIPT_OBJECTS(script)->length objects if any
+ * pointed by JS_SCRIPT_OBJECTS(script)->vector.
+ * JSObject *r[] array of JS_SCRIPT_REGEXPS(script)->length regexps if any
+ * pointed by JS_SCRIPT_REGEXPS(script)->vector.
+ * JSTryNote t[] array of JS_SCRIPT_TRYNOTES(script)->length try notes if any
+ * pointed by JS_SCRIPT_TRYNOTES(script)->vector.
+ * jsbytecode b[] script bytecode pointed by JSScript.code.
+ * jssrcnote s[] script source notes, use SCRIPT_NOTES(script) to access it
+ *
+ * The alignment avoids gaps between entries as alignment requirement for each
+ * subsequent structure or array is the same or divides the alignment
+ * requirement for the previous one.
+ *
+ * The followings asserts checks that assuming that the alignment requirement
+ * for JSObjectArray and JSTryNoteArray are sizeof(void *) and for JSTryNote
+ * it is sizeof(uint32) as the structure consists of 3 uint32 fields.
+ */
+JS_STATIC_ASSERT(sizeof(JSScript) % sizeof(void *) == 0);
+JS_STATIC_ASSERT(sizeof(JSObjectArray) % sizeof(void *) == 0);
+JS_STATIC_ASSERT(sizeof(JSTryNoteArray) == sizeof(JSObjectArray));
+JS_STATIC_ASSERT(sizeof(JSAtom *) == sizeof(JSObject *));
+JS_STATIC_ASSERT(sizeof(JSObject *) % sizeof(uint32) == 0);
+JS_STATIC_ASSERT(sizeof(JSTryNote) == 3 * sizeof(uint32));
+JS_STATIC_ASSERT(sizeof(uint32) % sizeof(jsbytecode) == 0);
+JS_STATIC_ASSERT(sizeof(jsbytecode) % sizeof(jssrcnote) == 0);
+
+/*
+ * Check that uint8 offset for object, upvar, regexp, and try note arrays is
+ * sufficient.
+ */
+JS_STATIC_ASSERT(sizeof(JSScript) + 2 * sizeof(JSObjectArray) +
+ sizeof(JSUpvarArray) < JS_BIT(8));
+
+JSScript *
+js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
+ uint32 nobjects, uint32 nupvars, uint32 nregexps,
+ uint32 ntrynotes)
+{
+ size_t size, vectorSize;
+ JSScript *script;
+ uint8 *cursor;
+
+ size = sizeof(JSScript) +
+ sizeof(JSAtom *) * natoms +
+ length * sizeof(jsbytecode) +
+ nsrcnotes * sizeof(jssrcnote);
+ if (nobjects != 0)
+ size += sizeof(JSObjectArray) + nobjects * sizeof(JSObject *);
+ if (nupvars != 0)
+ size += sizeof(JSUpvarArray) + nupvars * sizeof(uint32);
+ if (nregexps != 0)
+ size += sizeof(JSObjectArray) + nregexps * sizeof(JSObject *);
+ if (ntrynotes != 0)
+ size += sizeof(JSTryNoteArray) + ntrynotes * sizeof(JSTryNote);
+
+ script = (JSScript *) JS_malloc(cx, size);
+ if (!script)
+ return NULL;
+ memset(script, 0, sizeof(JSScript));
+ script->length = length;
+ script->version = cx->version;
+
+ cursor = (uint8 *)script + sizeof(JSScript);
+ if (nobjects != 0) {
+ script->objectsOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSObjectArray);
+ }
+ if (nupvars != 0) {
+ script->upvarsOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSUpvarArray);
+ }
+ if (nregexps != 0) {
+ script->regexpsOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSObjectArray);
+ }
+ if (ntrynotes != 0) {
+ script->trynotesOffset = (uint8)(cursor - (uint8 *)script);
+ cursor += sizeof(JSTryNoteArray);
+ }
+
+ if (natoms != 0) {
+ script->atomMap.length = natoms;
+ script->atomMap.vector = (JSAtom **)cursor;
+ vectorSize = natoms * sizeof(script->atomMap.vector[0]);
+
+ /*
+ * Clear object map's vector so the GC tracing can run when not yet
+ * all atoms are copied to the array.
+ */
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (nobjects != 0) {
+ JS_SCRIPT_OBJECTS(script)->length = nobjects;
+ JS_SCRIPT_OBJECTS(script)->vector = (JSObject **)cursor;
+ vectorSize = nobjects * sizeof(JS_SCRIPT_OBJECTS(script)->vector[0]);
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (nupvars != 0) {
+ JS_SCRIPT_UPVARS(script)->length = nupvars;
+ JS_SCRIPT_UPVARS(script)->vector = (uint32 *)cursor;
+ vectorSize = nupvars * sizeof(JS_SCRIPT_UPVARS(script)->vector[0]);
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (nregexps != 0) {
+ JS_SCRIPT_REGEXPS(script)->length = nregexps;
+ JS_SCRIPT_REGEXPS(script)->vector = (JSObject **)cursor;
+ vectorSize = nregexps * sizeof(JS_SCRIPT_REGEXPS(script)->vector[0]);
+ memset(cursor, 0, vectorSize);
+ cursor += vectorSize;
+ }
+
+ if (ntrynotes != 0) {
+ JS_SCRIPT_TRYNOTES(script)->length = ntrynotes;
+ JS_SCRIPT_TRYNOTES(script)->vector = (JSTryNote *)cursor;
+ vectorSize = ntrynotes * sizeof(JS_SCRIPT_TRYNOTES(script)->vector[0]);
+#ifdef DEBUG
+ memset(cursor, 0, vectorSize);
+#endif
+ cursor += vectorSize;
+ }
+
+ script->code = script->main = (jsbytecode *)cursor;
+ JS_ASSERT(cursor +
+ length * sizeof(jsbytecode) +
+ nsrcnotes * sizeof(jssrcnote) ==
+ (uint8 *)script + size);
+
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = cx->thread;
+#endif
+ return script;
+}
+
+JSScript *
+js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg)
+{
+ uint32 mainLength, prologLength, nsrcnotes, nfixed;
+ JSScript *script;
+ const char *filename;
+ JSFunction *fun;
+
+ /* The counts of indexed things must be checked during code generation. */
+ JS_ASSERT(cg->atomList.count <= INDEX_LIMIT);
+ JS_ASSERT(cg->objectList.length <= INDEX_LIMIT);
+ JS_ASSERT(cg->regexpList.length <= INDEX_LIMIT);
+
+ mainLength = CG_OFFSET(cg);
+ prologLength = CG_PROLOG_OFFSET(cg);
+ CG_COUNT_FINAL_SRCNOTES(cg, nsrcnotes);
+ script = js_NewScript(cx, prologLength + mainLength, nsrcnotes,
+ cg->atomList.count, cg->objectList.length,
+ cg->upvarList.count, cg->regexpList.length,
+ cg->ntrynotes);
+ if (!script)
+ return NULL;
+
+ /* Now that we have script, error control flow must go to label bad. */
+ script->main += prologLength;
+ memcpy(script->code, CG_PROLOG_BASE(cg), prologLength * sizeof(jsbytecode));
+ memcpy(script->main, CG_BASE(cg), mainLength * sizeof(jsbytecode));
+ nfixed = (cg->treeContext.flags & TCF_IN_FUNCTION)
+ ? cg->treeContext.u.fun->u.i.nvars
+ : cg->treeContext.ngvars + cg->regexpList.length;
+ JS_ASSERT(nfixed < SLOTNO_LIMIT);
+ script->nfixed = (uint16) nfixed;
+ js_InitAtomMap(cx, &script->atomMap, &cg->atomList);
+
+ filename = cg->treeContext.parseContext->tokenStream.filename;
+ if (filename) {
+ script->filename = js_SaveScriptFilename(cx, filename);
+ if (!script->filename)
+ goto bad;
+ }
+ script->lineno = cg->firstLine;
+ if (script->nfixed + cg->maxStackDepth >= JS_BIT(16)) {
+ js_ReportCompileErrorNumber(cx, CG_TS(cg), NULL, JSREPORT_ERROR,
+ JSMSG_NEED_DIET, "script");
+ goto bad;
+ }
+ script->nslots = script->nfixed + cg->maxStackDepth;
+ script->staticDepth = cg->staticDepth;
+ script->principals = cg->treeContext.parseContext->principals;
+ if (script->principals)
+ JSPRINCIPALS_HOLD(cx, script->principals);
+
+ if (!js_FinishTakingSrcNotes(cx, cg, SCRIPT_NOTES(script)))
+ goto bad;
+ if (cg->ntrynotes != 0)
+ js_FinishTakingTryNotes(cg, JS_SCRIPT_TRYNOTES(script));
+ if (cg->objectList.length != 0)
+ FinishParsedObjects(&cg->objectList, JS_SCRIPT_OBJECTS(script));
+ if (cg->regexpList.length != 0)
+ FinishParsedObjects(&cg->regexpList, JS_SCRIPT_REGEXPS(script));
+ if (cg->treeContext.flags & TCF_NO_SCRIPT_RVAL)
+ script->flags |= JSSF_NO_SCRIPT_RVAL;
+
+ if (cg->upvarList.count != 0) {
+ JS_ASSERT(cg->upvarList.count <= cg->upvarMap.length);
+ memcpy(JS_SCRIPT_UPVARS(script)->vector, cg->upvarMap.vector,
+ cg->upvarList.count * sizeof(uint32));
+ ATOM_LIST_INIT(&cg->upvarList);
+ JS_free(cx, cg->upvarMap.vector);
+ cg->upvarMap.vector = NULL;
+ }
+
+ /*
+ * We initialize fun->u.script to be the script constructed above
+ * so that the debugger has a valid FUN_SCRIPT(fun).
+ */
+ fun = NULL;
+ if (cg->treeContext.flags & TCF_IN_FUNCTION) {
+ fun = cg->treeContext.u.fun;
+ JS_ASSERT(FUN_INTERPRETED(fun) && !FUN_SCRIPT(fun));
+ JS_ASSERT_IF(script->upvarsOffset != 0,
+ JS_SCRIPT_UPVARS(script)->length == fun->u.i.nupvars);
+
+ js_FreezeLocalNames(cx, fun);
+ fun->u.i.script = script;
+#ifdef CHECK_SCRIPT_OWNER
+ script->owner = NULL;
+#endif
+ if (cg->treeContext.flags & TCF_FUN_HEAVYWEIGHT)
+ fun->flags |= JSFUN_HEAVYWEIGHT;
+ }
+
+ /* Tell the debugger about this compiled script. */
+ js_CallNewScriptHook(cx, script, fun);
+ return script;
+
+bad:
+ js_DestroyScript(cx, script);
+ return NULL;
+}
+
+JS_FRIEND_API(void)
+js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun)
+{
+ JSNewScriptHook hook;
+
+ hook = cx->debugHooks->newScriptHook;
+ if (hook) {
+ JS_KEEP_ATOMS(cx->runtime);
+ hook(cx, script->filename, script->lineno, script, fun,
+ cx->debugHooks->newScriptHookData);
+ JS_UNKEEP_ATOMS(cx->runtime);
+ }
+}
+
+JS_FRIEND_API(void)
+js_CallDestroyScriptHook(JSContext *cx, JSScript *script)
+{
+ JSDestroyScriptHook hook;
+
+ hook = cx->debugHooks->destroyScriptHook;
+ if (hook)
+ hook(cx, script, cx->debugHooks->destroyScriptHookData);
+}
+
+void
+js_DestroyScript(JSContext *cx, JSScript *script)
+{
+ js_CallDestroyScriptHook(cx, script);
+ JS_ClearScriptTraps(cx, script);
+
+ if (script->principals)
+ JSPRINCIPALS_DROP(cx, script->principals);
+
+ if (JS_GSN_CACHE(cx).code == script->code)
+ JS_CLEAR_GSN_CACHE(cx);
+
+ /*
+ * The GC flushes all property caches, so no need to purge just the
+ * entries for this script.
+ *
+ * JS_THREADSAFE note: js_FlushPropertyCacheForScript flushes only the
+ * current thread's property cache, so a script not owned by a function
+ * or object, which hands off lifetime management for that script to the
+ * GC, must be used by only one thread over its lifetime.
+ *
+ * This should be an API-compatible change, since a script is never safe
+ * against premature GC if shared among threads without a rooted object
+ * wrapping it to protect the script's mapped atoms against GC. We use
+ * script->owner to enforce this requirement via assertions.
+ */
+#ifdef CHECK_SCRIPT_OWNER
+ JS_ASSERT_IF(cx->runtime->gcRunning, !script->owner);
+#endif
+
+ if (!cx->runtime->gcRunning) {
+ if (!(cx->fp && (cx->fp->flags & JSFRAME_EVAL))) {
+#ifdef CHECK_SCRIPT_OWNER
+ JS_ASSERT(script->owner == cx->thread);
+#endif
+ js_FlushPropertyCacheForScript(cx, script);
+ }
+ }
+
+ JS_free(cx, script);
+}
+
+void
+js_TraceScript(JSTracer *trc, JSScript *script)
+{
+ JSAtomMap *map;
+ uintN i, length;
+ JSAtom **vector;
+ jsval v;
+ JSObjectArray *objarray;
+
+ map = &script->atomMap;
+ length = map->length;
+ vector = map->vector;
+ for (i = 0; i < length; i++) {
+ v = ATOM_KEY(vector[i]);
+ if (JSVAL_IS_TRACEABLE(v)) {
+ JS_SET_TRACING_INDEX(trc, "atomMap", i);
+ JS_CallTracer(trc, JSVAL_TO_TRACEABLE(v), JSVAL_TRACE_KIND(v));
+ }
+ }
+
+ if (script->objectsOffset != 0) {
+ objarray = JS_SCRIPT_OBJECTS(script);
+ i = objarray->length;
+ do {
+ --i;
+ if (objarray->vector[i]) {
+ JS_SET_TRACING_INDEX(trc, "objects", i);
+ JS_CallTracer(trc, objarray->vector[i], JSTRACE_OBJECT);
+ }
+ } while (i != 0);
+ }
+
+ if (script->regexpsOffset != 0) {
+ objarray = JS_SCRIPT_REGEXPS(script);
+ i = objarray->length;
+ do {
+ --i;
+ if (objarray->vector[i]) {
+ JS_SET_TRACING_INDEX(trc, "regexps", i);
+ JS_CallTracer(trc, objarray->vector[i], JSTRACE_OBJECT);
+ }
+ } while (i != 0);
+ }
+
+ if (script->u.object) {
+ JS_SET_TRACING_NAME(trc, "object");
+ JS_CallTracer(trc, script->u.object, JSTRACE_OBJECT);
+ }
+
+ if (IS_GC_MARKING_TRACER(trc) && script->filename)
+ js_MarkScriptFilename(script->filename);
+}
+
+typedef struct GSNCacheEntry {
+ JSDHashEntryHdr hdr;
+ jsbytecode *pc;
+ jssrcnote *sn;
+} GSNCacheEntry;
+
+#define GSN_CACHE_THRESHOLD 100
+
+jssrcnote *
+js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ ptrdiff_t target, offset;
+ GSNCacheEntry *entry;
+ jssrcnote *sn, *result;
+ uintN nsrcnotes;
+
+
+ target = PTRDIFF(pc, script->code, jsbytecode);
+ if ((uint32)target >= script->length)
+ return NULL;
+
+ if (JS_GSN_CACHE(cx).code == script->code) {
+ JS_METER_GSN_CACHE(cx, hits);
+ entry = (GSNCacheEntry *)
+ JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
+ JS_DHASH_LOOKUP);
+ return entry->sn;
+ }
+
+ JS_METER_GSN_CACHE(cx, misses);
+ offset = 0;
+ for (sn = SCRIPT_NOTES(script); ; sn = SN_NEXT(sn)) {
+ if (SN_IS_TERMINATOR(sn)) {
+ result = NULL;
+ break;
+ }
+ offset += SN_DELTA(sn);
+ if (offset == target && SN_IS_GETTABLE(sn)) {
+ result = sn;
+ break;
+ }
+ }
+
+ if (JS_GSN_CACHE(cx).code != script->code &&
+ script->length >= GSN_CACHE_THRESHOLD) {
+ JS_CLEAR_GSN_CACHE(cx);
+ nsrcnotes = 0;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
+ sn = SN_NEXT(sn)) {
+ if (SN_IS_GETTABLE(sn))
+ ++nsrcnotes;
+ }
+ if (!JS_DHashTableInit(&JS_GSN_CACHE(cx).table, JS_DHashGetStubOps(),
+ NULL, sizeof(GSNCacheEntry),
+ JS_DHASH_DEFAULT_CAPACITY(nsrcnotes))) {
+ JS_GSN_CACHE(cx).table.ops = NULL;
+ } else {
+ pc = script->code;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn);
+ sn = SN_NEXT(sn)) {
+ pc += SN_DELTA(sn);
+ if (SN_IS_GETTABLE(sn)) {
+ entry = (GSNCacheEntry *)
+ JS_DHashTableOperate(&JS_GSN_CACHE(cx).table, pc,
+ JS_DHASH_ADD);
+ entry->pc = pc;
+ entry->sn = sn;
+ }
+ }
+ JS_GSN_CACHE(cx).code = script->code;
+ JS_METER_GSN_CACHE(cx, fills);
+ }
+ }
+
+ return result;
+}
+
+uintN
+js_FramePCToLineNumber(JSContext *cx, JSStackFrame *fp)
+{
+ return js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : fp->regs->pc);
+}
+
+uintN
+js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
+{
+ JSFunction *fun;
+ uintN lineno;
+ ptrdiff_t offset, target;
+ jssrcnote *sn;
+ JSSrcNoteType type;
+
+ /* Cope with JSStackFrame.pc value prior to entering js_Interpret. */
+ if (!pc)
+ return 0;
+
+ /*
+ * Special case: function definition needs no line number note because
+ * the function's script contains its starting line number.
+ */
+ if (js_CodeSpec[*pc].format & JOF_INDEXBASE)
+ pc += js_CodeSpec[*pc].length;
+ if (*pc == JSOP_DEFFUN) {
+ GET_FUNCTION_FROM_BYTECODE(script, pc, 0, fun);
+ return fun->u.i.script->lineno;
+ }
+
+ /*
+ * General case: walk through source notes accumulating their deltas,
+ * keeping track of line-number notes, until we pass the note for pc's
+ * offset within script->code.
+ */
+ lineno = script->lineno;
+ offset = 0;
+ target = PTRDIFF(pc, script->code, jsbytecode);
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ offset += SN_DELTA(sn);
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ if (type == SRC_SETLINE) {
+ if (offset <= target)
+ lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
+ } else if (type == SRC_NEWLINE) {
+ if (offset <= target)
+ lineno++;
+ }
+ if (offset > target)
+ break;
+ }
+ return lineno;
+}
+
+/* The line number limit is the same as the jssrcnote offset limit. */
+#define SN_LINE_LIMIT (SN_3BYTE_OFFSET_FLAG << 16)
+
+jsbytecode *
+js_LineNumberToPC(JSScript *script, uintN target)
+{
+ ptrdiff_t offset, best;
+ uintN lineno, bestdiff, diff;
+ jssrcnote *sn;
+ JSSrcNoteType type;
+
+ offset = 0;
+ best = -1;
+ lineno = script->lineno;
+ bestdiff = SN_LINE_LIMIT;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ /*
+ * Exact-match only if offset is not in the prolog; otherwise use
+ * nearest greater-or-equal line number match.
+ */
+ if (lineno == target && script->code + offset >= script->main)
+ goto out;
+ if (lineno >= target) {
+ diff = lineno - target;
+ if (diff < bestdiff) {
+ bestdiff = diff;
+ best = offset;
+ }
+ }
+ offset += SN_DELTA(sn);
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ if (type == SRC_SETLINE) {
+ lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
+ } else if (type == SRC_NEWLINE) {
+ lineno++;
+ }
+ }
+ if (best >= 0)
+ offset = best;
+out:
+ return script->code + offset;
+}
+
+JS_FRIEND_API(uintN)
+js_GetScriptLineExtent(JSScript *script)
+{
+ uintN lineno;
+ jssrcnote *sn;
+ JSSrcNoteType type;
+
+ lineno = script->lineno;
+ for (sn = SCRIPT_NOTES(script); !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
+ type = (JSSrcNoteType) SN_TYPE(sn);
+ if (type == SRC_SETLINE) {
+ lineno = (uintN) js_GetSrcNoteOffset(sn, 0);
+ } else if (type == SRC_NEWLINE) {
+ lineno++;
+ }
+ }
+ return 1 + lineno - script->lineno;
+}
+
+#if JS_HAS_GENERATORS
+
+JSBool
+js_IsInsideTryWithFinally(JSScript *script, jsbytecode *pc)
+{
+ JSTryNoteArray *tarray;
+ JSTryNote *tn, *tnlimit;
+ uint32 off;
+
+ JS_ASSERT(script->code <= pc);
+ JS_ASSERT(pc < script->code + script->length);
+
+ if (!script->trynotesOffset != 0)
+ return JS_FALSE;
+ tarray = JS_SCRIPT_TRYNOTES(script);
+ JS_ASSERT(tarray->length != 0);
+
+ tn = tarray->vector;
+ tnlimit = tn + tarray->length;
+ off = (uint32)(pc - script->main);
+ do {
+ if (off - tn->start < tn->length) {
+ if (tn->kind == JSTRY_FINALLY)
+ return JS_TRUE;
+ JS_ASSERT(tn->kind == JSTRY_CATCH);
+ }
+ } while (++tn != tnlimit);
+ return JS_FALSE;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsscript.h b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.h
new file mode 100644
index 0000000..00f7ca7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsscript.h
@@ -0,0 +1,330 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=79 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsscript_h___
+#define jsscript_h___
+/*
+ * JS script descriptor.
+ */
+#include "jsatom.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Type of try note associated with each catch or finally block, and also with
+ * for-in loops.
+ */
+typedef enum JSTryNoteKind {
+ JSTRY_CATCH,
+ JSTRY_FINALLY,
+ JSTRY_ITER
+} JSTryNoteKind;
+
+/*
+ * Exception handling record.
+ */
+struct JSTryNote {
+ uint8 kind; /* one of JSTryNoteKind */
+ uint8 padding; /* explicit padding on uint16 boundary */
+ uint16 stackDepth; /* stack depth upon exception handler entry */
+ uint32 start; /* start of the try statement or for-in loop
+ relative to script->main */
+ uint32 length; /* length of the try statement or for-in loop */
+};
+
+typedef struct JSTryNoteArray {
+ JSTryNote *vector; /* array of indexed try notes */
+ uint32 length; /* count of indexed try notes */
+} JSTryNoteArray;
+
+typedef struct JSObjectArray {
+ JSObject **vector; /* array of indexed objects */
+ uint32 length; /* count of indexed objects */
+} JSObjectArray;
+
+typedef struct JSUpvarArray {
+ uint32 *vector; /* array of indexed upvar cookies */
+ uint32 length; /* count of indexed upvar cookies */
+} JSUpvarArray;
+
+#define MAKE_UPVAR_COOKIE(skip,slot) ((skip) << 16 | (slot))
+#define UPVAR_FRAME_SKIP(cookie) ((uint32)(cookie) >> 16)
+#define UPVAR_FRAME_SLOT(cookie) ((uint16)(cookie))
+
+#define JS_OBJECT_ARRAY_SIZE(length) \
+ (offsetof(JSObjectArray, vector) + sizeof(JSObject *) * (length))
+
+#if defined DEBUG && defined JS_THREADSAFE
+# define CHECK_SCRIPT_OWNER 1
+#endif
+
+struct JSScript {
+ jsbytecode *code; /* bytecodes and their immediate operands */
+ uint32 length; /* length of code vector */
+ uint16 version; /* JS version under which script was compiled */
+ uint16 nfixed; /* number of slots besides stack operands in
+ slot array */
+ uint8 objectsOffset; /* offset to the array of nested function,
+ block, scope, xml and one-time regexps
+ objects or 0 if none */
+ uint8 upvarsOffset; /* offset of the array of display ("up")
+ closure vars or 0 if none */
+ uint8 regexpsOffset; /* offset to the array of to-be-cloned
+ regexps or 0 if none. */
+ uint8 trynotesOffset; /* offset to the array of try notes or
+ 0 if none */
+ uint8 flags; /* see below */
+ jsbytecode *main; /* main entry point, after predef'ing prolog */
+ JSAtomMap atomMap; /* maps immediate index to literal struct */
+ const char *filename; /* source filename or null */
+ uint32 lineno; /* base line number of script */
+ uint16 nslots; /* vars plus maximum stack depth */
+ uint16 staticDepth;/* static depth for display maintenance */
+ JSPrincipals *principals;/* principals for this script */
+ union {
+ JSObject *object; /* optional Script-class object wrapper */
+ JSScript *nextToGC; /* next to GC in rt->scriptsToGC list */
+ } u;
+#ifdef CHECK_SCRIPT_OWNER
+ JSThread *owner; /* for thread-safe life-cycle assertions */
+#endif
+};
+
+#define JSSF_NO_SCRIPT_RVAL 0x01 /* no need for result value of last
+ expression statement */
+
+static JS_INLINE uintN
+StackDepth(JSScript *script)
+{
+ return script->nslots - script->nfixed;
+}
+
+/* No need to store script->notes now that it is allocated right after code. */
+#define SCRIPT_NOTES(script) ((jssrcnote*)((script)->code+(script)->length))
+
+#define JS_SCRIPT_OBJECTS(script) \
+ (JS_ASSERT((script)->objectsOffset != 0), \
+ (JSObjectArray *)((uint8 *)(script) + (script)->objectsOffset))
+
+#define JS_SCRIPT_UPVARS(script) \
+ (JS_ASSERT((script)->upvarsOffset != 0), \
+ (JSUpvarArray *)((uint8 *)(script) + (script)->upvarsOffset))
+
+#define JS_SCRIPT_REGEXPS(script) \
+ (JS_ASSERT((script)->regexpsOffset != 0), \
+ (JSObjectArray *)((uint8 *)(script) + (script)->regexpsOffset))
+
+#define JS_SCRIPT_TRYNOTES(script) \
+ (JS_ASSERT((script)->trynotesOffset != 0), \
+ (JSTryNoteArray *)((uint8 *)(script) + (script)->trynotesOffset))
+
+#define JS_GET_SCRIPT_ATOM(script_, index, atom) \
+ JS_BEGIN_MACRO \
+ if (cx->fp && cx->fp->imacpc && cx->fp->script == script_) { \
+ JS_ASSERT((size_t)(index) < js_common_atom_count); \
+ (atom) = COMMON_ATOMS_START(&cx->runtime->atomState)[index]; \
+ } else { \
+ JSAtomMap *atoms_ = &(script_)->atomMap; \
+ JS_ASSERT((uint32)(index) < atoms_->length); \
+ (atom) = atoms_->vector[index]; \
+ } \
+ JS_END_MACRO
+
+#define JS_GET_SCRIPT_OBJECT(script, index, obj) \
+ JS_BEGIN_MACRO \
+ JSObjectArray *objects_ = JS_SCRIPT_OBJECTS(script); \
+ JS_ASSERT((uint32)(index) < objects_->length); \
+ (obj) = objects_->vector[index]; \
+ JS_END_MACRO
+
+#define JS_GET_SCRIPT_FUNCTION(script, index, fun) \
+ JS_BEGIN_MACRO \
+ JSObject *funobj_; \
+ \
+ JS_GET_SCRIPT_OBJECT(script, index, funobj_); \
+ JS_ASSERT(HAS_FUNCTION_CLASS(funobj_)); \
+ JS_ASSERT(funobj_ == (JSObject *) STOBJ_GET_PRIVATE(funobj_)); \
+ (fun) = (JSFunction *) funobj_; \
+ JS_ASSERT(FUN_INTERPRETED(fun)); \
+ JS_END_MACRO
+
+#define JS_GET_SCRIPT_REGEXP(script, index, obj) \
+ JS_BEGIN_MACRO \
+ JSObjectArray *regexps_ = JS_SCRIPT_REGEXPS(script); \
+ JS_ASSERT((uint32)(index) < regexps_->length); \
+ (obj) = regexps_->vector[index]; \
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_RegExpClass); \
+ JS_END_MACRO
+
+/*
+ * Check if pc is inside a try block that has finally code. GC calls this to
+ * check if it is necessary to schedule generator.close() invocation for an
+ * unreachable generator.
+ */
+JSBool
+js_IsInsideTryWithFinally(JSScript *script, jsbytecode *pc);
+
+extern JS_FRIEND_DATA(JSClass) js_ScriptClass;
+
+extern JSObject *
+js_InitScriptClass(JSContext *cx, JSObject *obj);
+
+/*
+ * On first new context in rt, initialize script runtime state, specifically
+ * the script filename table and its lock.
+ */
+extern JSBool
+js_InitRuntimeScriptState(JSRuntime *rt);
+
+/*
+ * On last context destroy for rt, if script filenames are all GC'd, free the
+ * script filename table and its lock.
+ */
+extern void
+js_FinishRuntimeScriptState(JSRuntime *rt);
+
+/*
+ * On JS_DestroyRuntime(rt), forcibly free script filename prefixes and any
+ * script filename table entries that have not been GC'd, the latter using
+ * js_FinishRuntimeScriptState.
+ *
+ * This allows script filename prefixes to outlive any context in rt.
+ */
+extern void
+js_FreeRuntimeScriptState(JSRuntime *rt);
+
+extern const char *
+js_SaveScriptFilename(JSContext *cx, const char *filename);
+
+extern const char *
+js_SaveScriptFilenameRT(JSRuntime *rt, const char *filename, uint32 flags);
+
+extern uint32
+js_GetScriptFilenameFlags(const char *filename);
+
+extern void
+js_MarkScriptFilename(const char *filename);
+
+extern void
+js_MarkScriptFilenames(JSRuntime *rt, JSBool keepAtoms);
+
+extern void
+js_SweepScriptFilenames(JSRuntime *rt);
+
+/*
+ * Two successively less primitive ways to make a new JSScript. The first
+ * does *not* call a non-null cx->runtime->newScriptHook -- only the second,
+ * js_NewScriptFromCG, calls this optional debugger hook.
+ *
+ * The js_NewScript function can't know whether the script it creates belongs
+ * to a function, or is top-level or eval code, but the debugger wants access
+ * to the newly made script's function, if any -- so callers of js_NewScript
+ * are responsible for notifying the debugger after successfully creating any
+ * kind (function or other) of new JSScript.
+ */
+extern JSScript *
+js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
+ uint32 nobjects, uint32 nupvars, uint32 nregexps,
+ uint32 ntrynotes);
+
+extern JSScript *
+js_NewScriptFromCG(JSContext *cx, JSCodeGenerator *cg);
+
+/*
+ * New-script-hook calling is factored from js_NewScriptFromCG so that it
+ * and callers of js_XDRScript can share this code. In the case of callers
+ * of js_XDRScript, the hook should be invoked only after successful decode
+ * of any owning function (the fun parameter) or script object (null fun).
+ */
+extern JS_FRIEND_API(void)
+js_CallNewScriptHook(JSContext *cx, JSScript *script, JSFunction *fun);
+
+extern JS_FRIEND_API(void)
+js_CallDestroyScriptHook(JSContext *cx, JSScript *script);
+
+extern void
+js_DestroyScript(JSContext *cx, JSScript *script);
+
+extern void
+js_TraceScript(JSTracer *trc, JSScript *script);
+
+/*
+ * To perturb as little code as possible, we introduce a js_GetSrcNote lookup
+ * cache without adding an explicit cx parameter. Thus js_GetSrcNote becomes
+ * a macro that uses cx from its calls' lexical environments.
+ */
+#define js_GetSrcNote(script,pc) js_GetSrcNoteCached(cx, script, pc)
+
+extern jssrcnote *
+js_GetSrcNoteCached(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+/*
+ * NOTE: use js_FramePCToLineNumber(cx, fp) when you have an active fp, in
+ * preference to js_PCToLineNumber (cx, fp->script fp->regs->pc), because
+ * fp->imacpc may be non-null, indicating an active imacro.
+ */
+extern uintN
+js_FramePCToLineNumber(JSContext *cx, JSStackFrame *fp);
+
+extern uintN
+js_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
+
+extern jsbytecode *
+js_LineNumberToPC(JSScript *script, uintN lineno);
+
+extern JS_FRIEND_API(uintN)
+js_GetScriptLineExtent(JSScript *script);
+
+/*
+ * If magic is non-null, js_XDRScript succeeds on magic number mismatch but
+ * returns false in *magic; it reflects a match via a true *magic out param.
+ * If magic is null, js_XDRScript returns false on bad magic number errors,
+ * which it reports.
+ *
+ * NB: callers must call js_CallNewScriptHook after successful JSXDR_DECODE
+ * and subsequent set-up of owning function or script object, if any.
+ */
+extern JSBool
+js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *magic);
+
+JS_END_EXTERN_C
+
+#endif /* jsscript_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg b/tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg
new file mode 100644
index 0000000..7074fe9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsshell.msg
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ Error messages for JSShell. See js.msg for format.
+*/
+
+MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
+MSG_DEF(JSSMSG_CANT_OPEN, 1, 2, JSEXN_NONE, "can't open {0}: {1}")
+MSG_DEF(JSSMSG_TRAP_USAGE, 2, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr")
+MSG_DEF(JSSMSG_LINE2PC_USAGE, 3, 0, JSEXN_NONE, "usage: line2pc [fun] line")
+MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 4, 0, JSEXN_NONE, "only works on JS scripts read from files")
+MSG_DEF(JSSMSG_UNEXPECTED_EOF, 5, 1, JSEXN_NONE, "unexpected EOF in {0}")
+MSG_DEF(JSSMSG_DOEXP_USAGE, 6, 0, JSEXN_NONE, "usage: doexp obj id")
+MSG_DEF(JSSMSG_SCRIPTS_ONLY, 7, 0, JSEXN_NONE, "only works on scripts")
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h b/tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h
new file mode 100644
index 0000000..2614659
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstaticcheck.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsstaticcheck_h___
+#define jsstaticcheck_h___
+
+#ifdef NS_STATIC_CHECKING
+/*
+ * Trigger a control flow check to make sure that code flows through label
+ */
+inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {
+}
+
+/* avoid unused goto-label warnings */
+#define MUST_FLOW_LABEL(label) goto label; label:
+#else
+#define MUST_FLOW_THROUGH(label) ((void)0)
+#define MUST_FLOW_LABEL(label)
+#endif
+
+#endif /* jsstaticcheck_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h b/tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h
new file mode 100644
index 0000000..45b417f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstddef.h
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * stddef inclusion here to first declare ptrdif as a signed long instead of a
+ * signed int.
+ */
+
+#ifdef _WINDOWS
+# ifndef XP_WIN
+# define XP_WIN
+# endif
+#if defined(_WIN32) || defined(WIN32)
+# ifndef XP_WIN32
+# define XP_WIN32
+# endif
+#else
+# ifndef XP_WIN16
+# define XP_WIN16
+# endif
+#endif
+#endif
+
+#ifdef XP_WIN16
+#ifndef _PTRDIFF_T_DEFINED
+typedef long ptrdiff_t;
+
+/*
+ * The Win16 compiler treats pointer differences as 16-bit signed values.
+ * This macro allows us to treat them as 17-bit signed values, stored in
+ * a 32-bit type.
+ */
+#define PTRDIFF(p1, p2, type) \
+ ((((unsigned long)(p1)) - ((unsigned long)(p2))) / sizeof(type))
+
+#define _PTRDIFF_T_DEFINED
+#endif /*_PTRDIFF_T_DEFINED*/
+#else /*WIN16*/
+
+#define PTRDIFF(p1, p2, type) \
+ ((p1) - (p2))
+
+#endif
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+# define __cplusplus_only(x) x
+#else
+# define __cplusplus_only(x) /* nothing */
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp
new file mode 100644
index 0000000..eeb505d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.cpp
@@ -0,0 +1,5347 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS string type implementation.
+ *
+ * In order to avoid unnecessary js_LockGCThing/js_UnlockGCThing calls, these
+ * native methods store strings (possibly newborn) converted from their 'this'
+ * parameter and arguments on the stack: 'this' conversions at argv[-1], arg
+ * conversions at their index (argv[0], argv[1]). This is a legitimate method
+ * of rooting things that might lose their newborn root due to subsequent GC
+ * allocations in the same native method.
+ */
+#include "jsstddef.h"
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jshash.h" /* Added by JSIFY */
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jsbuiltins.h"
+#include "jscntxt.h"
+#include "jsversion.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscope.h"
+#include "jsstr.h"
+#include "jsbit.h"
+
+#define JSSTRDEP_RECURSION_LIMIT 100
+
+size_t
+js_MinimizeDependentStrings(JSString *str, int level, JSString **basep)
+{
+ JSString *base;
+ size_t start, length;
+
+ JS_ASSERT(JSSTRING_IS_DEPENDENT(str));
+ base = JSSTRDEP_BASE(str);
+ start = JSSTRDEP_START(str);
+ if (JSSTRING_IS_DEPENDENT(base)) {
+ if (level < JSSTRDEP_RECURSION_LIMIT) {
+ start += js_MinimizeDependentStrings(base, level + 1, &base);
+ } else {
+ do {
+ start += JSSTRDEP_START(base);
+ base = JSSTRDEP_BASE(base);
+ } while (JSSTRING_IS_DEPENDENT(base));
+ }
+ if (start == 0) {
+ JS_ASSERT(JSSTRDEP_IS_PREFIX(str));
+ JSPREFIX_SET_BASE(str, base);
+ } else if (start <= JSSTRDEP_START_MASK) {
+ length = JSSTRDEP_LENGTH(str);
+ JSSTRDEP_INIT(str, base, start, length);
+ }
+ }
+ *basep = base;
+ return start;
+}
+
+jschar *
+js_GetDependentStringChars(JSString *str)
+{
+ size_t start;
+ JSString *base;
+
+ start = js_MinimizeDependentStrings(str, 0, &base);
+ JS_ASSERT(start < JSFLATSTR_LENGTH(base));
+ return JSFLATSTR_CHARS(base) + start;
+}
+
+const jschar *
+js_GetStringChars(JSContext *cx, JSString *str)
+{
+ if (!js_MakeStringImmutable(cx, str))
+ return NULL;
+ return JSFLATSTR_CHARS(str);
+}
+
+JSString * JS_FASTCALL
+js_ConcatStrings(JSContext *cx, JSString *left, JSString *right)
+{
+ size_t rn, ln, lrdist, n;
+ jschar *rs, *ls, *s;
+ JSString *ldep; /* non-null if left should become dependent */
+ JSString *str;
+
+ JSSTRING_CHARS_AND_LENGTH(right, rs, rn);
+ if (rn == 0)
+ return left;
+
+ JSSTRING_CHARS_AND_LENGTH(left, ls, ln);
+ if (ln == 0)
+ return right;
+
+ if (!JSSTRING_IS_MUTABLE(left)) {
+ /* We must copy if left does not own a buffer to realloc. */
+ s = (jschar *) JS_malloc(cx, (ln + rn + 1) * sizeof(jschar));
+ if (!s)
+ return NULL;
+ js_strncpy(s, ls, ln);
+ ldep = NULL;
+ } else {
+ /* We can realloc left's space and make it depend on our result. */
+ JS_ASSERT(JSSTRING_IS_FLAT(left));
+ s = (jschar *) JS_realloc(cx, ls, (ln + rn + 1) * sizeof(jschar));
+ if (!s)
+ return NULL;
+
+ /* Take care: right could depend on left! */
+ lrdist = (size_t)(rs - ls);
+ if (lrdist < ln)
+ rs = s + lrdist;
+ left->u.chars = ls = s;
+ ldep = left;
+ }
+
+ js_strncpy(s + ln, rs, rn);
+ n = ln + rn;
+ s[n] = 0;
+ str = js_NewString(cx, s, n);
+ if (!str) {
+ /* Out of memory: clean up any space we (re-)allocated. */
+ if (!ldep) {
+ JS_free(cx, s);
+ } else {
+ s = (jschar *) JS_realloc(cx, ls, (ln + 1) * sizeof(jschar));
+ if (s)
+ left->u.chars = s;
+ }
+ } else {
+ JSFLATSTR_SET_MUTABLE(str);
+
+ /* Morph left into a dependent prefix if we realloc'd its buffer. */
+ if (ldep) {
+ JSPREFIX_INIT(ldep, str, ln);
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_METER(rt, liveDependentStrings);
+ JS_RUNTIME_METER(rt, totalDependentStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->strdepLengthSum += (double)ln,
+ rt->strdepLengthSquaredSum += (double)ln * (double)ln));
+ }
+#endif
+ }
+ }
+
+ return str;
+}
+
+const jschar *
+js_UndependString(JSContext *cx, JSString *str)
+{
+ size_t n, size;
+ jschar *s;
+
+ if (JSSTRING_IS_DEPENDENT(str)) {
+ n = JSSTRDEP_LENGTH(str);
+ size = (n + 1) * sizeof(jschar);
+ s = (jschar *) JS_malloc(cx, size);
+ if (!s)
+ return NULL;
+
+ js_strncpy(s, JSSTRDEP_CHARS(str), n);
+ s[n] = 0;
+ JSFLATSTR_INIT(str, s, n);
+
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_UNMETER(rt, liveDependentStrings);
+ JS_RUNTIME_UNMETER(rt, totalDependentStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->strdepLengthSum -= (double)n,
+ rt->strdepLengthSquaredSum -= (double)n * (double)n));
+ }
+#endif
+ }
+
+ return JSFLATSTR_CHARS(str);
+}
+
+JSBool
+js_MakeStringImmutable(JSContext *cx, JSString *str)
+{
+ if (JSSTRING_IS_DEPENDENT(str) && !js_UndependString(cx, str)) {
+ JS_RUNTIME_METER(cx->runtime, badUndependStrings);
+ return JS_FALSE;
+ }
+ JSFLATSTR_CLEAR_MUTABLE(str);
+ return JS_TRUE;
+}
+
+static JSString *
+ArgToRootedString(JSContext *cx, uintN argc, jsval *vp, uintN arg)
+{
+ JSObject *obj;
+ JSString *str;
+
+ if (arg >= argc)
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ vp += 2 + arg;
+
+ if (JSVAL_IS_OBJECT(*vp)) {
+ obj = JSVAL_TO_OBJECT(*vp);
+ if (!obj)
+ return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, vp))
+ return NULL;
+ }
+ if (JSVAL_IS_STRING(*vp))
+ return JSVAL_TO_STRING(*vp);
+ if (JSVAL_IS_INT(*vp)) {
+ str = js_NumberToString(cx, JSVAL_TO_INT(*vp));
+ } else if (JSVAL_IS_DOUBLE(*vp)) {
+ str = js_NumberToString(cx, *JSVAL_TO_DOUBLE(*vp));
+ } else if (JSVAL_IS_BOOLEAN(*vp)) {
+ return ATOM_TO_STRING(cx->runtime->atomState.booleanAtoms[
+ JSVAL_TO_BOOLEAN(*vp)? 1 : 0]);
+ } else {
+ JS_ASSERT(JSVAL_IS_VOID(*vp));
+ return ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ }
+ if (str)
+ *vp = STRING_TO_JSVAL(str);
+ return str;
+}
+
+/*
+ * Forward declarations for URI encode/decode and helper routines
+ */
+static JSBool
+str_decodeURI(JSContext *cx, uintN argc, jsval *vp);
+
+static JSBool
+str_decodeURI_Component(JSContext *cx, uintN argc, jsval *vp);
+
+static JSBool
+str_encodeURI(JSContext *cx, uintN argc, jsval *vp);
+
+static JSBool
+str_encodeURI_Component(JSContext *cx, uintN argc, jsval *vp);
+
+static uint32
+Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length);
+
+/*
+ * Contributions from the String class to the set of methods defined for the
+ * global object. escape and unescape used to be defined in the Mocha library,
+ * but as ECMA decided to spec them, they've been moved to the core engine
+ * and made ECMA-compliant. (Incomplete escapes are interpreted as literal
+ * characters by unescape.)
+ */
+
+/*
+ * Stuff to emulate the old libmocha escape, which took a second argument
+ * giving the type of escape to perform. Retained for compatibility, and
+ * copied here to avoid reliance on net.h, mkparse.c/NET_EscapeBytes.
+ */
+
+#define URL_XALPHAS ((uint8) 1)
+#define URL_XPALPHAS ((uint8) 2)
+#define URL_PATH ((uint8) 4)
+
+static const uint8 urlCharType[256] =
+/* Bit 0 xalpha -- the alphas
+ * Bit 1 xpalpha -- as xalpha but
+ * converts spaces to plus and plus to %20
+ * Bit 2 ... path -- as xalphas but doesn't escape '/'
+ */
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1x */
+ 0,0,0,0,0,0,0,0,0,0,7,4,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
+ 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0, /* 7X pqrstuvwxyz{\}~ DEL */
+ 0, };
+
+/* This matches the ECMA escape set when mask is 7 (default.) */
+
+#define IS_OK(C, mask) (urlCharType[((uint8) (C))] & (mask))
+
+/* See ECMA-262 Edition 3 B.2.1 */
+JSBool
+js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+ size_t i, ni, length, newlength;
+ const jschar *chars;
+ jschar *newchars;
+ jschar ch;
+ jsint mask;
+ jsdouble d;
+ const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &argv[1]);
+ if (JSVAL_IS_NULL(argv[1]))
+ return JS_FALSE;
+ if (!JSDOUBLE_IS_FINITE(d) ||
+ (mask = (jsint)d) != d ||
+ mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))
+ {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) mask);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_STRING_MASK, numBuf);
+ return JS_FALSE;
+ }
+ }
+
+ str = ArgToRootedString(cx, argc, argv - 2, 0);
+ if (!str)
+ return JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ newlength = length;
+
+ /* Take a first pass and see how big the result string will need to be. */
+ for (i = 0; i < length; i++) {
+ if ((ch = chars[i]) < 128 && IS_OK(ch, mask))
+ continue;
+ if (ch < 256) {
+ if (mask == URL_XPALPHAS && ch == ' ')
+ continue; /* The character will be encoded as '+' */
+ newlength += 2; /* The character will be encoded as %XX */
+ } else {
+ newlength += 5; /* The character will be encoded as %uXXXX */
+ }
+
+ /*
+ * This overflow test works because newlength is incremented by at
+ * most 5 on each iteration.
+ */
+ if (newlength < length) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+ }
+
+ if (newlength >= ~(size_t)0 / sizeof(jschar)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ newchars = (jschar *) JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+ if (!newchars)
+ return JS_FALSE;
+ for (i = 0, ni = 0; i < length; i++) {
+ if ((ch = chars[i]) < 128 && IS_OK(ch, mask)) {
+ newchars[ni++] = ch;
+ } else if (ch < 256) {
+ if (mask == URL_XPALPHAS && ch == ' ') {
+ newchars[ni++] = '+'; /* convert spaces to pluses */
+ } else {
+ newchars[ni++] = '%';
+ newchars[ni++] = digits[ch >> 4];
+ newchars[ni++] = digits[ch & 0xF];
+ }
+ } else {
+ newchars[ni++] = '%';
+ newchars[ni++] = 'u';
+ newchars[ni++] = digits[ch >> 12];
+ newchars[ni++] = digits[(ch & 0xF00) >> 8];
+ newchars[ni++] = digits[(ch & 0xF0) >> 4];
+ newchars[ni++] = digits[ch & 0xF];
+ }
+ }
+ JS_ASSERT(ni == newlength);
+ newchars[newlength] = 0;
+
+ str = js_NewString(cx, newchars, newlength);
+ if (!str) {
+ JS_free(cx, newchars);
+ return JS_FALSE;
+ }
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#undef IS_OK
+
+static JSBool
+str_escape(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && js_str_escape(cx, obj, argc, vp + 2, vp);
+}
+
+/* See ECMA-262 Edition 3 B.2.2 */
+static JSBool
+str_unescape(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ size_t i, ni, length;
+ const jschar *chars;
+ jschar *newchars;
+ jschar ch;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+
+ /* Don't bother allocating less space for the new string. */
+ newchars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!newchars)
+ return JS_FALSE;
+ ni = i = 0;
+ while (i < length) {
+ ch = chars[i++];
+ if (ch == '%') {
+ if (i + 1 < length &&
+ JS7_ISHEX(chars[i]) && JS7_ISHEX(chars[i + 1]))
+ {
+ ch = JS7_UNHEX(chars[i]) * 16 + JS7_UNHEX(chars[i + 1]);
+ i += 2;
+ } else if (i + 4 < length && chars[i] == 'u' &&
+ JS7_ISHEX(chars[i + 1]) && JS7_ISHEX(chars[i + 2]) &&
+ JS7_ISHEX(chars[i + 3]) && JS7_ISHEX(chars[i + 4]))
+ {
+ ch = (((((JS7_UNHEX(chars[i + 1]) << 4)
+ + JS7_UNHEX(chars[i + 2])) << 4)
+ + JS7_UNHEX(chars[i + 3])) << 4)
+ + JS7_UNHEX(chars[i + 4]);
+ i += 5;
+ }
+ }
+ newchars[ni++] = ch;
+ }
+ newchars[ni] = 0;
+
+ str = js_NewString(cx, newchars, ni);
+ if (!str) {
+ JS_free(cx, newchars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#if JS_HAS_UNEVAL
+static JSBool
+str_uneval(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = js_ValueToSource(cx, argc != 0 ? vp[2] : JSVAL_VOID);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif
+
+const char js_escape_str[] = "escape";
+const char js_unescape_str[] = "unescape";
+#if JS_HAS_UNEVAL
+const char js_uneval_str[] = "uneval";
+#endif
+const char js_decodeURI_str[] = "decodeURI";
+const char js_encodeURI_str[] = "encodeURI";
+const char js_decodeURIComponent_str[] = "decodeURIComponent";
+const char js_encodeURIComponent_str[] = "encodeURIComponent";
+
+static JSFunctionSpec string_functions[] = {
+ JS_FN(js_escape_str, str_escape, 1,0),
+ JS_FN(js_unescape_str, str_unescape, 1,0),
+#if JS_HAS_UNEVAL
+ JS_FN(js_uneval_str, str_uneval, 1,0),
+#endif
+ JS_FN(js_decodeURI_str, str_decodeURI, 1,0),
+ JS_FN(js_encodeURI_str, str_encodeURI, 1,0),
+ JS_FN(js_decodeURIComponent_str, str_decodeURI_Component, 1,0),
+ JS_FN(js_encodeURIComponent_str, str_encodeURI_Component, 1,0),
+
+ JS_FS_END
+};
+
+jschar js_empty_ucstr[] = {0};
+JSSubString js_EmptySubString = {0, js_empty_ucstr};
+
+enum string_tinyid {
+ STRING_LENGTH = -1
+};
+
+static JSPropertySpec string_props[] = {
+ {js_length_str, STRING_LENGTH,
+ JSPROP_READONLY|JSPROP_PERMANENT|JSPROP_SHARED, 0,0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+str_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ jsval v;
+ JSString *str;
+ jsint slot;
+
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ slot = JSVAL_TO_INT(id);
+ if (slot == STRING_LENGTH) {
+ if (OBJ_GET_CLASS(cx, obj) == &js_StringClass) {
+ /* Follow ECMA-262 by fetching intrinsic length of our string. */
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = JSVAL_TO_STRING(v);
+ } else {
+ /* Preserve compatibility: convert obj to a string primitive. */
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ if (!str)
+ return JS_FALSE;
+ }
+
+ *vp = INT_TO_JSVAL((jsint) JSSTRING_LENGTH(str));
+ }
+ return JS_TRUE;
+}
+
+#define STRING_ELEMENT_ATTRS (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
+
+static JSBool
+str_enumerate(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+ JSString *str, *str1;
+ size_t i, length;
+
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = JSVAL_TO_STRING(v);
+
+ length = JSSTRING_LENGTH(str);
+ for (i = 0; i < length; i++) {
+ str1 = js_NewDependentString(cx, str, i, 1);
+ if (!str1)
+ return JS_FALSE;
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(i),
+ STRING_TO_JSVAL(str1), NULL, NULL,
+ STRING_ELEMENT_ATTRS, NULL)) {
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+str_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
+ JSObject **objp)
+{
+ jsval v;
+ JSString *str, *str1;
+ jsint slot;
+
+ if (!JSVAL_IS_INT(id) || (flags & JSRESOLVE_ASSIGNING))
+ return JS_TRUE;
+
+ v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = JSVAL_TO_STRING(v);
+
+ slot = JSVAL_TO_INT(id);
+ if ((size_t)slot < JSSTRING_LENGTH(str)) {
+ str1 = js_GetUnitString(cx, str, (size_t)slot);
+ if (!str1)
+ return JS_FALSE;
+ if (!OBJ_DEFINE_PROPERTY(cx, obj, INT_TO_JSID(slot),
+ STRING_TO_JSVAL(str1), NULL, NULL,
+ STRING_ELEMENT_ATTRS, NULL)) {
+ return JS_FALSE;
+ }
+ *objp = obj;
+ }
+ return JS_TRUE;
+}
+
+JSClass js_StringClass = {
+ js_String_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_String),
+ JS_PropertyStub, JS_PropertyStub, str_getProperty, JS_PropertyStub,
+ str_enumerate, (JSResolveOp)str_resolve, JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+#define NORMALIZE_THIS(cx,vp,str) \
+ JS_BEGIN_MACRO \
+ if (JSVAL_IS_STRING(vp[1])) { \
+ str = JSVAL_TO_STRING(vp[1]); \
+ } else { \
+ str = NormalizeThis(cx, vp); \
+ if (!str) \
+ return JS_FALSE; \
+ } \
+ JS_END_MACRO
+
+static JSString *
+NormalizeThis(JSContext *cx, jsval *vp)
+{
+ JSString *str;
+
+ if (JSVAL_IS_NULL(vp[1]) && JSVAL_IS_NULL(JS_THIS(cx, vp)))
+ return NULL;
+ str = js_ValueToString(cx, vp[1]);
+ if (!str)
+ return NULL;
+ vp[1] = STRING_TO_JSVAL(str);
+ return str;
+}
+
+#if JS_HAS_TOSOURCE
+
+/*
+ * String.prototype.quote is generic (as are most string methods), unlike
+ * toSource, toString, and valueOf.
+ */
+static JSBool
+str_quote(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NORMALIZE_THIS(cx, vp, str);
+ str = js_QuoteString(cx, str, '"');
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval v;
+ JSString *str;
+ size_t i, j, k, n;
+ char buf[16];
+ jschar *s, *t;
+
+ if (!js_GetPrimitiveThis(cx, vp, &js_StringClass, &v))
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ str = js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
+ if (!str)
+ return JS_FALSE;
+ j = JS_snprintf(buf, sizeof buf, "(new %s(", js_StringClass.name);
+ JSSTRING_CHARS_AND_LENGTH(str, s, k);
+ n = j + k + 2;
+ t = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!t)
+ return JS_FALSE;
+ for (i = 0; i < j; i++)
+ t[i] = buf[i];
+ for (j = 0; j < k; i++, j++)
+ t[i] = s[j];
+ t[i++] = ')';
+ t[i++] = ')';
+ t[i] = 0;
+ str = js_NewString(cx, t, n);
+ if (!str) {
+ JS_free(cx, t);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#endif /* JS_HAS_TOSOURCE */
+
+static JSBool
+str_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_GetPrimitiveThis(cx, vp, &js_StringClass, vp);
+}
+
+/*
+ * Java-like string native methods.
+ */
+
+static JSString *
+SubstringTail(JSContext *cx, JSString *str, jsdouble length, jsdouble begin, jsdouble end)
+{
+ if (begin < 0)
+ begin = 0;
+ else if (begin > length)
+ begin = length;
+
+ if (end < 0)
+ end = 0;
+ else if (end > length)
+ end = length;
+ if (end < begin) {
+ /* ECMA emulates old JDK1.0 java.lang.String.substring. */
+ jsdouble tmp = begin;
+ begin = end;
+ end = tmp;
+ }
+
+ return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
+}
+
+static JSBool
+str_substring(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble d;
+ jsdouble length, begin, end;
+
+ NORMALIZE_THIS(cx, vp, str);
+ if (argc != 0) {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ length = JSSTRING_LENGTH(str);
+ begin = js_DoubleToInteger(d);
+ if (argc == 1) {
+ end = length;
+ } else {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ end = js_DoubleToInteger(d);
+ }
+
+ str = SubstringTail(cx, str, length, begin, end);
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_p_toString(JSContext* cx, JSObject* obj)
+{
+ if (!JS_InstanceOf(cx, obj, &js_StringClass, NULL))
+ return NULL;
+ jsval v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+static JSString* FASTCALL
+String_p_substring(JSContext* cx, JSString* str, int32 begin, int32 end)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+
+ size_t length = JSSTRING_LENGTH(str);
+ return SubstringTail(cx, str, length, begin, end);
+}
+
+static JSString* FASTCALL
+String_p_substring_1(JSContext* cx, JSString* str, int32 begin)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+
+ size_t length = JSSTRING_LENGTH(str);
+ return SubstringTail(cx, str, length, begin, length);
+}
+#endif
+
+JSString* JS_FASTCALL
+js_toLowerCase(JSContext *cx, JSString *str)
+{
+ size_t i, n;
+ jschar *s, *news;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, n);
+ news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!news)
+ return NULL;
+ for (i = 0; i < n; i++)
+ news[i] = JS_TOLOWER(s[i]);
+ news[n] = 0;
+ str = js_NewString(cx, news, n);
+ if (!str) {
+ JS_free(cx, news);
+ return NULL;
+ }
+ return str;
+}
+
+static JSBool
+str_toLowerCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NORMALIZE_THIS(cx, vp, str);
+ str = js_toLowerCase(cx, str);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_toLocaleLowerCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ /*
+ * Forcefully ignore the first (or any) argument and return toLowerCase(),
+ * ECMA has reserved that argument, presumably for defining the locale.
+ */
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToLowerCase) {
+ NORMALIZE_THIS(cx, vp, str);
+ return cx->localeCallbacks->localeToLowerCase(cx, str, vp);
+ }
+ return str_toLowerCase(cx, 0, vp);
+}
+
+JSString* JS_FASTCALL
+js_toUpperCase(JSContext *cx, JSString *str)
+{
+ size_t i, n;
+ jschar *s, *news;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, n);
+ news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!news)
+ return NULL;
+ for (i = 0; i < n; i++)
+ news[i] = JS_TOUPPER(s[i]);
+ news[n] = 0;
+ str = js_NewString(cx, news, n);
+ if (!str) {
+ JS_free(cx, news);
+ return NULL;
+ }
+ return str;
+}
+
+static JSBool
+str_toUpperCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NORMALIZE_THIS(cx, vp, str);
+ str = js_toUpperCase(cx, str);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_toLocaleUpperCase(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ /*
+ * Forcefully ignore the first (or any) argument and return toUpperCase(),
+ * ECMA has reserved that argument, presumably for defining the locale.
+ */
+ if (cx->localeCallbacks && cx->localeCallbacks->localeToUpperCase) {
+ NORMALIZE_THIS(cx, vp, str);
+ return cx->localeCallbacks->localeToUpperCase(cx, str, vp);
+ }
+ return str_toUpperCase(cx, 0, vp);
+}
+
+static JSBool
+str_localeCompare(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *thatStr;
+
+ NORMALIZE_THIS(cx, vp, str);
+ if (argc == 0) {
+ *vp = JSVAL_ZERO;
+ } else {
+ thatStr = js_ValueToString(cx, vp[2]);
+ if (!thatStr)
+ return JS_FALSE;
+ if (cx->localeCallbacks && cx->localeCallbacks->localeCompare) {
+ vp[2] = STRING_TO_JSVAL(thatStr);
+ return cx->localeCallbacks->localeCompare(cx, str, thatStr, vp);
+ }
+ *vp = INT_TO_JSVAL(js_CompareStrings(str, thatStr));
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+str_charAt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t;
+ JSString *str;
+ jsint i;
+ jsdouble d;
+
+ t = vp[1];
+ if (JSVAL_IS_STRING(t) && argc != 0 && JSVAL_IS_INT(vp[2])) {
+ str = JSVAL_TO_STRING(t);
+ i = JSVAL_TO_INT(vp[2]);
+ if ((size_t)i >= JSSTRING_LENGTH(str))
+ goto out_of_range;
+ } else {
+ str = NormalizeThis(cx, vp);
+ if (!str)
+ return JS_FALSE;
+
+ if (argc == 0) {
+ d = 0.0;
+ } else {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ }
+
+ if (d < 0 || JSSTRING_LENGTH(str) <= d)
+ goto out_of_range;
+ i = (jsint) d;
+ }
+
+ str = js_GetUnitString(cx, str, (size_t)i);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+
+out_of_range:
+ *vp = JS_GetEmptyStringValue(cx);
+ return JS_TRUE;
+}
+
+static JSBool
+str_charCodeAt(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t;
+ JSString *str;
+ jsint i;
+ jsdouble d;
+
+ t = vp[1];
+ if (JSVAL_IS_STRING(t) && argc != 0 && JSVAL_IS_INT(vp[2])) {
+ str = JSVAL_TO_STRING(t);
+ i = JSVAL_TO_INT(vp[2]);
+ if ((size_t)i >= JSSTRING_LENGTH(str))
+ goto out_of_range;
+ } else {
+ str = NormalizeThis(cx, vp);
+ if (!str)
+ return JS_FALSE;
+
+ if (argc == 0) {
+ d = 0.0;
+ } else {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ }
+
+ if (d < 0 || JSSTRING_LENGTH(str) <= d)
+ goto out_of_range;
+ i = (jsint) d;
+ }
+
+ *vp = INT_TO_JSVAL(JSSTRING_CHARS(str)[i]);
+ return JS_TRUE;
+
+out_of_range:
+ *vp = JS_GetNaNValue(cx);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+int32 FASTCALL
+js_String_p_charCodeAt(JSString* str, int32 i)
+{
+ if (i < 0 || (int32)JSSTRING_LENGTH(str) <= i)
+ return -1;
+ return JSSTRING_CHARS(str)[i];
+}
+#endif
+
+jsint
+js_BoyerMooreHorspool(const jschar *text, jsint textlen,
+ const jschar *pat, jsint patlen,
+ jsint start)
+{
+ jsint i, j, k, m;
+ uint8 skip[BMH_CHARSET_SIZE];
+ jschar c;
+
+ JS_ASSERT(0 < patlen && patlen <= BMH_PATLEN_MAX);
+ for (i = 0; i < BMH_CHARSET_SIZE; i++)
+ skip[i] = (uint8)patlen;
+ m = patlen - 1;
+ for (i = 0; i < m; i++) {
+ c = pat[i];
+ if (c >= BMH_CHARSET_SIZE)
+ return BMH_BAD_PATTERN;
+ skip[c] = (uint8)(m - i);
+ }
+ for (k = start + m;
+ k < textlen;
+ k += ((c = text[k]) >= BMH_CHARSET_SIZE) ? patlen : skip[c]) {
+ for (i = k, j = m; ; i--, j--) {
+ if (j < 0)
+ return i + 1;
+ if (text[i] != pat[j])
+ break;
+ }
+ }
+ return -1;
+}
+
+static JSBool
+str_indexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t;
+ JSString *str, *str2;
+ const jschar *text, *pat;
+ jsint i, j, index, textlen, patlen;
+ jsdouble d;
+
+ t = vp[1];
+ if (JSVAL_IS_STRING(t) && argc != 0 && JSVAL_IS_STRING(vp[2])) {
+ str = JSVAL_TO_STRING(t);
+ str2 = JSVAL_TO_STRING(vp[2]);
+ } else {
+ str = NormalizeThis(cx, vp);
+ if (!str)
+ return JS_FALSE;
+
+ str2 = ArgToRootedString(cx, argc, vp, 0);
+ if (!str2)
+ return JS_FALSE;
+ }
+
+ text = JSSTRING_CHARS(str);
+ textlen = (jsint) JSSTRING_LENGTH(str);
+ pat = JSSTRING_CHARS(str2);
+ patlen = (jsint) JSSTRING_LENGTH(str2);
+
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ d = js_DoubleToInteger(d);
+ if (d < 0)
+ i = 0;
+ else if (d > textlen)
+ i = textlen;
+ else
+ i = (jsint)d;
+ } else {
+ i = 0;
+ }
+ if (patlen == 0) {
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+
+ /* XXX tune the BMH threshold (512) */
+ if (textlen - i >= 512 && (jsuint)(patlen - 2) <= BMH_PATLEN_MAX - 2) {
+ index = js_BoyerMooreHorspool(text, textlen, pat, patlen, i);
+ if (index != BMH_BAD_PATTERN)
+ goto out;
+ }
+
+ index = -1;
+ j = 0;
+ while (i + j < textlen) {
+ if (text[i + j] == pat[j]) {
+ if (++j == patlen) {
+ index = i;
+ break;
+ }
+ } else {
+ i++;
+ j = 0;
+ }
+ }
+
+out:
+ *vp = INT_TO_JSVAL(index);
+ return JS_TRUE;
+}
+
+static JSBool
+str_lastIndexOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *str2;
+ const jschar *text, *pat;
+ jsint i, j, textlen, patlen;
+ jsdouble d;
+
+ NORMALIZE_THIS(cx, vp, str);
+ text = JSSTRING_CHARS(str);
+ textlen = (jsint) JSSTRING_LENGTH(str);
+
+ str2 = ArgToRootedString(cx, argc, vp, 0);
+ if (!str2)
+ return JS_FALSE;
+ pat = JSSTRING_CHARS(str2);
+ patlen = (jsint) JSSTRING_LENGTH(str2);
+
+ if (argc > 1) {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ if (JSDOUBLE_IS_NaN(d)) {
+ i = textlen;
+ } else {
+ d = js_DoubleToInteger(d);
+ if (d < 0)
+ i = 0;
+ else if (d > textlen)
+ i = textlen;
+ else
+ i = (jsint)d;
+ }
+ } else {
+ i = textlen;
+ }
+
+ if (patlen == 0) {
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+ }
+
+ j = 0;
+ while (i >= 0) {
+ /* Don't assume that text is NUL-terminated: it could be dependent. */
+ if (i + j < textlen && text[i + j] == pat[j]) {
+ if (++j == patlen)
+ break;
+ } else {
+ i--;
+ j = 0;
+ }
+ }
+ *vp = INT_TO_JSVAL(i);
+ return JS_TRUE;
+}
+
+static JSBool
+js_TrimString(JSContext *cx, jsval *vp, JSBool trimLeft, JSBool trimRight)
+{
+ JSString *str;
+ const jschar *chars;
+ size_t length, begin, end;
+
+ NORMALIZE_THIS(cx, vp, str);
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ begin = 0;
+ end = length;
+
+ if (trimLeft) {
+ while (begin < length && JS_ISSPACE(chars[begin]))
+ ++begin;
+ }
+
+ if (trimRight) {
+ while (end > begin && JS_ISSPACE(chars[end-1]))
+ --end;
+ }
+
+ str = js_NewDependentString(cx, str, begin, end - begin);
+ if (!str)
+ return JS_FALSE;
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+str_trim(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_TrimString(cx, vp, JS_TRUE, JS_TRUE);
+}
+
+static JSBool
+str_trimLeft(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_TrimString(cx, vp, JS_TRUE, JS_FALSE);
+}
+
+static JSBool
+str_trimRight(JSContext *cx, uintN argc, jsval *vp)
+{
+ return js_TrimString(cx, vp, JS_FALSE, JS_TRUE);
+}
+
+/*
+ * Perl-inspired string functions.
+ */
+typedef struct GlobData {
+ jsbytecode *pc; /* in: program counter resulting in us matching */
+ uintN flags; /* inout: mode and flag bits, see below */
+ uintN optarg; /* in: index of optional flags argument */
+ JSString *str; /* out: 'this' parameter object as string */
+ JSRegExp *regexp; /* out: regexp parameter object private data */
+} GlobData;
+
+/*
+ * Mode and flag bit definitions for match_or_replace's GlobData.flags field.
+ */
+#define MODE_MATCH 0x00 /* in: return match array on success */
+#define MODE_REPLACE 0x01 /* in: match and replace */
+#define MODE_SEARCH 0x02 /* in: search only, return match index or -1 */
+#define GET_MODE(f) ((f) & 0x03)
+#define FORCE_FLAT 0x04 /* in: force flat (non-regexp) string match */
+#define KEEP_REGEXP 0x08 /* inout: keep GlobData.regexp alive for caller
+ of match_or_replace; if set on input
+ but clear on output, regexp ownership
+ does not pass to caller */
+#define GLOBAL_REGEXP 0x10 /* out: regexp had the 'g' flag */
+
+static JSBool
+match_or_replace(JSContext *cx,
+ JSBool (*glob)(JSContext *cx, jsint count, GlobData *data),
+ void (*destroy)(JSContext *cx, GlobData *data),
+ GlobData *data, uintN argc, jsval *vp)
+{
+ JSString *str, *src, *opt;
+ JSObject *reobj;
+ JSRegExp *re;
+ size_t index, length;
+ JSBool ok, test;
+ jsint count;
+
+ NORMALIZE_THIS(cx, vp, str);
+ data->str = str;
+
+ if (argc != 0 && VALUE_IS_REGEXP(cx, vp[2])) {
+ reobj = JSVAL_TO_OBJECT(vp[2]);
+ re = (JSRegExp *) JS_GetPrivate(cx, reobj);
+ } else {
+ src = ArgToRootedString(cx, argc, vp, 0);
+ if (!src)
+ return JS_FALSE;
+ if (data->optarg < argc) {
+ opt = js_ValueToString(cx, vp[2 + data->optarg]);
+ if (!opt)
+ return JS_FALSE;
+ } else {
+ opt = NULL;
+ }
+ re = js_NewRegExpOpt(cx, src, opt, (data->flags & FORCE_FLAT) != 0);
+ if (!re)
+ return JS_FALSE;
+ reobj = NULL;
+ }
+ /* From here on, all control flow must reach the matching DROP. */
+ data->regexp = re;
+ HOLD_REGEXP(cx, re);
+
+ if (re->flags & JSREG_GLOB)
+ data->flags |= GLOBAL_REGEXP;
+ index = 0;
+ if (GET_MODE(data->flags) == MODE_SEARCH) {
+ ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
+ if (ok) {
+ *vp = (*vp == JSVAL_TRUE)
+ ? INT_TO_JSVAL(cx->regExpStatics.leftContext.length)
+ : INT_TO_JSVAL(-1);
+ }
+ } else if (data->flags & GLOBAL_REGEXP) {
+ if (reobj) {
+ /* Set the lastIndex property's reserved slot to 0. */
+ ok = js_SetLastIndex(cx, reobj, 0);
+ } else {
+ ok = JS_TRUE;
+ }
+ if (ok) {
+ length = JSSTRING_LENGTH(str);
+ for (count = 0; index <= length; count++) {
+ ok = js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, vp);
+ if (!ok || *vp != JSVAL_TRUE)
+ break;
+ ok = glob(cx, count, data);
+ if (!ok)
+ break;
+ if (cx->regExpStatics.lastMatch.length == 0) {
+ if (index == length)
+ break;
+ index++;
+ }
+ }
+ if (!ok && destroy)
+ destroy(cx, data);
+ }
+ } else {
+ if (GET_MODE(data->flags) == MODE_REPLACE) {
+ test = JS_TRUE;
+ } else {
+ /*
+ * MODE_MATCH implies str_match is being called from a script or a
+ * scripted function. If the caller cares only about testing null
+ * vs. non-null return value, optimize away the array object that
+ * would normally be returned in *vp.
+ *
+ * Assume a full array result is required, then prove otherwise.
+ */
+ test = JS_FALSE;
+ if (data->pc && (*data->pc == JSOP_CALL || *data->pc == JSOP_NEW)) {
+ JS_ASSERT(js_CodeSpec[*data->pc].length == 3);
+ switch (data->pc[3]) {
+ case JSOP_POP:
+ case JSOP_IFEQ:
+ case JSOP_IFNE:
+ case JSOP_IFEQX:
+ case JSOP_IFNEX:
+ test = JS_TRUE;
+ break;
+ default:;
+ }
+ }
+ }
+ ok = js_ExecuteRegExp(cx, re, str, &index, test, vp);
+ }
+
+ DROP_REGEXP(cx, re);
+ if (reobj) {
+ /* Tell our caller that it doesn't need to destroy data->regexp. */
+ data->flags &= ~KEEP_REGEXP;
+ } else if (!ok || !(data->flags & KEEP_REGEXP)) {
+ /* Caller didn't want to keep data->regexp, so null and destroy it. */
+ data->regexp = NULL;
+ js_DestroyRegExp(cx, re);
+ }
+
+ return ok;
+}
+
+typedef struct MatchData {
+ GlobData base;
+ jsval *arrayval; /* NB: local root pointer */
+} MatchData;
+
+static JSBool
+match_glob(JSContext *cx, jsint count, GlobData *data)
+{
+ MatchData *mdata;
+ JSObject *arrayobj;
+ JSSubString *matchsub;
+ JSString *matchstr;
+ jsval v;
+
+ mdata = (MatchData *)data;
+ arrayobj = JSVAL_TO_OBJECT(*mdata->arrayval);
+ if (!arrayobj) {
+ arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);
+ if (!arrayobj)
+ return JS_FALSE;
+ *mdata->arrayval = OBJECT_TO_JSVAL(arrayobj);
+ }
+ matchsub = &cx->regExpStatics.lastMatch;
+ matchstr = js_NewStringCopyN(cx, matchsub->chars, matchsub->length);
+ if (!matchstr)
+ return JS_FALSE;
+ v = STRING_TO_JSVAL(matchstr);
+ JS_ASSERT(count <= JSVAL_INT_MAX);
+
+ JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_ASSIGNING);
+ return OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(count), &v);
+}
+
+JSBool
+js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc)
+{
+ JSTempValueRooter tvr;
+ MatchData mdata;
+ JSBool ok;
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ mdata.base.pc = pc;
+ mdata.base.flags = MODE_MATCH;
+ mdata.base.optarg = 1;
+ mdata.arrayval = &tvr.u.value;
+ ok = match_or_replace(cx, match_glob, NULL, &mdata.base, argc, vp);
+ if (ok && !JSVAL_IS_NULL(*mdata.arrayval))
+ *vp = *mdata.arrayval;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSBool
+str_match(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSStackFrame *fp;
+
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+ JS_ASSERT(!fp->script);
+ return js_StringMatchHelper(cx, argc, vp, fp ? fp->regs->pc : NULL);
+}
+
+#ifdef JS_TRACER
+static JSObject* FASTCALL
+String_p_match(JSContext* cx, JSString* str, jsbytecode *pc, JSObject* regexp)
+{
+ jsval vp[3] = { JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
+ if (!js_StringMatchHelper(cx, 1, vp, pc))
+ return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
+ (!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
+ return JSVAL_TO_OBJECT(vp[0]);
+}
+
+static JSObject* FASTCALL
+String_p_match_obj(JSContext* cx, JSObject* str, jsbytecode *pc, JSObject* regexp)
+{
+ jsval vp[3] = { JSVAL_NULL, OBJECT_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp) };
+ if (!js_StringMatchHelper(cx, 1, vp, pc))
+ return (JSObject*) JSVAL_TO_BOOLEAN(JSVAL_VOID);
+ JS_ASSERT(JSVAL_IS_NULL(vp[0]) ||
+ (!JSVAL_IS_PRIMITIVE(vp[0]) && OBJ_IS_ARRAY(cx, JSVAL_TO_OBJECT(vp[0]))));
+ return JSVAL_TO_OBJECT(vp[0]);
+}
+#endif
+
+static JSBool
+str_search(JSContext *cx, uintN argc, jsval *vp)
+{
+ GlobData data;
+
+ data.flags = MODE_SEARCH;
+ data.optarg = 1;
+ return match_or_replace(cx, NULL, NULL, &data, argc, vp);
+}
+
+typedef struct ReplaceData {
+ GlobData base; /* base struct state */
+ JSObject *lambda; /* replacement function object or null */
+ JSString *repstr; /* replacement string */
+ jschar *dollar; /* null or pointer to first $ in repstr */
+ jschar *dollarEnd; /* limit pointer for js_strchr_limit */
+ jschar *chars; /* result chars, null initially */
+ size_t length; /* result length, 0 initially */
+ jsint index; /* index in result of next replacement */
+ jsint leftIndex; /* left context index in base.str->chars */
+ JSSubString dollarStr; /* for "$$" interpret_dollar result */
+} ReplaceData;
+
+static JSSubString *
+interpret_dollar(JSContext *cx, jschar *dp, jschar *ep, ReplaceData *rdata,
+ size_t *skip)
+{
+ JSRegExpStatics *res;
+ jschar dc, *cp;
+ uintN num, tmp;
+
+ JS_ASSERT(*dp == '$');
+
+ /* If there is only a dollar, bail now */
+ if (dp + 1 >= ep)
+ return NULL;
+
+ /* Interpret all Perl match-induced dollar variables. */
+ res = &cx->regExpStatics;
+ dc = dp[1];
+ if (JS7_ISDEC(dc)) {
+ /* ECMA-262 Edition 3: 1-9 or 01-99 */
+ num = JS7_UNDEC(dc);
+ if (num > res->parenCount)
+ return NULL;
+
+ cp = dp + 2;
+ if (cp < ep && (dc = *cp, JS7_ISDEC(dc))) {
+ tmp = 10 * num + JS7_UNDEC(dc);
+ if (tmp <= res->parenCount) {
+ cp++;
+ num = tmp;
+ }
+ }
+ if (num == 0)
+ return NULL;
+
+ /* Adjust num from 1 $n-origin to 0 array-index-origin. */
+ num--;
+ *skip = cp - dp;
+ return REGEXP_PAREN_SUBSTRING(res, num);
+ }
+
+ *skip = 2;
+ switch (dc) {
+ case '$':
+ rdata->dollarStr.chars = dp;
+ rdata->dollarStr.length = 1;
+ return &rdata->dollarStr;
+ case '&':
+ return &res->lastMatch;
+ case '+':
+ return &res->lastParen;
+ case '`':
+ return &res->leftContext;
+ case '\'':
+ return &res->rightContext;
+ }
+ return NULL;
+}
+
+static JSBool
+find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)
+{
+ JSString *repstr;
+ size_t replen, skip;
+ jschar *dp, *ep;
+ JSSubString *sub;
+ JSObject *lambda;
+
+ lambda = rdata->lambda;
+ if (lambda) {
+ uintN argc, i, j, m, n, p;
+ jsval *invokevp, *sp;
+ void *mark;
+ JSBool ok;
+
+ /*
+ * Save the regExpStatics from the current regexp, since they may be
+ * clobbered by a RegExp usage in the lambda function. Note that all
+ * members of JSRegExpStatics are JSSubStrings, so not GC roots, save
+ * input, which is rooted otherwise via vp[1] in str_replace.
+ */
+ JSRegExpStatics save = cx->regExpStatics;
+ JSBool freeMoreParens = JS_FALSE;
+
+ /*
+ * In the lambda case, not only do we find the replacement string's
+ * length, we compute repstr and return it via rdata for use within
+ * do_replace. The lambda is called with arguments ($&, $1, $2, ...,
+ * index, input), i.e., all the properties of a regexp match array.
+ * For $&, etc., we must create string jsvals from cx->regExpStatics.
+ * We grab up stack space to keep the newborn strings GC-rooted.
+ */
+ p = rdata->base.regexp->parenCount;
+ argc = 1 + p + 2;
+ invokevp = js_AllocStack(cx, 2 + argc, &mark);
+ if (!invokevp)
+ return JS_FALSE;
+
+ /* Push lambda and its 'this' parameter. */
+ sp = invokevp;
+ *sp++ = OBJECT_TO_JSVAL(lambda);
+ *sp++ = OBJECT_TO_JSVAL(OBJ_GET_PARENT(cx, lambda));
+
+#define PUSH_REGEXP_STATIC(sub) \
+ JS_BEGIN_MACRO \
+ JSString *str = js_NewStringCopyN(cx, \
+ cx->regExpStatics.sub.chars, \
+ cx->regExpStatics.sub.length); \
+ if (!str) { \
+ ok = JS_FALSE; \
+ goto lambda_out; \
+ } \
+ *sp++ = STRING_TO_JSVAL(str); \
+ JS_END_MACRO
+
+ /* Push $&, $1, $2, ... */
+ PUSH_REGEXP_STATIC(lastMatch);
+ i = 0;
+ m = cx->regExpStatics.parenCount;
+ n = JS_MIN(m, 9);
+ for (j = 0; i < n; i++, j++)
+ PUSH_REGEXP_STATIC(parens[j]);
+ for (j = 0; i < m; i++, j++)
+ PUSH_REGEXP_STATIC(moreParens[j]);
+
+ /*
+ * We need to clear moreParens in the top-of-stack cx->regExpStatics
+ * to it won't be possibly realloc'ed, leaving the bottom-of-stack
+ * moreParens pointing to freed memory.
+ */
+ cx->regExpStatics.moreParens = NULL;
+ freeMoreParens = JS_TRUE;
+
+#undef PUSH_REGEXP_STATIC
+
+ /* Make sure to push undefined for any unmatched parens. */
+ for (; i < p; i++)
+ *sp++ = JSVAL_VOID;
+
+ /* Push match index and input string. */
+ *sp++ = INT_TO_JSVAL((jsint)cx->regExpStatics.leftContext.length);
+ *sp++ = STRING_TO_JSVAL(rdata->base.str);
+
+ ok = js_Invoke(cx, argc, invokevp, 0);
+ if (ok) {
+ /*
+ * NB: we count on the newborn string root to hold any string
+ * created by this js_ValueToString that would otherwise be GC-
+ * able, until we use rdata->repstr in do_replace.
+ */
+ repstr = js_ValueToString(cx, *invokevp);
+ if (!repstr) {
+ ok = JS_FALSE;
+ } else {
+ rdata->repstr = repstr;
+ *sizep = JSSTRING_LENGTH(repstr);
+ }
+ }
+
+ lambda_out:
+ js_FreeStack(cx, mark);
+ if (freeMoreParens)
+ JS_free(cx, cx->regExpStatics.moreParens);
+ cx->regExpStatics = save;
+ return ok;
+ }
+
+ repstr = rdata->repstr;
+ replen = JSSTRING_LENGTH(repstr);
+ for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
+ dp = js_strchr_limit(dp, '$', ep)) {
+ sub = interpret_dollar(cx, dp, ep, rdata, &skip);
+ if (sub) {
+ replen += sub->length - skip;
+ dp += skip;
+ }
+ else
+ dp++;
+ }
+ *sizep = replen;
+ return JS_TRUE;
+}
+
+static void
+do_replace(JSContext *cx, ReplaceData *rdata, jschar *chars)
+{
+ JSString *repstr;
+ jschar *bp, *cp, *dp, *ep;
+ size_t len, skip;
+ JSSubString *sub;
+
+ repstr = rdata->repstr;
+ bp = cp = JSSTRING_CHARS(repstr);
+ for (dp = rdata->dollar, ep = rdata->dollarEnd; dp;
+ dp = js_strchr_limit(dp, '$', ep)) {
+ len = dp - cp;
+ js_strncpy(chars, cp, len);
+ chars += len;
+ cp = dp;
+ sub = interpret_dollar(cx, dp, ep, rdata, &skip);
+ if (sub) {
+ len = sub->length;
+ js_strncpy(chars, sub->chars, len);
+ chars += len;
+ cp += skip;
+ dp += skip;
+ } else {
+ dp++;
+ }
+ }
+ js_strncpy(chars, cp, JSSTRING_LENGTH(repstr) - (cp - bp));
+}
+
+static void
+replace_destroy(JSContext *cx, GlobData *data)
+{
+ ReplaceData *rdata;
+
+ rdata = (ReplaceData *)data;
+ JS_free(cx, rdata->chars);
+ rdata->chars = NULL;
+}
+
+static JSBool
+replace_glob(JSContext *cx, jsint count, GlobData *data)
+{
+ ReplaceData *rdata;
+ JSString *str;
+ size_t leftoff, leftlen, replen, growth;
+ const jschar *left;
+ jschar *chars;
+
+ rdata = (ReplaceData *)data;
+ str = data->str;
+ leftoff = rdata->leftIndex;
+ left = JSSTRING_CHARS(str) + leftoff;
+ leftlen = cx->regExpStatics.lastMatch.chars - left;
+ rdata->leftIndex = cx->regExpStatics.lastMatch.chars - JSSTRING_CHARS(str);
+ rdata->leftIndex += cx->regExpStatics.lastMatch.length;
+ if (!find_replen(cx, rdata, &replen))
+ return JS_FALSE;
+ growth = leftlen + replen;
+ chars = (jschar *)
+ (rdata->chars
+ ? JS_realloc(cx, rdata->chars, (rdata->length + growth + 1)
+ * sizeof(jschar))
+ : JS_malloc(cx, (growth + 1) * sizeof(jschar)));
+ if (!chars)
+ return JS_FALSE;
+ rdata->chars = chars;
+ rdata->length += growth;
+ chars += rdata->index;
+ rdata->index += growth;
+ js_strncpy(chars, left, leftlen);
+ chars += leftlen;
+ do_replace(cx, rdata, chars);
+ return JS_TRUE;
+}
+
+static JSBool
+str_replace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *lambda;
+ JSString *repstr;
+
+ if (argc >= 2 && JS_TypeOfValue(cx, vp[3]) == JSTYPE_FUNCTION) {
+ lambda = JSVAL_TO_OBJECT(vp[3]);
+ repstr = NULL;
+ } else {
+ lambda = NULL;
+ repstr = ArgToRootedString(cx, argc, vp, 1);
+ if (!repstr)
+ return JS_FALSE;
+ }
+
+ return js_StringReplaceHelper(cx, argc, lambda, repstr, vp);
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_p_replace_str(JSContext* cx, JSString* str, JSObject* regexp, JSString* repstr)
+{
+ jsval vp[4] = {
+ JSVAL_NULL, STRING_TO_JSVAL(str), OBJECT_TO_JSVAL(regexp), STRING_TO_JSVAL(repstr)
+ };
+ if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(vp[0]));
+ return JSVAL_TO_STRING(vp[0]);
+}
+
+static JSString* FASTCALL
+String_p_replace_str2(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr)
+{
+ jsval vp[4] = {
+ JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr)
+ };
+ if (!js_StringReplaceHelper(cx, 2, NULL, repstr, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(vp[0]));
+ return JSVAL_TO_STRING(vp[0]);
+}
+
+static JSString* FASTCALL
+String_p_replace_str3(JSContext* cx, JSString* str, JSString* patstr, JSString* repstr,
+ JSString* flagstr)
+{
+ jsval vp[5] = {
+ JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(patstr), STRING_TO_JSVAL(repstr),
+ STRING_TO_JSVAL(flagstr)
+ };
+ if (!js_StringReplaceHelper(cx, 3, NULL, repstr, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(vp[0]));
+ return JSVAL_TO_STRING(vp[0]);
+}
+#endif
+
+JSBool
+js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
+ JSString *repstr, jsval *vp)
+{
+ ReplaceData rdata;
+ JSBool ok;
+ size_t leftlen, rightlen, length;
+ jschar *chars;
+ JSString *str;
+
+ /*
+ * For ECMA Edition 3, the first argument is to be converted to a string
+ * to match in a "flat" sense (without regular expression metachars having
+ * special meanings) UNLESS the first arg is a RegExp object.
+ */
+ rdata.base.flags = MODE_REPLACE | KEEP_REGEXP | FORCE_FLAT;
+ rdata.base.optarg = 2;
+
+ rdata.lambda = lambda;
+ rdata.repstr = repstr;
+ if (repstr) {
+ rdata.dollarEnd = JSSTRING_CHARS(repstr) + JSSTRING_LENGTH(repstr);
+ rdata.dollar = js_strchr_limit(JSSTRING_CHARS(repstr), '$',
+ rdata.dollarEnd);
+ } else {
+ rdata.dollar = rdata.dollarEnd = NULL;
+ }
+ rdata.chars = NULL;
+ rdata.length = 0;
+ rdata.index = 0;
+ rdata.leftIndex = 0;
+
+ ok = match_or_replace(cx, replace_glob, replace_destroy, &rdata.base,
+ argc, vp);
+ if (!ok)
+ return JS_FALSE;
+
+ if (!rdata.chars) {
+ if ((rdata.base.flags & GLOBAL_REGEXP) || *vp != JSVAL_TRUE) {
+ /* Didn't match even once. */
+ *vp = STRING_TO_JSVAL(rdata.base.str);
+ goto out;
+ }
+ leftlen = cx->regExpStatics.leftContext.length;
+ ok = find_replen(cx, &rdata, &length);
+ if (!ok)
+ goto out;
+ length += leftlen;
+ chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ js_strncpy(chars, cx->regExpStatics.leftContext.chars, leftlen);
+ do_replace(cx, &rdata, chars + leftlen);
+ rdata.chars = chars;
+ rdata.length = length;
+ }
+
+ rightlen = cx->regExpStatics.rightContext.length;
+ length = rdata.length + rightlen;
+ chars = (jschar *)
+ JS_realloc(cx, rdata.chars, (length + 1) * sizeof(jschar));
+ if (!chars) {
+ JS_free(cx, rdata.chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ js_strncpy(chars + rdata.length, cx->regExpStatics.rightContext.chars,
+ rightlen);
+ chars[length] = 0;
+
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ ok = JS_FALSE;
+ goto out;
+ }
+ *vp = STRING_TO_JSVAL(str);
+
+out:
+ /* If KEEP_REGEXP is still set, it's our job to destroy regexp now. */
+ if (rdata.base.flags & KEEP_REGEXP)
+ js_DestroyRegExp(cx, rdata.base.regexp);
+ return ok;
+}
+
+/*
+ * Subroutine used by str_split to find the next split point in str, starting
+ * at offset *ip and looking either for the separator substring given by sep, or
+ * for the next re match. In the re case, return the matched separator in *sep,
+ * and the possibly updated offset in *ip.
+ *
+ * Return -2 on error, -1 on end of string, >= 0 for a valid index of the next
+ * separator occurrence if found, or str->length if no separator is found.
+ */
+static jsint
+find_split(JSContext *cx, JSString *str, JSRegExp *re, jsint *ip,
+ JSSubString *sep)
+{
+ jsint i, j, k;
+ size_t length;
+ jschar *chars;
+
+ /*
+ * Stop if past end of string. If at end of string, we will compare the
+ * null char stored there (by js_NewString*) to sep->chars[j] in the while
+ * loop at the end of this function, so that
+ *
+ * "ab,".split(',') => ["ab", ""]
+ *
+ * and the resulting array converts back to the string "ab," for symmetry.
+ * However, we ape Perl and do this only if there is a sufficiently large
+ * limit argument (see str_split).
+ */
+ i = *ip;
+ length = JSSTRING_LENGTH(str);
+ if ((size_t)i > length)
+ return -1;
+
+ chars = JSSTRING_CHARS(str);
+
+ /*
+ * Match a regular expression against the separator at or above index i.
+ * Call js_ExecuteRegExp with true for the test argument. On successful
+ * match, get the separator from cx->regExpStatics.lastMatch.
+ */
+ if (re) {
+ size_t index;
+ jsval rval;
+
+ again:
+ /* JS1.2 deviated from Perl by never matching at end of string. */
+ index = (size_t)i;
+ if (!js_ExecuteRegExp(cx, re, str, &index, JS_TRUE, &rval))
+ return -2;
+ if (rval != JSVAL_TRUE) {
+ /* Mismatch: ensure our caller advances i past end of string. */
+ sep->length = 1;
+ return length;
+ }
+ i = (jsint)index;
+ *sep = cx->regExpStatics.lastMatch;
+ if (sep->length == 0) {
+ /*
+ * Empty string match: never split on an empty match at the start
+ * of a find_split cycle. Same rule as for an empty global match
+ * in match_or_replace.
+ */
+ if (i == *ip) {
+ /*
+ * "Bump-along" to avoid sticking at an empty match, but don't
+ * bump past end of string -- our caller must do that by adding
+ * sep->length to our return value.
+ */
+ if ((size_t)i == length)
+ return -1;
+ i++;
+ goto again;
+ }
+ if ((size_t)i == length) {
+ /*
+ * If there was a trivial zero-length match at the end of the
+ * split, then we shouldn't output the matched string at the end
+ * of the split array. See ECMA-262 Ed. 3, 15.5.4.14, Step 15.
+ */
+ sep->chars = NULL;
+ }
+ }
+ JS_ASSERT((size_t)i >= sep->length);
+ return i - sep->length;
+ }
+
+ /*
+ * Special case: if sep is the empty string, split str into one character
+ * substrings. Let our caller worry about whether to split once at end of
+ * string into an empty substring.
+ */
+ if (sep->length == 0)
+ return ((size_t)i == length) ? -1 : i + 1;
+
+ /*
+ * Now that we know sep is non-empty, search starting at i in str for an
+ * occurrence of all of sep's chars. If we find them, return the index of
+ * the first separator char. Otherwise, return length.
+ */
+ j = 0;
+ while ((size_t)(k = i + j) < length) {
+ if (chars[k] == sep->chars[j]) {
+ if ((size_t)++j == sep->length)
+ return i;
+ } else {
+ i++;
+ j = 0;
+ }
+ }
+ return k;
+}
+
+static JSBool
+str_split(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *sub;
+ JSObject *arrayobj;
+ jsval v;
+ JSBool ok, limited;
+ JSRegExp *re;
+ JSSubString *sep, tmp;
+ jsdouble d;
+ jsint i, j;
+ uint32 len, limit;
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ arrayobj = js_ConstructObject(cx, &js_ArrayClass, NULL, NULL, 0, NULL);
+ if (!arrayobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(arrayobj);
+
+ if (argc == 0) {
+ v = STRING_TO_JSVAL(str);
+ ok = OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(0), &v);
+ } else {
+ if (VALUE_IS_REGEXP(cx, vp[2])) {
+ re = (JSRegExp *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(vp[2]));
+ sep = &tmp;
+
+ /* Set a magic value so we can detect a successful re match. */
+ sep->chars = NULL;
+ sep->length = 0;
+ } else {
+ JSString *str2 = js_ValueToString(cx, vp[2]);
+ if (!str2)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(str2);
+
+ /*
+ * Point sep at a local copy of str2's header because find_split
+ * will modify sep->length.
+ */
+ JSSTRING_CHARS_AND_LENGTH(str2, tmp.chars, tmp.length);
+ sep = &tmp;
+ re = NULL;
+ }
+
+ /* Use the second argument as the split limit, if given. */
+ limited = (argc > 1) && !JSVAL_IS_VOID(vp[3]);
+ limit = 0; /* Avoid warning. */
+ if (limited) {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+
+ /* Clamp limit between 0 and 1 + string length. */
+ limit = js_DoubleToECMAUint32(d);
+ if (limit > JSSTRING_LENGTH(str))
+ limit = 1 + JSSTRING_LENGTH(str);
+ }
+
+ len = i = 0;
+ while ((j = find_split(cx, str, re, &i, sep)) >= 0) {
+ if (limited && len >= limit)
+ break;
+ sub = js_NewDependentString(cx, str, i, (size_t)(j - i));
+ if (!sub)
+ return JS_FALSE;
+ v = STRING_TO_JSVAL(sub);
+ if (!JS_SetElement(cx, arrayobj, len, &v))
+ return JS_FALSE;
+ len++;
+
+ /*
+ * Imitate perl's feature of including parenthesized substrings
+ * that matched part of the delimiter in the new array, after the
+ * split substring that was delimited.
+ */
+ if (re && sep->chars) {
+ uintN num;
+ JSSubString *parsub;
+
+ for (num = 0; num < cx->regExpStatics.parenCount; num++) {
+ if (limited && len >= limit)
+ break;
+ parsub = REGEXP_PAREN_SUBSTRING(&cx->regExpStatics, num);
+ sub = js_NewStringCopyN(cx, parsub->chars, parsub->length);
+ if (!sub)
+ return JS_FALSE;
+ v = STRING_TO_JSVAL(sub);
+ if (!JS_SetElement(cx, arrayobj, len, &v))
+ return JS_FALSE;
+ len++;
+ }
+ sep->chars = NULL;
+ }
+ i = j + sep->length;
+ }
+ ok = (j != -2);
+ }
+ return ok;
+}
+
+#ifdef JS_TRACER
+static JSObject* FASTCALL
+String_p_split(JSContext* cx, JSString* str, JSString* sepstr)
+{
+ // FIXME: Avoid building and then parsing this array.
+ jsval vp[4] = { JSVAL_NULL, STRING_TO_JSVAL(str), STRING_TO_JSVAL(sepstr), JSVAL_VOID };
+ if (!str_split(cx, 2, vp))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_OBJECT(vp[0]));
+ return JSVAL_TO_OBJECT(vp[0]);
+}
+#endif
+
+#if JS_HAS_PERL_SUBSTR
+static JSBool
+str_substr(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+ jsdouble d;
+ jsdouble length, begin, end;
+
+ NORMALIZE_THIS(cx, vp, str);
+ if (argc != 0) {
+ d = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ length = JSSTRING_LENGTH(str);
+ begin = js_DoubleToInteger(d);
+ if (begin < 0) {
+ begin += length;
+ if (begin < 0)
+ begin = 0;
+ } else if (begin > length) {
+ begin = length;
+ }
+
+ if (argc == 1) {
+ end = length;
+ } else {
+ d = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ end = js_DoubleToInteger(d);
+ if (end < 0)
+ end = 0;
+ end += begin;
+ if (end > length)
+ end = length;
+ }
+
+ str = js_NewDependentString(cx, str,
+ (size_t)begin,
+ (size_t)(end - begin));
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+#endif /* JS_HAS_PERL_SUBSTR */
+
+/*
+ * Python-esque sequence operations.
+ */
+static JSBool
+str_concat(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str, *str2;
+ jsval *argv;
+ uintN i;
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ for (i = 0, argv = vp + 2; i < argc; i++) {
+ str2 = js_ValueToString(cx, argv[i]);
+ if (!str2)
+ return JS_FALSE;
+ argv[i] = STRING_TO_JSVAL(str2);
+
+ str = js_ConcatStrings(cx, str, str2);
+ if (!str)
+ return JS_FALSE;
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_p_concat_1int(JSContext* cx, JSString* str, int32 i)
+{
+ // FIXME: should be able to use stack buffer and avoid istr...
+ JSString* istr = js_NumberToString(cx, i);
+ if (!istr)
+ return NULL;
+ return js_ConcatStrings(cx, str, istr);
+}
+
+static JSString* FASTCALL
+String_p_concat_2str(JSContext* cx, JSString* str, JSString* a, JSString* b)
+{
+ str = js_ConcatStrings(cx, str, a);
+ if (str)
+ return js_ConcatStrings(cx, str, b);
+ return NULL;
+}
+
+static JSString* FASTCALL
+String_p_concat_3str(JSContext* cx, JSString* str, JSString* a, JSString* b, JSString* c)
+{
+ str = js_ConcatStrings(cx, str, a);
+ if (str) {
+ str = js_ConcatStrings(cx, str, b);
+ if (str)
+ return js_ConcatStrings(cx, str, c);
+ }
+ return NULL;
+}
+#endif
+
+static JSBool
+str_slice(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval t, v;
+ JSString *str;
+
+ t = vp[1];
+ v = vp[2];
+ if (argc == 1 && JSVAL_IS_STRING(t) && JSVAL_IS_INT(v)) {
+ size_t begin, end, length;
+
+ str = JSVAL_TO_STRING(t);
+ begin = JSVAL_TO_INT(v);
+ end = JSSTRING_LENGTH(str);
+ if (begin <= end) {
+ length = end - begin;
+ if (length == 0) {
+ str = cx->runtime->emptyString;
+ } else {
+ str = (length == 1)
+ ? js_GetUnitString(cx, str, begin)
+ : js_NewDependentString(cx, str, begin, length);
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+ }
+ }
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ if (argc != 0) {
+ double begin, end, length;
+
+ begin = js_ValueToNumber(cx, &vp[2]);
+ if (JSVAL_IS_NULL(vp[2]))
+ return JS_FALSE;
+ begin = js_DoubleToInteger(begin);
+ length = JSSTRING_LENGTH(str);
+ if (begin < 0) {
+ begin += length;
+ if (begin < 0)
+ begin = 0;
+ } else if (begin > length) {
+ begin = length;
+ }
+
+ if (argc == 1) {
+ end = length;
+ } else {
+ end = js_ValueToNumber(cx, &vp[3]);
+ if (JSVAL_IS_NULL(vp[3]))
+ return JS_FALSE;
+ end = js_DoubleToInteger(end);
+ if (end < 0) {
+ end += length;
+ if (end < 0)
+ end = 0;
+ } else if (end > length) {
+ end = length;
+ }
+ if (end < begin)
+ end = begin;
+ }
+
+ str = js_NewDependentString(cx, str,
+ (size_t)begin,
+ (size_t)(end - begin));
+ if (!str)
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#if JS_HAS_STR_HTML_HELPERS
+/*
+ * HTML composition aids.
+ */
+static JSBool
+tagify(JSContext *cx, const char *begin, JSString *param, const char *end,
+ jsval *vp)
+{
+ JSString *str;
+ jschar *tagbuf;
+ size_t beglen, endlen, parlen, taglen;
+ size_t i, j;
+
+ NORMALIZE_THIS(cx, vp, str);
+
+ if (!end)
+ end = begin;
+
+ beglen = strlen(begin);
+ taglen = 1 + beglen + 1; /* '<begin' + '>' */
+ parlen = 0; /* Avoid warning. */
+ if (param) {
+ parlen = JSSTRING_LENGTH(param);
+ taglen += 2 + parlen + 1; /* '="param"' */
+ }
+ endlen = strlen(end);
+ taglen += JSSTRING_LENGTH(str) + 2 + endlen + 1; /* 'str</end>' */
+
+ if (taglen >= ~(size_t)0 / sizeof(jschar)) {
+ js_ReportAllocationOverflow(cx);
+ return JS_FALSE;
+ }
+
+ tagbuf = (jschar *) JS_malloc(cx, (taglen + 1) * sizeof(jschar));
+ if (!tagbuf)
+ return JS_FALSE;
+
+ j = 0;
+ tagbuf[j++] = '<';
+ for (i = 0; i < beglen; i++)
+ tagbuf[j++] = (jschar)begin[i];
+ if (param) {
+ tagbuf[j++] = '=';
+ tagbuf[j++] = '"';
+ js_strncpy(&tagbuf[j], JSSTRING_CHARS(param), parlen);
+ j += parlen;
+ tagbuf[j++] = '"';
+ }
+ tagbuf[j++] = '>';
+ js_strncpy(&tagbuf[j], JSSTRING_CHARS(str), JSSTRING_LENGTH(str));
+ j += JSSTRING_LENGTH(str);
+ tagbuf[j++] = '<';
+ tagbuf[j++] = '/';
+ for (i = 0; i < endlen; i++)
+ tagbuf[j++] = (jschar)end[i];
+ tagbuf[j++] = '>';
+ JS_ASSERT(j == taglen);
+ tagbuf[j] = 0;
+
+ str = js_NewString(cx, tagbuf, taglen);
+ if (!str) {
+ free((char *)tagbuf);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+tagify_value(JSContext *cx, uintN argc, jsval *vp,
+ const char *begin, const char *end)
+{
+ JSString *param;
+
+ param = ArgToRootedString(cx, argc, vp, 0);
+ if (!param)
+ return JS_FALSE;
+ return tagify(cx, begin, param, end, vp);
+}
+
+static JSBool
+str_bold(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "b", NULL, NULL, vp);
+}
+
+static JSBool
+str_italics(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "i", NULL, NULL, vp);
+}
+
+static JSBool
+str_fixed(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "tt", NULL, NULL, vp);
+}
+
+static JSBool
+str_fontsize(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "font size", "font");
+}
+
+static JSBool
+str_fontcolor(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "font color", "font");
+}
+
+static JSBool
+str_link(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "a href", "a");
+}
+
+static JSBool
+str_anchor(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify_value(cx, argc, vp, "a name", "a");
+}
+
+static JSBool
+str_strike(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "strike", NULL, NULL, vp);
+}
+
+static JSBool
+str_small(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "small", NULL, NULL, vp);
+}
+
+static JSBool
+str_big(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "big", NULL, NULL, vp);
+}
+
+static JSBool
+str_blink(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "blink", NULL, NULL, vp);
+}
+
+static JSBool
+str_sup(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "sup", NULL, NULL, vp);
+}
+
+static JSBool
+str_sub(JSContext *cx, uintN argc, jsval *vp)
+{
+ return tagify(cx, "sub", NULL, NULL, vp);
+}
+#endif /* JS_HAS_STR_HTML_HELPERS */
+
+#ifdef JS_TRACER
+JSString* FASTCALL
+js_String_getelem(JSContext* cx, JSString* str, int32 i)
+{
+ if ((size_t)i >= JSSTRING_LENGTH(str))
+ return NULL;
+ return js_GetUnitString(cx, str, (size_t)i);
+}
+#endif
+
+JS_DEFINE_CALLINFO_2(extern, BOOL, js_EqualStrings, STRING, STRING, 1, 1)
+JS_DEFINE_CALLINFO_2(extern, INT32, js_CompareStrings, STRING, STRING, 1, 1)
+
+JS_DEFINE_TRCINFO_1(str_toString,
+ (2, (extern, STRING_FAIL, String_p_toString, CONTEXT, THIS, 1, 1)))
+JS_DEFINE_TRCINFO_2(str_substring,
+ (4, (static, STRING_FAIL, String_p_substring, CONTEXT, THIS_STRING, INT32, INT32, 1, 1)),
+ (3, (static, STRING_FAIL, String_p_substring_1, CONTEXT, THIS_STRING, INT32, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_charAt,
+ (3, (extern, STRING_FAIL, js_String_getelem, CONTEXT, THIS_STRING, INT32, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_charCodeAt,
+ (2, (extern, INT32_FAIL, js_String_p_charCodeAt, THIS_STRING, INT32, 1, 1)))
+JS_DEFINE_TRCINFO_4(str_concat,
+ (3, (static, STRING_FAIL, String_p_concat_1int, CONTEXT, THIS_STRING, INT32, 1, 1)),
+ (3, (extern, STRING_FAIL, js_ConcatStrings, CONTEXT, THIS_STRING, STRING, 1, 1)),
+ (4, (static, STRING_FAIL, String_p_concat_2str, CONTEXT, THIS_STRING, STRING, STRING, 1, 1)),
+ (5, (static, STRING_FAIL, String_p_concat_3str, CONTEXT, THIS_STRING, STRING, STRING, STRING, 1, 1)))
+JS_DEFINE_TRCINFO_2(str_match,
+ (4, (static, OBJECT_FAIL_VOID, String_p_match, CONTEXT, THIS_STRING, PC, REGEXP, 1, 1)),
+ (4, (static, OBJECT_FAIL_VOID, String_p_match_obj, CONTEXT, THIS, PC, REGEXP, 1, 1)))
+JS_DEFINE_TRCINFO_3(str_replace,
+ (4, (static, STRING_FAIL, String_p_replace_str, CONTEXT, THIS_STRING, REGEXP, STRING, 1, 1)),
+ (4, (static, STRING_FAIL, String_p_replace_str2, CONTEXT, THIS_STRING, STRING, STRING, 1, 1)),
+ (5, (static, STRING_FAIL, String_p_replace_str3, CONTEXT, THIS_STRING, STRING, STRING, STRING, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_split,
+ (3, (static, OBJECT_FAIL_NULL, String_p_split, CONTEXT, THIS_STRING, STRING, 0, 0)))
+JS_DEFINE_TRCINFO_1(str_toLowerCase,
+ (2, (extern, STRING_FAIL, js_toLowerCase, CONTEXT, THIS_STRING, 1, 1)))
+JS_DEFINE_TRCINFO_1(str_toUpperCase,
+ (2, (extern, STRING_FAIL, js_toUpperCase, CONTEXT, THIS_STRING, 1, 1)))
+
+#define GENERIC JSFUN_GENERIC_NATIVE
+#define PRIMITIVE JSFUN_THISP_PRIMITIVE
+#define GENERIC_PRIMITIVE (GENERIC | PRIMITIVE)
+
+static JSFunctionSpec string_methods[] = {
+#if JS_HAS_TOSOURCE
+ JS_FN("quote", str_quote, 0,GENERIC_PRIMITIVE),
+ JS_FN(js_toSource_str, str_toSource, 0,JSFUN_THISP_STRING),
+#endif
+
+ /* Java-like methods. */
+ JS_TN(js_toString_str, str_toString, 0,JSFUN_THISP_STRING, str_toString_trcinfo),
+ JS_FN(js_valueOf_str, str_toString, 0,JSFUN_THISP_STRING),
+ JS_FN(js_toJSON_str, str_toString, 0,JSFUN_THISP_STRING),
+ JS_TN("substring", str_substring, 2,GENERIC_PRIMITIVE, str_substring_trcinfo),
+ JS_TN("toLowerCase", str_toLowerCase, 0,GENERIC_PRIMITIVE, str_toLowerCase_trcinfo),
+ JS_TN("toUpperCase", str_toUpperCase, 0,GENERIC_PRIMITIVE, str_toUpperCase_trcinfo),
+ JS_TN("charAt", str_charAt, 1,GENERIC_PRIMITIVE, str_charAt_trcinfo),
+ JS_TN("charCodeAt", str_charCodeAt, 1,GENERIC_PRIMITIVE, str_charCodeAt_trcinfo),
+ JS_FN("indexOf", str_indexOf, 1,GENERIC_PRIMITIVE),
+ JS_FN("lastIndexOf", str_lastIndexOf, 1,GENERIC_PRIMITIVE),
+ JS_FN("trim", str_trim, 0,GENERIC_PRIMITIVE),
+ JS_FN("trimLeft", str_trimLeft, 0,GENERIC_PRIMITIVE),
+ JS_FN("trimRight", str_trimRight, 0,GENERIC_PRIMITIVE),
+ JS_FN("toLocaleLowerCase", str_toLocaleLowerCase, 0,GENERIC_PRIMITIVE),
+ JS_FN("toLocaleUpperCase", str_toLocaleUpperCase, 0,GENERIC_PRIMITIVE),
+ JS_FN("localeCompare", str_localeCompare, 1,GENERIC_PRIMITIVE),
+
+ /* Perl-ish methods (search is actually Python-esque). */
+ JS_TN("match", str_match, 1,GENERIC_PRIMITIVE, str_match_trcinfo),
+ JS_FN("search", str_search, 1,GENERIC_PRIMITIVE),
+ JS_TN("replace", str_replace, 2,GENERIC_PRIMITIVE, str_replace_trcinfo),
+ JS_TN("split", str_split, 2,GENERIC_PRIMITIVE, str_split_trcinfo),
+#if JS_HAS_PERL_SUBSTR
+ JS_FN("substr", str_substr, 2,GENERIC_PRIMITIVE),
+#endif
+
+ /* Python-esque sequence methods. */
+ JS_TN("concat", str_concat, 1,GENERIC_PRIMITIVE, str_concat_trcinfo),
+ JS_FN("slice", str_slice, 2,GENERIC_PRIMITIVE),
+
+ /* HTML string methods. */
+#if JS_HAS_STR_HTML_HELPERS
+ JS_FN("bold", str_bold, 0,PRIMITIVE),
+ JS_FN("italics", str_italics, 0,PRIMITIVE),
+ JS_FN("fixed", str_fixed, 0,PRIMITIVE),
+ JS_FN("fontsize", str_fontsize, 1,PRIMITIVE),
+ JS_FN("fontcolor", str_fontcolor, 1,PRIMITIVE),
+ JS_FN("link", str_link, 1,PRIMITIVE),
+ JS_FN("anchor", str_anchor, 1,PRIMITIVE),
+ JS_FN("strike", str_strike, 0,PRIMITIVE),
+ JS_FN("small", str_small, 0,PRIMITIVE),
+ JS_FN("big", str_big, 0,PRIMITIVE),
+ JS_FN("blink", str_blink, 0,PRIMITIVE),
+ JS_FN("sup", str_sup, 0,PRIMITIVE),
+ JS_FN("sub", str_sub, 0,PRIMITIVE),
+#endif
+
+ JS_FS_END
+};
+
+static JSBool
+String(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ JSString *str;
+
+ if (argc > 0) {
+ str = js_ValueToString(cx, argv[0]);
+ if (!str)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(str);
+ } else {
+ str = cx->runtime->emptyString;
+ }
+ if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+ }
+ STOBJ_SET_SLOT(obj, JSSLOT_PRIVATE, STRING_TO_JSVAL(str));
+ return JS_TRUE;
+}
+
+static JSBool
+str_fromCharCode(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval *argv;
+ uintN i;
+ uint16 code;
+ jschar *chars;
+ JSString *str;
+
+ argv = vp + 2;
+ JS_ASSERT(argc < ARRAY_INIT_LIMIT);
+ if (argc == 1 &&
+ (code = js_ValueToUint16(cx, &argv[0])) < UNIT_STRING_LIMIT) {
+ str = js_GetUnitStringForChar(cx, code);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+ }
+ chars = (jschar *) JS_malloc(cx, (argc + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ for (i = 0; i < argc; i++) {
+ code = js_ValueToUint16(cx, &argv[i]);
+ if (JSVAL_IS_NULL(argv[i])) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ chars[i] = (jschar)code;
+ }
+ chars[i] = 0;
+ str = js_NewString(cx, chars, argc);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+#ifdef JS_TRACER
+static JSString* FASTCALL
+String_fromCharCode(JSContext* cx, int32 i)
+{
+ JS_ASSERT(JS_ON_TRACE(cx));
+ jschar c = (jschar)i;
+ if (c < UNIT_STRING_LIMIT)
+ return js_GetUnitStringForChar(cx, c);
+ return js_NewStringCopyN(cx, &c, 1);
+}
+#endif
+
+JS_DEFINE_TRCINFO_1(str_fromCharCode,
+ (2, (static, STRING_FAIL, String_fromCharCode, CONTEXT, INT32, 1, 1)))
+
+static JSFunctionSpec string_static_methods[] = {
+ JS_TN("fromCharCode", str_fromCharCode, 1, 0, str_fromCharCode_trcinfo),
+ JS_FS_END
+};
+
+static JSHashNumber
+js_hash_string_pointer(const void *key)
+{
+ return (JSHashNumber)JS_PTR_TO_UINT32(key) >> JSVAL_TAGBITS;
+}
+
+JSBool
+js_InitRuntimeStringState(JSContext *cx)
+{
+ JSRuntime *rt;
+
+ rt = cx->runtime;
+ rt->emptyString = ATOM_TO_STRING(rt->atomState.emptyAtom);
+ return JS_TRUE;
+}
+
+JSBool
+js_InitDeflatedStringCache(JSRuntime *rt)
+{
+ JSHashTable *cache;
+
+ /* Initialize string cache */
+ JS_ASSERT(!rt->deflatedStringCache);
+ cache = JS_NewHashTable(8, js_hash_string_pointer,
+ JS_CompareValues, JS_CompareValues,
+ NULL, NULL);
+ if (!cache)
+ return JS_FALSE;
+ rt->deflatedStringCache = cache;
+
+#ifdef JS_THREADSAFE
+ JS_ASSERT(!rt->deflatedStringCacheLock);
+ rt->deflatedStringCacheLock = JS_NEW_LOCK();
+ if (!rt->deflatedStringCacheLock)
+ return JS_FALSE;
+#endif
+ return JS_TRUE;
+}
+
+#define UNIT_STRING_SPACE(sp) ((jschar *) ((sp) + UNIT_STRING_LIMIT))
+#define UNIT_STRING_SPACE_RT(rt) UNIT_STRING_SPACE((rt)->unitStrings)
+
+#define IN_UNIT_STRING_SPACE(sp,cp) \
+ ((size_t)((cp) - UNIT_STRING_SPACE(sp)) < 2 * UNIT_STRING_LIMIT)
+#define IN_UNIT_STRING_SPACE_RT(rt,cp) \
+ IN_UNIT_STRING_SPACE((rt)->unitStrings, cp)
+
+JSString *
+js_GetUnitStringForChar(JSContext *cx, jschar c)
+{
+ jschar *cp, i;
+ JSRuntime *rt;
+ JSString **sp;
+
+ JS_ASSERT(c < UNIT_STRING_LIMIT);
+ rt = cx->runtime;
+ if (!rt->unitStrings) {
+ sp = (JSString **) calloc(UNIT_STRING_LIMIT * sizeof(JSString *) +
+ UNIT_STRING_LIMIT * 2 * sizeof(jschar),
+ 1);
+ if (!sp) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ cp = UNIT_STRING_SPACE(sp);
+ for (i = 0; i < UNIT_STRING_LIMIT; i++) {
+ *cp = i;
+ cp += 2;
+ }
+ JS_LOCK_GC(rt);
+ if (!rt->unitStrings) {
+ rt->unitStrings = sp;
+ JS_UNLOCK_GC(rt);
+ } else {
+ JS_UNLOCK_GC(rt);
+ free(sp);
+ }
+ }
+ if (!rt->unitStrings[c]) {
+ JSString *str;
+
+ cp = UNIT_STRING_SPACE_RT(rt);
+ str = js_NewString(cx, cp + 2 * c, 1);
+ if (!str)
+ return NULL;
+ JS_LOCK_GC(rt);
+ if (!rt->unitStrings[c])
+ rt->unitStrings[c] = str;
+ JS_UNLOCK_GC(rt);
+ }
+ return rt->unitStrings[c];
+}
+
+JSString *
+js_GetUnitString(JSContext *cx, JSString *str, size_t index)
+{
+ jschar c;
+
+ JS_ASSERT(index < JSSTRING_LENGTH(str));
+ c = JSSTRING_CHARS(str)[index];
+ if (c >= UNIT_STRING_LIMIT)
+ return js_NewDependentString(cx, str, index, 1);
+ return js_GetUnitStringForChar(cx, c);
+}
+
+void
+js_FinishUnitStrings(JSRuntime *rt)
+{
+ free(rt->unitStrings);
+ rt->unitStrings = NULL;
+}
+
+void
+js_FinishRuntimeStringState(JSContext *cx)
+{
+ cx->runtime->emptyString = NULL;
+}
+
+void
+js_FinishDeflatedStringCache(JSRuntime *rt)
+{
+ if (rt->deflatedStringCache) {
+ JS_HashTableDestroy(rt->deflatedStringCache);
+ rt->deflatedStringCache = NULL;
+ }
+#ifdef JS_THREADSAFE
+ if (rt->deflatedStringCacheLock) {
+ JS_DESTROY_LOCK(rt->deflatedStringCacheLock);
+ rt->deflatedStringCacheLock = NULL;
+ }
+#endif
+}
+
+JSObject *
+js_InitStringClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ /* Define the escape, unescape functions in the global object. */
+ if (!JS_DefineFunctions(cx, obj, string_functions))
+ return NULL;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_StringClass, String, 1,
+ string_props, string_methods,
+ NULL, string_static_methods);
+ if (!proto)
+ return NULL;
+ STOBJ_SET_SLOT(proto, JSSLOT_PRIVATE,
+ STRING_TO_JSVAL(cx->runtime->emptyString));
+ return proto;
+}
+
+JSString *
+js_NewString(JSContext *cx, jschar *chars, size_t length)
+{
+ JSString *str;
+
+ if (length > JSSTRING_LENGTH_MASK) {
+ js_ReportAllocationOverflow(cx);
+ return NULL;
+ }
+
+ str = (JSString *) js_NewGCThing(cx, GCX_STRING, sizeof(JSString));
+ if (!str)
+ return NULL;
+ JSFLATSTR_INIT(str, chars, length);
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_METER(rt, liveStrings);
+ JS_RUNTIME_METER(rt, totalStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->lengthSum += (double)length,
+ rt->lengthSquaredSum += (double)length * (double)length));
+ }
+#endif
+ return str;
+}
+
+JSString *
+js_NewDependentString(JSContext *cx, JSString *base, size_t start,
+ size_t length)
+{
+ JSString *ds;
+
+ if (length == 0)
+ return cx->runtime->emptyString;
+
+ if (start == 0 && length == JSSTRING_LENGTH(base))
+ return base;
+
+ if (start > JSSTRDEP_START_MASK ||
+ (start != 0 && length > JSSTRDEP_LENGTH_MASK)) {
+ return js_NewStringCopyN(cx, JSSTRING_CHARS(base) + start, length);
+ }
+
+ ds = (JSString *)js_NewGCThing(cx, GCX_STRING, sizeof(JSString));
+ if (!ds)
+ return NULL;
+ if (start == 0)
+ JSPREFIX_INIT(ds, base, length);
+ else
+ JSSTRDEP_INIT(ds, base, start, length);
+#ifdef DEBUG
+ {
+ JSRuntime *rt = cx->runtime;
+ JS_RUNTIME_METER(rt, liveDependentStrings);
+ JS_RUNTIME_METER(rt, totalDependentStrings);
+ JS_RUNTIME_METER(rt, liveStrings);
+ JS_RUNTIME_METER(rt, totalStrings);
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->strdepLengthSum += (double)length,
+ rt->strdepLengthSquaredSum += (double)length * (double)length));
+ JS_LOCK_RUNTIME_VOID(rt,
+ (rt->lengthSum += (double)length,
+ rt->lengthSquaredSum += (double)length * (double)length));
+ }
+#endif
+ return ds;
+}
+
+#ifdef DEBUG
+#include <math.h>
+
+void printJSStringStats(JSRuntime *rt)
+{
+ double mean, sigma;
+
+ mean = JS_MeanAndStdDev(rt->totalStrings, rt->lengthSum,
+ rt->lengthSquaredSum, &sigma);
+
+ fprintf(stderr, "%lu total strings, mean length %g (sigma %g)\n",
+ (unsigned long)rt->totalStrings, mean, sigma);
+
+ mean = JS_MeanAndStdDev(rt->totalDependentStrings, rt->strdepLengthSum,
+ rt->strdepLengthSquaredSum, &sigma);
+
+ fprintf(stderr, "%lu total dependent strings, mean length %g (sigma %g)\n",
+ (unsigned long)rt->totalDependentStrings, mean, sigma);
+}
+#endif
+
+JSString *
+js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n)
+{
+ jschar *news;
+ JSString *str;
+
+ news = (jschar *) JS_malloc(cx, (n + 1) * sizeof(jschar));
+ if (!news)
+ return NULL;
+ js_strncpy(news, s, n);
+ news[n] = 0;
+ str = js_NewString(cx, news, n);
+ if (!str)
+ JS_free(cx, news);
+ return str;
+}
+
+JSString *
+js_NewStringCopyZ(JSContext *cx, const jschar *s)
+{
+ size_t n, m;
+ jschar *news;
+ JSString *str;
+
+ n = js_strlen(s);
+ m = (n + 1) * sizeof(jschar);
+ news = (jschar *) JS_malloc(cx, m);
+ if (!news)
+ return NULL;
+ memcpy(news, s, m);
+ str = js_NewString(cx, news, n);
+ if (!str)
+ JS_free(cx, news);
+ return str;
+}
+
+void
+js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str)
+{
+ JSHashNumber hash;
+ JSHashEntry *he, **hep;
+
+ hash = js_hash_string_pointer(str);
+ JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
+ hep = JS_HashTableRawLookup(rt->deflatedStringCache, hash, str);
+ he = *hep;
+ if (he) {
+#ifdef DEBUG
+ rt->deflatedStringCacheBytes -= JSSTRING_LENGTH(str);
+#endif
+ free(he->value);
+ JS_HashTableRawRemove(rt->deflatedStringCache, hep, he);
+ }
+ JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
+}
+
+static JSStringFinalizeOp str_finalizers[GCX_NTYPES - GCX_EXTERNAL_STRING] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+intN
+js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
+ JSStringFinalizeOp newop)
+{
+ uintN i;
+
+ for (i = 0; i != JS_ARRAY_LENGTH(str_finalizers); i++) {
+ if (str_finalizers[i] == oldop) {
+ str_finalizers[i] = newop;
+ return (intN) i;
+ }
+ }
+ return -1;
+}
+
+/*
+ * cx is NULL when we are called from js_FinishAtomState to force the
+ * finalization of the permanently interned strings.
+ */
+void
+js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx)
+{
+ jschar *chars;
+ JSBool valid;
+ JSStringFinalizeOp finalizer;
+
+ JS_RUNTIME_UNMETER(rt, liveStrings);
+ if (JSSTRING_IS_DEPENDENT(str)) {
+ /* A dependent string can not be external and must be valid. */
+ JS_ASSERT(type < 0);
+ JS_ASSERT(JSSTRDEP_BASE(str));
+ JS_RUNTIME_UNMETER(rt, liveDependentStrings);
+ valid = JS_TRUE;
+ } else {
+ /* A stillborn string has null chars, so is not valid. */
+ chars = JSFLATSTR_CHARS(str);
+ valid = (chars != NULL);
+ if (valid) {
+ if (IN_UNIT_STRING_SPACE_RT(rt, chars)) {
+ JS_ASSERT(rt->unitStrings[*chars] == str);
+ JS_ASSERT(type < 0);
+ rt->unitStrings[*chars] = NULL;
+ } else if (type < 0) {
+ free(chars);
+ } else {
+ JS_ASSERT((uintN) type < JS_ARRAY_LENGTH(str_finalizers));
+ finalizer = str_finalizers[type];
+ if (finalizer) {
+ /*
+ * Assume that the finalizer for the permanently interned
+ * string knows how to deal with null context.
+ */
+ finalizer(cx, str);
+ }
+ }
+ }
+ }
+ if (valid)
+ js_PurgeDeflatedStringCache(rt, str);
+}
+
+JS_FRIEND_API(const char *)
+js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun)
+{
+ JSString *str;
+
+ str = v2sfun(cx, v);
+ if (!str)
+ return NULL;
+ str = js_QuoteString(cx, str, 0);
+ if (!str)
+ return NULL;
+ return js_GetStringBytes(cx, str);
+}
+
+JS_FRIEND_API(JSString *)
+js_ValueToString(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSString *str;
+
+ if (JSVAL_IS_OBJECT(v)) {
+ obj = JSVAL_TO_OBJECT(v);
+ if (!obj)
+ return ATOM_TO_STRING(cx->runtime->atomState.nullAtom);
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+ return NULL;
+ }
+ if (JSVAL_IS_STRING(v)) {
+ str = JSVAL_TO_STRING(v);
+ } else if (JSVAL_IS_INT(v)) {
+ str = js_NumberToString(cx, JSVAL_TO_INT(v));
+ } else if (JSVAL_IS_DOUBLE(v)) {
+ str = js_NumberToString(cx, *JSVAL_TO_DOUBLE(v));
+ } else if (JSVAL_IS_BOOLEAN(v)) {
+ str = js_BooleanToString(cx, JSVAL_TO_BOOLEAN(v));
+ } else {
+ str = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ }
+ return str;
+}
+
+JS_FRIEND_API(JSString *)
+js_ValueToSource(JSContext *cx, jsval v)
+{
+ JSTempValueRooter tvr;
+ JSString *str;
+
+ if (JSVAL_IS_VOID(v))
+ return ATOM_TO_STRING(cx->runtime->atomState.void0Atom);
+ if (JSVAL_IS_STRING(v))
+ return js_QuoteString(cx, JSVAL_TO_STRING(v), '"');
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ /* Special case to preserve negative zero, _contra_ toString. */
+ if (JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v))) {
+ /* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
+ static const jschar js_negzero_ucNstr[] = {'-', '0'};
+
+ return js_NewStringCopyN(cx, js_negzero_ucNstr, 2);
+ }
+ return js_ValueToString(cx, v);
+ }
+
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v),
+ cx->runtime->atomState.toSourceAtom,
+ 0, NULL, &tvr.u.value)) {
+ str = NULL;
+ } else {
+ str = js_ValueToString(cx, tvr.u.value);
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return str;
+}
+
+/*
+ * str is not necessarily a GC thing here.
+ */
+uint32
+js_HashString(JSString *str)
+{
+ const jschar *s;
+ size_t n;
+ uint32 h;
+
+ JSSTRING_CHARS_AND_LENGTH(str, s, n);
+ for (h = 0; n; s++, n--)
+ h = JS_ROTATE_LEFT32(h, 4) ^ *s;
+ return h;
+}
+
+/*
+ * str is not necessarily a GC thing here.
+ */
+JSBool JS_FASTCALL
+js_EqualStrings(JSString *str1, JSString *str2)
+{
+ size_t n;
+ const jschar *s1, *s2;
+
+ JS_ASSERT(str1);
+ JS_ASSERT(str2);
+
+ /* Fast case: pointer equality could be a quick win. */
+ if (str1 == str2)
+ return JS_TRUE;
+
+ n = JSSTRING_LENGTH(str1);
+ if (n != JSSTRING_LENGTH(str2))
+ return JS_FALSE;
+
+ if (n == 0)
+ return JS_TRUE;
+
+ s1 = JSSTRING_CHARS(str1), s2 = JSSTRING_CHARS(str2);
+ do {
+ if (*s1 != *s2)
+ return JS_FALSE;
+ ++s1, ++s2;
+ } while (--n != 0);
+
+ return JS_TRUE;
+}
+
+int32 JS_FASTCALL
+js_CompareStrings(JSString *str1, JSString *str2)
+{
+ size_t l1, l2, n, i;
+ const jschar *s1, *s2;
+ intN cmp;
+
+ JS_ASSERT(str1);
+ JS_ASSERT(str2);
+
+ /* Fast case: pointer equality could be a quick win. */
+ if (str1 == str2)
+ return 0;
+
+ JSSTRING_CHARS_AND_LENGTH(str1, s1, l1);
+ JSSTRING_CHARS_AND_LENGTH(str2, s2, l2);
+ n = JS_MIN(l1, l2);
+ for (i = 0; i < n; i++) {
+ cmp = s1[i] - s2[i];
+ if (cmp != 0)
+ return cmp;
+ }
+ return (intN)(l1 - l2);
+}
+
+size_t
+js_strlen(const jschar *s)
+{
+ const jschar *t;
+
+ for (t = s; *t != 0; t++)
+ continue;
+ return (size_t)(t - s);
+}
+
+jschar *
+js_strchr(const jschar *s, jschar c)
+{
+ while (*s != 0) {
+ if (*s == c)
+ return (jschar *)s;
+ s++;
+ }
+ return NULL;
+}
+
+jschar *
+js_strchr_limit(const jschar *s, jschar c, const jschar *limit)
+{
+ while (s < limit) {
+ if (*s == c)
+ return (jschar *)s;
+ s++;
+ }
+ return NULL;
+}
+
+const jschar *
+js_SkipWhiteSpace(const jschar *s, const jschar *end)
+{
+ JS_ASSERT(s <= end);
+ while (s != end && JS_ISSPACE(*s))
+ s++;
+ return s;
+}
+
+jschar *
+js_InflateString(JSContext *cx, const char *bytes, size_t *lengthp)
+{
+ size_t nbytes, nchars, i;
+ jschar *chars;
+#ifdef DEBUG
+ JSBool ok;
+#endif
+
+ nbytes = *lengthp;
+ if (js_CStringsAreUTF8) {
+ if (!js_InflateStringToBuffer(cx, bytes, nbytes, NULL, &nchars))
+ goto bad;
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof (jschar));
+ if (!chars)
+ goto bad;
+#ifdef DEBUG
+ ok =
+#endif
+ js_InflateStringToBuffer(cx, bytes, nbytes, chars, &nchars);
+ JS_ASSERT(ok);
+ } else {
+ nchars = nbytes;
+ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar));
+ if (!chars)
+ goto bad;
+ for (i = 0; i < nchars; i++)
+ chars[i] = (unsigned char) bytes[i];
+ }
+ *lengthp = nchars;
+ chars[nchars] = 0;
+ return chars;
+
+ bad:
+ /*
+ * For compatibility with callers of JS_DecodeBytes we must zero lengthp
+ * on errors.
+ */
+ *lengthp = 0;
+ return NULL;
+}
+
+/*
+ * May be called with null cx by js_GetStringBytes, see below.
+ */
+char *
+js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
+{
+ size_t nbytes, i;
+ char *bytes;
+#ifdef DEBUG
+ JSBool ok;
+#endif
+
+ if (js_CStringsAreUTF8) {
+ nbytes = js_GetDeflatedStringLength(cx, chars, nchars);
+ if (nbytes == (size_t) -1)
+ return NULL;
+ bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1));
+ if (!bytes)
+ return NULL;
+#ifdef DEBUG
+ ok =
+#endif
+ js_DeflateStringToBuffer(cx, chars, nchars, bytes, &nbytes);
+ JS_ASSERT(ok);
+ } else {
+ nbytes = nchars;
+ bytes = (char *) (cx ? JS_malloc(cx, nbytes + 1) : malloc(nbytes + 1));
+ if (!bytes)
+ return NULL;
+ for (i = 0; i < nbytes; i++)
+ bytes[i] = (char) chars[i];
+ }
+ bytes[nbytes] = 0;
+ return bytes;
+}
+
+/*
+ * May be called with null cx through js_GetStringBytes, see below.
+ */
+size_t
+js_GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
+{
+ size_t nbytes;
+ const jschar *end;
+ uintN c, c2;
+ char buffer[10];
+
+ if (!js_CStringsAreUTF8)
+ return nchars;
+
+ nbytes = nchars;
+ for (end = chars + nchars; chars != end; chars++) {
+ c = *chars;
+ if (c < 0x80)
+ continue;
+ if (0xD800 <= c && c <= 0xDFFF) {
+ /* Surrogate pair. */
+ chars++;
+ if (c >= 0xDC00 || chars == end)
+ goto bad_surrogate;
+ c2 = *chars;
+ if (c2 < 0xDC00 || c2 > 0xDFFF)
+ goto bad_surrogate;
+ c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+ }
+ c >>= 11;
+ nbytes++;
+ while (c) {
+ c >>= 5;
+ nbytes++;
+ }
+ }
+ return nbytes;
+
+ bad_surrogate:
+ if (cx) {
+ JS_snprintf(buffer, 10, "0x%x", c);
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
+ NULL, JSMSG_BAD_SURROGATE_CHAR, buffer);
+ }
+ return (size_t) -1;
+}
+
+JSBool
+js_DeflateStringToBuffer(JSContext *cx, const jschar *src, size_t srclen,
+ char *dst, size_t *dstlenp)
+{
+ size_t dstlen, i, origDstlen, utf8Len;
+ jschar c, c2;
+ uint32 v;
+ uint8 utf8buf[6];
+
+ dstlen = *dstlenp;
+ if (!js_CStringsAreUTF8) {
+ if (srclen > dstlen) {
+ for (i = 0; i < dstlen; i++)
+ dst[i] = (char) src[i];
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+ }
+ for (i = 0; i < srclen; i++)
+ dst[i] = (char) src[i];
+ *dstlenp = srclen;
+ return JS_TRUE;
+ }
+
+ origDstlen = dstlen;
+ while (srclen) {
+ c = *src++;
+ srclen--;
+ if ((c >= 0xDC00) && (c <= 0xDFFF))
+ goto badSurrogate;
+ if (c < 0xD800 || c > 0xDBFF) {
+ v = c;
+ } else {
+ if (srclen < 1)
+ goto badSurrogate;
+ c2 = *src;
+ if ((c2 < 0xDC00) || (c2 > 0xDFFF))
+ goto badSurrogate;
+ src++;
+ srclen--;
+ v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+ }
+ if (v < 0x0080) {
+ /* no encoding necessary - performance hack */
+ if (dstlen == 0)
+ goto bufferTooSmall;
+ *dst++ = (char) v;
+ utf8Len = 1;
+ } else {
+ utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
+ if (utf8Len > dstlen)
+ goto bufferTooSmall;
+ for (i = 0; i < utf8Len; i++)
+ *dst++ = (char) utf8buf[i];
+ }
+ dstlen -= utf8Len;
+ }
+ *dstlenp = (origDstlen - dstlen);
+ return JS_TRUE;
+
+badSurrogate:
+ *dstlenp = (origDstlen - dstlen);
+ /* Delegate error reporting to the measurement function. */
+ if (cx)
+ js_GetDeflatedStringLength(cx, src - 1, srclen + 1);
+ return JS_FALSE;
+
+bufferTooSmall:
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_InflateStringToBuffer(JSContext *cx, const char *src, size_t srclen,
+ jschar *dst, size_t *dstlenp)
+{
+ size_t dstlen, i, origDstlen, offset, j, n;
+ uint32 v;
+
+ if (!js_CStringsAreUTF8) {
+ if (dst) {
+ dstlen = *dstlenp;
+ if (srclen > dstlen) {
+ for (i = 0; i < dstlen; i++)
+ dst[i] = (unsigned char) src[i];
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+ }
+ for (i = 0; i < srclen; i++)
+ dst[i] = (unsigned char) src[i];
+ }
+ *dstlenp = srclen;
+ return JS_TRUE;
+ }
+
+ dstlen = dst ? *dstlenp : (size_t) -1;
+ origDstlen = dstlen;
+ offset = 0;
+
+ while (srclen) {
+ v = (uint8) *src;
+ n = 1;
+ if (v & 0x80) {
+ while (v & (0x80 >> n))
+ n++;
+ if (n > srclen)
+ goto bufferTooSmall;
+ if (n == 1 || n > 6)
+ goto badCharacter;
+ for (j = 1; j < n; j++) {
+ if ((src[j] & 0xC0) != 0x80)
+ goto badCharacter;
+ }
+ v = Utf8ToOneUcs4Char((uint8 *)src, n);
+ if (v >= 0x10000) {
+ v -= 0x10000;
+ if (v > 0xFFFFF || dstlen < 2) {
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ char buffer[10];
+ JS_snprintf(buffer, 10, "0x%x", v + 0x10000);
+ JS_ReportErrorFlagsAndNumber(cx,
+ JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_UTF8_CHAR_TOO_LARGE,
+ buffer);
+ }
+ return JS_FALSE;
+ }
+ if (dstlen < 2)
+ goto bufferTooSmall;
+ if (dst) {
+ *dst++ = (jschar)((v >> 10) + 0xD800);
+ v = (jschar)((v & 0x3FF) + 0xDC00);
+ }
+ dstlen--;
+ }
+ }
+ if (!dstlen)
+ goto bufferTooSmall;
+ if (dst)
+ *dst++ = (jschar) v;
+ dstlen--;
+ offset += n;
+ src += n;
+ srclen -= n;
+ }
+ *dstlenp = (origDstlen - dstlen);
+ return JS_TRUE;
+
+badCharacter:
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ char buffer[10];
+ JS_snprintf(buffer, 10, "%d", offset);
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_MALFORMED_UTF8_CHAR,
+ buffer);
+ }
+ return JS_FALSE;
+
+bufferTooSmall:
+ *dstlenp = (origDstlen - dstlen);
+ if (cx) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BUFFER_TOO_SMALL);
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_SetStringBytes(JSContext *cx, JSString *str, char *bytes, size_t length)
+{
+ JSRuntime *rt;
+ JSHashTable *cache;
+ JSBool ok;
+ JSHashNumber hash;
+ JSHashEntry **hep;
+
+ rt = cx->runtime;
+ JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
+
+ cache = rt->deflatedStringCache;
+ hash = js_hash_string_pointer(str);
+ hep = JS_HashTableRawLookup(cache, hash, str);
+ JS_ASSERT(*hep == NULL);
+ ok = JS_HashTableRawAdd(cache, hep, hash, str, bytes) != NULL;
+#ifdef DEBUG
+ if (ok)
+ rt->deflatedStringCacheBytes += length;
+#endif
+
+ JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
+ return ok;
+}
+
+const char *
+js_GetStringBytes(JSContext *cx, JSString *str)
+{
+ JSRuntime *rt;
+ JSHashTable *cache;
+ char *bytes;
+ JSHashNumber hash;
+ JSHashEntry *he, **hep;
+
+ if (cx) {
+ rt = cx->runtime;
+ } else {
+ /* JS_GetStringBytes calls us with null cx. */
+ rt = js_GetGCStringRuntime(str);
+ }
+
+#ifdef JS_THREADSAFE
+ if (!rt->deflatedStringCacheLock) {
+ /*
+ * Called from last GC (see js_DestroyContext), after runtime string
+ * state has been finalized. We have no choice but to leak here.
+ */
+ return js_DeflateString(NULL, JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ }
+#endif
+
+ JS_ACQUIRE_LOCK(rt->deflatedStringCacheLock);
+
+ cache = rt->deflatedStringCache;
+ hash = js_hash_string_pointer(str);
+ hep = JS_HashTableRawLookup(cache, hash, str);
+ he = *hep;
+ if (he) {
+ bytes = (char *) he->value;
+
+ /* Try to catch failure to JS_ShutDown between runtime epochs. */
+ if (!js_CStringsAreUTF8) {
+ JS_ASSERT_IF(*bytes != (char) JSSTRING_CHARS(str)[0],
+ *bytes == '\0' && JSSTRING_LENGTH(str) == 0);
+ }
+ } else {
+ bytes = js_DeflateString(cx, JSSTRING_CHARS(str),
+ JSSTRING_LENGTH(str));
+ if (bytes) {
+ if (JS_HashTableRawAdd(cache, hep, hash, str, bytes)) {
+#ifdef DEBUG
+ rt->deflatedStringCacheBytes += JSSTRING_LENGTH(str);
+#endif
+ } else {
+ if (cx)
+ JS_free(cx, bytes);
+ else
+ free(bytes);
+ bytes = NULL;
+ }
+ }
+ }
+
+ JS_RELEASE_LOCK(rt->deflatedStringCacheLock);
+ return bytes;
+}
+
+/*
+ * From java.lang.Character.java:
+ *
+ * The character properties are currently encoded into 32 bits in the
+ * following manner:
+ *
+ * 10 bits signed offset used for converting case
+ * 1 bit if 1, adding the signed offset converts the character to
+ * lowercase
+ * 1 bit if 1, subtracting the signed offset converts the character to
+ * uppercase
+ * 1 bit if 1, character has a titlecase equivalent (possibly itself)
+ * 3 bits 0 may not be part of an identifier
+ * 1 ignorable control; may continue a Unicode identifier or JS
+ * identifier
+ * 2 may continue a JS identifier but not a Unicode identifier
+ * (unused)
+ * 3 may continue a Unicode identifier or JS identifier
+ * 4 is a JS whitespace character
+ * 5 may start or continue a JS identifier;
+ * may continue but not start a Unicode identifier (_)
+ * 6 may start or continue a JS identifier but not a Unicode
+ * identifier ($)
+ * 7 may start or continue a Unicode identifier or JS identifier
+ * Thus:
+ * 5, 6, 7 may start a JS identifier
+ * 1, 2, 3, 5, 6, 7 may continue a JS identifier
+ * 7 may start a Unicode identifier
+ * 1, 3, 5, 7 may continue a Unicode identifier
+ * 1 is ignorable within an identifier
+ * 4 is JS whitespace
+ * 2 bits 0 this character has no numeric property
+ * 1 adding the digit offset to the character code and then
+ * masking with 0x1F will produce the desired numeric value
+ * 2 this character has a "strange" numeric value
+ * 3 a JS supradecimal digit: adding the digit offset to the
+ * character code, then masking with 0x1F, then adding 10
+ * will produce the desired numeric value
+ * 5 bits digit offset
+ * 1 bit XML 1.0 name start character
+ * 1 bit XML 1.0 name character
+ * 2 bits reserved for future use
+ * 5 bits character type
+ */
+
+/* The X table has 1024 entries for a total of 1024 bytes. */
+
+const uint8 js_X[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, /* 0x0000 */
+ 8, 9, 10, 11, 12, 13, 14, 15, /* 0x0200 */
+ 16, 17, 18, 19, 20, 21, 22, 23, /* 0x0400 */
+ 24, 25, 26, 27, 28, 28, 28, 28, /* 0x0600 */
+ 28, 28, 28, 28, 29, 30, 31, 32, /* 0x0800 */
+ 33, 34, 35, 36, 37, 38, 39, 40, /* 0x0A00 */
+ 41, 42, 43, 44, 45, 46, 28, 28, /* 0x0C00 */
+ 47, 48, 49, 50, 51, 52, 53, 28, /* 0x0E00 */
+ 28, 28, 54, 55, 56, 57, 58, 59, /* 0x1000 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x1C00 */
+ 60, 60, 61, 62, 63, 64, 65, 66, /* 0x1E00 */
+ 67, 68, 69, 70, 71, 72, 73, 74, /* 0x2000 */
+ 75, 75, 75, 76, 77, 78, 28, 28, /* 0x2200 */
+ 79, 80, 81, 82, 83, 83, 84, 85, /* 0x2400 */
+ 86, 85, 28, 28, 87, 88, 89, 28, /* 0x2600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2C00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x2E00 */
+ 90, 91, 92, 93, 94, 56, 95, 28, /* 0x3000 */
+ 96, 97, 98, 99, 83, 100, 83, 101, /* 0x3200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3C00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x3E00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4000 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4A00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0x4C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x4E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x5E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x6E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x7E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8C00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x8E00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9A00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0x9C00 */
+ 56, 56, 56, 56, 56, 56, 102, 28, /* 0x9E00 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA000 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA200 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA400 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA600 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xA800 */
+ 28, 28, 28, 28, 28, 28, 28, 28, /* 0xAA00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAC00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xAE00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xB800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBA00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBC00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xBE00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC400 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC600 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xC800 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCA00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCC00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xCE00 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD000 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD200 */
+ 56, 56, 56, 56, 56, 56, 56, 56, /* 0xD400 */
+ 56, 56, 56, 56, 56, 56, 103, 28, /* 0xD600 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xD800 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xDA00 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xDC00 */
+104, 104, 104, 104, 104, 104, 104, 104, /* 0xDE00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE000 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE200 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE400 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE600 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xE800 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xEA00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xEC00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xEE00 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF000 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF200 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF400 */
+105, 105, 105, 105, 105, 105, 105, 105, /* 0xF600 */
+105, 105, 105, 105, 56, 56, 56, 56, /* 0xF800 */
+106, 28, 28, 28, 107, 108, 109, 110, /* 0xFA00 */
+ 56, 56, 56, 56, 111, 112, 113, 114, /* 0xFC00 */
+115, 116, 56, 117, 118, 119, 120, 121 /* 0xFE00 */
+};
+
+/* The Y table has 7808 entries for a total of 7808 bytes. */
+
+const uint8 js_Y[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 0, 1, 1, 1, 1, 1, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 */
+ 2, 3, 3, 3, 4, 3, 3, 3, /* 0 */
+ 5, 6, 3, 7, 3, 8, 3, 3, /* 0 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 0 */
+ 9, 9, 3, 3, 7, 7, 7, 3, /* 0 */
+ 3, 10, 10, 10, 10, 10, 10, 10, /* 1 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 1 */
+ 10, 10, 10, 5, 3, 6, 11, 12, /* 1 */
+ 11, 13, 13, 13, 13, 13, 13, 13, /* 1 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 1 */
+ 13, 13, 13, 5, 7, 6, 7, 0, /* 1 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 2 */
+ 2, 3, 4, 4, 4, 4, 15, 15, /* 2 */
+ 11, 15, 16, 5, 7, 8, 15, 11, /* 2 */
+ 15, 7, 17, 17, 11, 16, 15, 3, /* 2 */
+ 11, 18, 16, 6, 19, 19, 19, 3, /* 2 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 3 */
+ 20, 20, 20, 20, 20, 20, 20, 7, /* 3 */
+ 20, 20, 20, 20, 20, 20, 20, 16, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 7, /* 3 */
+ 21, 21, 21, 21, 21, 21, 21, 22, /* 3 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 4 */
+ 25, 26, 23, 24, 23, 24, 23, 24, /* 4 */
+ 16, 23, 24, 23, 24, 23, 24, 23, /* 4 */
+ 24, 23, 24, 23, 24, 23, 24, 23, /* 5 */
+ 24, 16, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 5 */
+ 27, 23, 24, 23, 24, 23, 24, 28, /* 5 */
+ 16, 29, 23, 24, 23, 24, 30, 23, /* 6 */
+ 24, 31, 31, 23, 24, 16, 32, 32, /* 6 */
+ 33, 23, 24, 31, 34, 16, 35, 36, /* 6 */
+ 23, 24, 16, 16, 35, 37, 16, 38, /* 6 */
+ 23, 24, 23, 24, 23, 24, 38, 23, /* 6 */
+ 24, 39, 40, 16, 23, 24, 39, 23, /* 6 */
+ 24, 41, 41, 23, 24, 23, 24, 42, /* 6 */
+ 23, 24, 16, 40, 23, 24, 40, 40, /* 6 */
+ 40, 40, 40, 40, 43, 44, 45, 43, /* 7 */
+ 44, 45, 43, 44, 45, 23, 24, 23, /* 7 */
+ 24, 23, 24, 23, 24, 23, 24, 23, /* 7 */
+ 24, 23, 24, 23, 24, 16, 23, 24, /* 7 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 7 */
+ 16, 43, 44, 45, 23, 24, 46, 46, /* 7 */
+ 46, 46, 23, 24, 23, 24, 23, 24, /* 7 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 8 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 9 */
+ 16, 16, 16, 47, 48, 16, 49, 49, /* 9 */
+ 50, 50, 16, 51, 16, 16, 16, 16, /* 9 */
+ 49, 16, 16, 52, 16, 16, 16, 16, /* 9 */
+ 53, 54, 16, 16, 16, 16, 16, 54, /* 9 */
+ 16, 16, 55, 16, 16, 16, 16, 16, /* 9 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 9 */
+ 16, 16, 16, 56, 16, 16, 16, 16, /* 10 */
+ 56, 16, 57, 57, 16, 16, 16, 16, /* 10 */
+ 16, 16, 58, 16, 16, 16, 16, 16, /* 10 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 10 */
+ 16, 46, 46, 46, 46, 46, 46, 46, /* 10 */
+ 59, 59, 59, 59, 59, 59, 59, 59, /* 10 */
+ 59, 11, 11, 59, 59, 59, 59, 59, /* 10 */
+ 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */
+ 11, 11, 11, 11, 11, 11, 11, 11, /* 11 */
+ 59, 59, 11, 11, 11, 11, 11, 11, /* 11 */
+ 11, 11, 11, 11, 11, 11, 11, 46, /* 11 */
+ 59, 59, 59, 59, 59, 11, 11, 11, /* 11 */
+ 11, 11, 46, 46, 46, 46, 46, 46, /* 11 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 11 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 12 */
+ 60, 60, 60, 60, 60, 60, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 60, 60, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 13 */
+ 46, 46, 46, 46, 3, 3, 46, 46, /* 13 */
+ 46, 46, 59, 46, 46, 46, 3, 46, /* 13 */
+ 46, 46, 46, 46, 11, 11, 61, 3, /* 14 */
+ 62, 62, 62, 46, 63, 46, 64, 64, /* 14 */
+ 16, 20, 20, 20, 20, 20, 20, 20, /* 14 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 14 */
+ 20, 20, 46, 20, 20, 20, 20, 20, /* 14 */
+ 20, 20, 20, 20, 65, 66, 66, 66, /* 14 */
+ 16, 21, 21, 21, 21, 21, 21, 21, /* 14 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 14 */
+ 21, 21, 16, 21, 21, 21, 21, 21, /* 15 */
+ 21, 21, 21, 21, 67, 68, 68, 46, /* 15 */
+ 69, 70, 38, 38, 38, 71, 72, 46, /* 15 */
+ 46, 46, 38, 46, 38, 46, 38, 46, /* 15 */
+ 38, 46, 23, 24, 23, 24, 23, 24, /* 15 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 15 */
+ 73, 74, 16, 40, 46, 46, 46, 46, /* 15 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 15 */
+ 46, 75, 75, 75, 75, 75, 75, 75, /* 16 */
+ 75, 75, 75, 75, 75, 46, 75, 75, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 20, 20, 20, 20, 20, 20, 20, 20, /* 16 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 16 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */
+ 21, 21, 21, 21, 21, 21, 21, 21, /* 17 */
+ 46, 74, 74, 74, 74, 74, 74, 74, /* 17 */
+ 74, 74, 74, 74, 74, 46, 74, 74, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 17 */
+ 23, 24, 15, 60, 60, 60, 60, 46, /* 18 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 18 */
+ 40, 23, 24, 23, 24, 46, 46, 23, /* 19 */
+ 24, 46, 46, 23, 24, 46, 46, 46, /* 19 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 19 */
+ 23, 24, 23, 24, 46, 46, 23, 24, /* 19 */
+ 23, 24, 23, 24, 23, 24, 46, 46, /* 19 */
+ 23, 24, 46, 46, 46, 46, 46, 46, /* 19 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 20 */
+ 46, 76, 76, 76, 76, 76, 76, 76, /* 20 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 20 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 21 */
+ 76, 76, 76, 76, 76, 76, 76, 46, /* 21 */
+ 46, 59, 3, 3, 3, 3, 3, 3, /* 21 */
+ 46, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 77, /* 21 */
+ 77, 77, 77, 77, 77, 77, 77, 16, /* 22 */
+ 46, 3, 46, 46, 46, 46, 46, 46, /* 22 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 46, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 22 */
+ 60, 60, 46, 60, 60, 60, 3, 60, /* 22 */
+ 3, 60, 60, 3, 60, 46, 46, 46, /* 23 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 23 */
+ 40, 40, 40, 46, 46, 46, 46, 46, /* 23 */
+ 40, 40, 40, 3, 3, 46, 46, 46, /* 23 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 23 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */
+ 46, 46, 46, 46, 3, 46, 46, 46, /* 24 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 24 */
+ 46, 46, 46, 3, 46, 46, 46, 3, /* 24 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 24 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 24 */
+ 40, 40, 40, 46, 46, 46, 46, 46, /* 24 */
+ 59, 40, 40, 40, 40, 40, 40, 40, /* 25 */
+ 40, 40, 40, 60, 60, 60, 60, 60, /* 25 */
+ 60, 60, 60, 46, 46, 46, 46, 46, /* 25 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 25 */
+ 78, 78, 78, 78, 78, 78, 78, 78, /* 25 */
+ 78, 78, 3, 3, 3, 3, 46, 46, /* 25 */
+ 60, 40, 40, 40, 40, 40, 40, 40, /* 25 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 25 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 26 */
+ 46, 46, 40, 40, 40, 40, 40, 46, /* 26 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 27 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 27 */
+ 40, 40, 40, 40, 3, 40, 60, 60, /* 27 */
+ 60, 60, 60, 60, 60, 79, 79, 60, /* 27 */
+ 60, 60, 60, 60, 60, 59, 59, 60, /* 27 */
+ 60, 15, 60, 60, 60, 60, 46, 46, /* 27 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 27 */
+ 9, 9, 46, 46, 46, 46, 46, 46, /* 27 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 28 */
+ 46, 60, 60, 80, 46, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 29 */
+ 40, 40, 46, 46, 60, 40, 80, 80, /* 29 */
+ 80, 60, 60, 60, 60, 60, 60, 60, /* 30 */
+ 60, 80, 80, 80, 80, 60, 46, 46, /* 30 */
+ 15, 60, 60, 60, 60, 46, 46, 46, /* 30 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 30 */
+ 40, 40, 60, 60, 3, 3, 81, 81, /* 30 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 30 */
+ 3, 46, 46, 46, 46, 46, 46, 46, /* 30 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 30 */
+ 46, 60, 80, 80, 46, 40, 40, 40, /* 31 */
+ 40, 40, 40, 40, 40, 46, 46, 40, /* 31 */
+ 40, 46, 46, 40, 40, 40, 40, 40, /* 31 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 31 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 31 */
+ 40, 46, 40, 46, 46, 46, 40, 40, /* 31 */
+ 40, 40, 46, 46, 60, 46, 80, 80, /* 31 */
+ 80, 60, 60, 60, 60, 46, 46, 80, /* 32 */
+ 80, 46, 46, 80, 80, 60, 46, 46, /* 32 */
+ 46, 46, 46, 46, 46, 46, 46, 80, /* 32 */
+ 46, 46, 46, 46, 40, 40, 46, 40, /* 32 */
+ 40, 40, 60, 60, 46, 46, 81, 81, /* 32 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 32 */
+ 40, 40, 4, 4, 82, 82, 82, 82, /* 32 */
+ 19, 83, 15, 46, 46, 46, 46, 46, /* 32 */
+ 46, 46, 60, 46, 46, 40, 40, 40, /* 33 */
+ 40, 40, 40, 46, 46, 46, 46, 40, /* 33 */
+ 40, 46, 46, 40, 40, 40, 40, 40, /* 33 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 33 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 33 */
+ 40, 46, 40, 40, 46, 40, 40, 46, /* 33 */
+ 40, 40, 46, 46, 60, 46, 80, 80, /* 33 */
+ 80, 60, 60, 46, 46, 46, 46, 60, /* 34 */
+ 60, 46, 46, 60, 60, 60, 46, 46, /* 34 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */
+ 46, 40, 40, 40, 40, 46, 40, 46, /* 34 */
+ 46, 46, 46, 46, 46, 46, 81, 81, /* 34 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 34 */
+ 60, 60, 40, 40, 40, 46, 46, 46, /* 34 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 34 */
+ 46, 60, 60, 80, 46, 40, 40, 40, /* 35 */
+ 40, 40, 40, 40, 46, 40, 46, 40, /* 35 */
+ 40, 40, 46, 40, 40, 40, 40, 40, /* 35 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 35 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 35 */
+ 40, 46, 40, 40, 46, 40, 40, 40, /* 35 */
+ 40, 40, 46, 46, 60, 40, 80, 80, /* 35 */
+ 80, 60, 60, 60, 60, 60, 46, 60, /* 36 */
+ 60, 80, 46, 80, 80, 60, 46, 46, /* 36 */
+ 15, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 40, 46, 46, 46, 46, 46, 81, 81, /* 36 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 36 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 36 */
+ 46, 60, 80, 80, 46, 40, 40, 40, /* 37 */
+ 40, 40, 40, 40, 40, 46, 46, 40, /* 37 */
+ 40, 46, 46, 40, 40, 40, 40, 40, /* 37 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 37 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 37 */
+ 40, 46, 40, 40, 46, 46, 40, 40, /* 37 */
+ 40, 40, 46, 46, 60, 40, 80, 60, /* 37 */
+ 80, 60, 60, 60, 46, 46, 46, 80, /* 38 */
+ 80, 46, 46, 80, 80, 60, 46, 46, /* 38 */
+ 46, 46, 46, 46, 46, 46, 60, 80, /* 38 */
+ 46, 46, 46, 46, 40, 40, 46, 40, /* 38 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 38 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 38 */
+ 15, 46, 46, 46, 46, 46, 46, 46, /* 38 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 38 */
+ 46, 46, 60, 80, 46, 40, 40, 40, /* 39 */
+ 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */
+ 40, 46, 40, 40, 40, 40, 46, 46, /* 39 */
+ 46, 40, 40, 46, 40, 46, 40, 40, /* 39 */
+ 46, 46, 46, 40, 40, 46, 46, 46, /* 39 */
+ 40, 40, 40, 46, 46, 46, 40, 40, /* 39 */
+ 40, 40, 40, 40, 40, 40, 46, 40, /* 39 */
+ 40, 40, 46, 46, 46, 46, 80, 80, /* 39 */
+ 60, 80, 80, 46, 46, 46, 80, 80, /* 40 */
+ 80, 46, 80, 80, 80, 60, 46, 46, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 80, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 81, /* 40 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 40 */
+ 84, 19, 19, 46, 46, 46, 46, 46, /* 40 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 40 */
+ 46, 80, 80, 80, 46, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 40, 46, 40, 40, /* 41 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 41 */
+ 40, 40, 40, 40, 46, 40, 40, 40, /* 41 */
+ 40, 40, 46, 46, 46, 46, 60, 60, /* 41 */
+ 60, 80, 80, 80, 80, 46, 60, 60, /* 42 */
+ 60, 46, 60, 60, 60, 60, 46, 46, /* 42 */
+ 46, 46, 46, 46, 46, 60, 60, 46, /* 42 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 42 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 42 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 42 */
+ 46, 46, 80, 80, 46, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 40, 46, 40, 40, /* 43 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 43 */
+ 40, 40, 40, 40, 46, 40, 40, 40, /* 43 */
+ 40, 40, 46, 46, 46, 46, 80, 60, /* 43 */
+ 80, 80, 80, 80, 80, 46, 60, 80, /* 44 */
+ 80, 46, 80, 80, 60, 60, 46, 46, /* 44 */
+ 46, 46, 46, 46, 46, 80, 80, 46, /* 44 */
+ 46, 46, 46, 46, 46, 46, 40, 46, /* 44 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 44 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 44 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 44 */
+ 46, 46, 80, 80, 46, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 46, 40, 40, /* 45 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 46, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 45 */
+ 40, 40, 46, 46, 46, 46, 80, 80, /* 45 */
+ 80, 60, 60, 60, 46, 46, 80, 80, /* 46 */
+ 80, 46, 80, 80, 80, 60, 46, 46, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 80, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
+ 40, 40, 46, 46, 46, 46, 81, 81, /* 46 */
+ 81, 81, 81, 81, 81, 81, 81, 81, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 46 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 47 */
+ 40, 40, 40, 40, 40, 40, 40, 3, /* 47 */
+ 40, 60, 40, 40, 60, 60, 60, 60, /* 47 */
+ 60, 60, 60, 46, 46, 46, 46, 4, /* 47 */
+ 40, 40, 40, 40, 40, 40, 59, 60, /* 48 */
+ 60, 60, 60, 60, 60, 60, 60, 15, /* 48 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 48 */
+ 9, 9, 3, 3, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 48 */
+ 46, 40, 40, 46, 40, 46, 46, 40, /* 49 */
+ 40, 46, 40, 46, 46, 40, 46, 46, /* 49 */
+ 46, 46, 46, 46, 40, 40, 40, 40, /* 49 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 49 */
+ 46, 40, 40, 40, 46, 40, 46, 40, /* 49 */
+ 46, 46, 40, 40, 46, 40, 40, 3, /* 49 */
+ 40, 60, 40, 40, 60, 60, 60, 60, /* 49 */
+ 60, 60, 46, 60, 60, 40, 46, 46, /* 49 */
+ 40, 40, 40, 40, 40, 46, 59, 46, /* 50 */
+ 60, 60, 60, 60, 60, 60, 46, 46, /* 50 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 50 */
+ 9, 9, 46, 46, 40, 40, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 50 */
+ 15, 15, 15, 15, 3, 3, 3, 3, /* 51 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 51 */
+ 3, 3, 3, 15, 15, 15, 15, 15, /* 51 */
+ 60, 60, 15, 15, 15, 15, 15, 15, /* 51 */
+ 78, 78, 78, 78, 78, 78, 78, 78, /* 51 */
+ 78, 78, 85, 85, 85, 85, 85, 85, /* 51 */
+ 85, 85, 85, 85, 15, 60, 15, 60, /* 51 */
+ 15, 60, 5, 6, 5, 6, 80, 80, /* 51 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 52 */
+ 40, 40, 46, 46, 46, 46, 46, 46, /* 52 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 52 */
+ 60, 60, 60, 60, 60, 60, 60, 80, /* 52 */
+ 60, 60, 60, 60, 60, 3, 60, 60, /* 53 */
+ 60, 60, 60, 60, 46, 46, 46, 46, /* 53 */
+ 60, 60, 60, 60, 60, 60, 46, 60, /* 53 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 53 */
+ 60, 60, 60, 60, 60, 60, 46, 46, /* 53 */
+ 46, 60, 60, 60, 60, 60, 60, 60, /* 53 */
+ 46, 60, 46, 46, 46, 46, 46, 46, /* 53 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 76, 76, /* 54 */
+ 76, 76, 76, 76, 76, 76, 46, 46, /* 55 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 16, /* 55 */
+ 16, 16, 16, 16, 16, 16, 16, 46, /* 55 */
+ 46, 46, 46, 3, 46, 46, 46, 46, /* 55 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 56 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 46, 46, 46, 46, 46, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 57 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 46, 46, 46, 46, 46, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 58 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 59 */
+ 40, 40, 46, 46, 46, 46, 46, 46, /* 59 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 60 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 16, 16, /* 61 */
+ 16, 16, 16, 16, 46, 46, 46, 46, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 61 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 23, 24, 23, 24, 23, 24, /* 62 */
+ 23, 24, 46, 46, 46, 46, 46, 46, /* 62 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
+ 86, 86, 86, 86, 86, 86, 46, 46, /* 63 */
+ 87, 87, 87, 87, 87, 87, 46, 46, /* 63 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 63 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 63 */
+ 86, 86, 86, 86, 86, 86, 46, 46, /* 64 */
+ 87, 87, 87, 87, 87, 87, 46, 46, /* 64 */
+ 16, 86, 16, 86, 16, 86, 16, 86, /* 64 */
+ 46, 87, 46, 87, 46, 87, 46, 87, /* 64 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 64 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 64 */
+ 88, 88, 89, 89, 89, 89, 90, 90, /* 64 */
+ 91, 91, 92, 92, 93, 93, 46, 46, /* 64 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
+ 86, 86, 86, 86, 86, 86, 86, 86, /* 65 */
+ 87, 87, 87, 87, 87, 87, 87, 87, /* 65 */
+ 86, 86, 16, 94, 16, 46, 16, 16, /* 65 */
+ 87, 87, 95, 95, 96, 11, 38, 11, /* 65 */
+ 11, 11, 16, 94, 16, 46, 16, 16, /* 66 */
+ 97, 97, 97, 97, 96, 11, 11, 11, /* 66 */
+ 86, 86, 16, 16, 46, 46, 16, 16, /* 66 */
+ 87, 87, 98, 98, 46, 11, 11, 11, /* 66 */
+ 86, 86, 16, 16, 16, 99, 16, 16, /* 66 */
+ 87, 87, 100, 100, 101, 11, 11, 11, /* 66 */
+ 46, 46, 16, 94, 16, 46, 16, 16, /* 66 */
+102, 102, 103, 103, 96, 11, 11, 46, /* 66 */
+ 2, 2, 2, 2, 2, 2, 2, 2, /* 67 */
+ 2, 2, 2, 2, 104, 104, 104, 104, /* 67 */
+ 8, 8, 8, 8, 8, 8, 3, 3, /* 67 */
+ 5, 6, 5, 5, 5, 6, 5, 5, /* 67 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */
+105, 106, 104, 104, 104, 104, 104, 46, /* 67 */
+ 3, 3, 3, 3, 3, 3, 3, 3, /* 67 */
+ 3, 5, 6, 3, 3, 3, 3, 12, /* 67 */
+ 12, 3, 3, 3, 7, 5, 6, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 68 */
+ 46, 46, 104, 104, 104, 104, 104, 104, /* 68 */
+ 17, 46, 46, 46, 17, 17, 17, 17, /* 68 */
+ 17, 17, 7, 7, 7, 5, 6, 16, /* 68 */
+107, 107, 107, 107, 107, 107, 107, 107, /* 69 */
+107, 107, 7, 7, 7, 5, 6, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 4, 4, 4, 4, 4, 4, 4, 4, /* 69 */
+ 4, 4, 4, 4, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 69 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 60, 60, 60, 60, 60, 60, 60, 60, /* 70 */
+ 60, 60, 60, 60, 60, 79, 79, 79, /* 70 */
+ 79, 60, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 70 */
+ 15, 15, 38, 15, 15, 15, 15, 38, /* 71 */
+ 15, 15, 16, 38, 38, 38, 16, 16, /* 71 */
+ 38, 38, 38, 16, 15, 38, 15, 15, /* 71 */
+ 38, 38, 38, 38, 38, 38, 15, 15, /* 71 */
+ 15, 15, 15, 15, 38, 15, 38, 15, /* 71 */
+ 38, 15, 38, 38, 38, 38, 16, 16, /* 71 */
+ 38, 38, 15, 38, 16, 40, 40, 40, /* 71 */
+ 40, 46, 46, 46, 46, 46, 46, 46, /* 71 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 72 */
+ 46, 46, 46, 19, 19, 19, 19, 19, /* 72 */
+ 19, 19, 19, 19, 19, 19, 19, 108, /* 72 */
+109, 109, 109, 109, 109, 109, 109, 109, /* 72 */
+109, 109, 109, 109, 110, 110, 110, 110, /* 72 */
+111, 111, 111, 111, 111, 111, 111, 111, /* 72 */
+111, 111, 111, 111, 112, 112, 112, 112, /* 72 */
+113, 113, 113, 46, 46, 46, 46, 46, /* 73 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 73 */
+ 7, 7, 7, 7, 7, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 73 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 7, 15, 7, 15, 15, 15, /* 74 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 74 */
+ 15, 15, 15, 46, 46, 46, 46, 46, /* 74 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 74 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 75 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 7, 7, 7, 7, 7, 7, /* 76 */
+ 7, 7, 46, 46, 46, 46, 46, 46, /* 76 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 76 */
+ 15, 46, 15, 15, 15, 15, 15, 15, /* 77 */
+ 7, 7, 7, 7, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 7, 7, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 5, 6, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 77 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 78 */
+ 15, 15, 15, 46, 46, 46, 46, 46, /* 78 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 79 */
+ 15, 15, 15, 15, 15, 46, 46, 46, /* 79 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 79 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 80 */
+ 15, 15, 15, 46, 46, 46, 46, 46, /* 80 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 80 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 80 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 80 */
+114, 114, 114, 114, 82, 82, 82, 82, /* 80 */
+ 82, 82, 82, 82, 82, 82, 82, 82, /* 80 */
+ 82, 82, 82, 82, 82, 82, 82, 82, /* 81 */
+115, 115, 115, 115, 115, 115, 115, 115, /* 81 */
+115, 115, 115, 115, 115, 115, 115, 115, /* 81 */
+115, 115, 115, 115, 15, 15, 15, 15, /* 81 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 81 */
+ 15, 15, 15, 15, 15, 15, 116, 116, /* 81 */
+116, 116, 116, 116, 116, 116, 116, 116, /* 81 */
+116, 116, 116, 116, 116, 116, 116, 116, /* 82 */
+116, 116, 116, 116, 116, 116, 116, 116, /* 82 */
+117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
+117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
+117, 117, 117, 117, 117, 117, 117, 117, /* 82 */
+117, 117, 118, 46, 46, 46, 46, 46, /* 82 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 82 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 83 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 46, 46, /* 84 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 84 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 85 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 85 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 46, 46, 46, 46, /* 86 */
+ 46, 46, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 86 */
+ 46, 15, 15, 15, 15, 46, 15, 15, /* 87 */
+ 15, 15, 46, 46, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 46, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 87 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 88 */
+ 15, 15, 15, 15, 46, 15, 46, 15, /* 88 */
+ 15, 15, 15, 46, 46, 46, 15, 46, /* 88 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 88 */
+ 46, 15, 15, 15, 15, 15, 15, 15, /* 88 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 88 */
+ 46, 46, 46, 46, 46, 46, 119, 119, /* 88 */
+119, 119, 119, 119, 119, 119, 119, 119, /* 88 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 89 */
+114, 114, 83, 83, 83, 83, 83, 83, /* 89 */
+ 83, 83, 83, 83, 15, 46, 46, 46, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 46, 15, 15, 15, 15, 15, 15, 15, /* 89 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 89 */
+ 2, 3, 3, 3, 15, 59, 3, 120, /* 90 */
+ 5, 6, 5, 6, 5, 6, 5, 6, /* 90 */
+ 5, 6, 15, 15, 5, 6, 5, 6, /* 90 */
+ 5, 6, 5, 6, 8, 5, 6, 5, /* 90 */
+ 15, 121, 121, 121, 121, 121, 121, 121, /* 90 */
+121, 121, 60, 60, 60, 60, 60, 60, /* 90 */
+ 8, 59, 59, 59, 59, 59, 15, 15, /* 90 */
+ 46, 46, 46, 46, 46, 46, 46, 15, /* 90 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 91 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 46, 46, 46, /* 92 */
+ 46, 60, 60, 59, 59, 59, 59, 46, /* 92 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 92 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 93 */
+ 40, 40, 40, 3, 59, 59, 59, 46, /* 93 */
+ 46, 46, 46, 46, 46, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 46, 46, 46, /* 94 */
+ 46, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 94 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 95 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 95 */
+ 15, 15, 85, 85, 85, 85, 15, 15, /* 95 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 95 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 46, 46, 46, /* 96 */
+ 85, 85, 85, 85, 85, 85, 85, 85, /* 96 */
+ 85, 85, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 96 */
+ 15, 15, 15, 15, 46, 46, 46, 46, /* 97 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 97 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 97 */
+ 15, 15, 15, 15, 46, 46, 46, 15, /* 97 */
+114, 114, 114, 114, 114, 114, 114, 114, /* 98 */
+114, 114, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 98 */
+ 15, 46, 46, 46, 46, 46, 46, 46, /* 98 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 98 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 46, 46, 46, 46, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 99 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 100 */
+ 46, 46, 46, 15, 15, 15, 15, 15, /* 100 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 46, 46, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 15, /* 101 */
+ 15, 15, 15, 15, 15, 15, 15, 46, /* 101 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 102 */
+ 40, 40, 40, 40, 40, 40, 46, 46, /* 102 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 102 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 103 */
+ 40, 40, 40, 40, 46, 46, 46, 46, /* 103 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 103 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+122, 122, 122, 122, 122, 122, 122, 122, /* 104 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+123, 123, 123, 123, 123, 123, 123, 123, /* 105 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 106 */
+ 40, 40, 40, 40, 40, 40, 46, 46, /* 106 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 106 */
+ 16, 16, 16, 16, 16, 16, 16, 46, /* 107 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 107 */
+ 46, 46, 46, 16, 16, 16, 16, 16, /* 107 */
+ 46, 46, 46, 46, 46, 46, 60, 40, /* 107 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 107 */
+ 40, 7, 40, 40, 40, 40, 40, 40, /* 107 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 107 */
+ 40, 40, 40, 40, 40, 46, 40, 46, /* 107 */
+ 40, 40, 46, 40, 40, 46, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 108 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 109 */
+ 40, 40, 46, 46, 46, 46, 46, 46, /* 109 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 109 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 110 */
+ 46, 46, 46, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 110 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 111 */
+ 40, 40, 40, 40, 40, 40, 5, 6, /* 111 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 112 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 113 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 114 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 114 */
+ 40, 40, 40, 40, 46, 46, 46, 46, /* 114 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 60, 60, 60, 60, 46, 46, 46, 46, /* 115 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 115 */
+ 3, 8, 8, 12, 12, 5, 6, 5, /* 115 */
+ 6, 5, 6, 5, 6, 5, 6, 5, /* 115 */
+ 6, 5, 6, 5, 6, 46, 46, 46, /* 116 */
+ 46, 3, 3, 3, 3, 12, 12, 12, /* 116 */
+ 3, 3, 3, 46, 3, 3, 3, 3, /* 116 */
+ 8, 5, 6, 5, 6, 5, 6, 3, /* 116 */
+ 3, 3, 7, 8, 7, 7, 7, 46, /* 116 */
+ 3, 4, 3, 3, 46, 46, 46, 46, /* 116 */
+ 40, 40, 40, 46, 40, 46, 40, 40, /* 116 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 116 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 117 */
+ 40, 40, 40, 40, 40, 46, 46, 104, /* 117 */
+ 46, 3, 3, 3, 4, 3, 3, 3, /* 118 */
+ 5, 6, 3, 7, 3, 8, 3, 3, /* 118 */
+ 9, 9, 9, 9, 9, 9, 9, 9, /* 118 */
+ 9, 9, 3, 3, 7, 7, 7, 3, /* 118 */
+ 3, 10, 10, 10, 10, 10, 10, 10, /* 118 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */
+ 10, 10, 10, 10, 10, 10, 10, 10, /* 118 */
+ 10, 10, 10, 5, 3, 6, 11, 12, /* 118 */
+ 11, 13, 13, 13, 13, 13, 13, 13, /* 119 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */
+ 13, 13, 13, 13, 13, 13, 13, 13, /* 119 */
+ 13, 13, 13, 5, 7, 6, 7, 46, /* 119 */
+ 46, 3, 5, 6, 3, 3, 40, 40, /* 119 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */
+ 59, 40, 40, 40, 40, 40, 40, 40, /* 119 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 119 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 59, 59, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 40, /* 120 */
+ 40, 40, 40, 40, 40, 40, 40, 46, /* 120 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
+ 46, 46, 40, 40, 40, 40, 40, 40, /* 121 */
+ 46, 46, 40, 40, 40, 46, 46, 46, /* 121 */
+ 4, 4, 7, 11, 15, 4, 4, 46, /* 121 */
+ 7, 7, 7, 7, 7, 15, 15, 46, /* 121 */
+ 46, 46, 46, 46, 46, 46, 46, 46, /* 121 */
+ 46, 46, 46, 46, 46, 15, 46, 46 /* 121 */
+};
+
+/* The A table has 124 entries for a total of 496 bytes. */
+
+const uint32 js_A[] = {
+0x0001000F, /* 0 Cc, ignorable */
+0x0004000F, /* 1 Cc, whitespace */
+0x0004000C, /* 2 Zs, whitespace */
+0x00000018, /* 3 Po */
+0x0006001A, /* 4 Sc, currency */
+0x00000015, /* 5 Ps */
+0x00000016, /* 6 Pe */
+0x00000019, /* 7 Sm */
+0x00000014, /* 8 Pd */
+0x00036089, /* 9 Nd, identifier part, decimal 16 */
+0x0827FF81, /* 10 Lu, hasLower (add 32), identifier start, supradecimal 31 */
+0x0000001B, /* 11 Sk */
+0x00050017, /* 12 Pc, underscore */
+0x0817FF82, /* 13 Ll, hasUpper (subtract 32), identifier start, supradecimal 31 */
+0x0000000C, /* 14 Zs */
+0x0000001C, /* 15 So */
+0x00070182, /* 16 Ll, identifier start */
+0x0000600B, /* 17 No, decimal 16 */
+0x0000500B, /* 18 No, decimal 8 */
+0x0000800B, /* 19 No, strange */
+0x08270181, /* 20 Lu, hasLower (add 32), identifier start */
+0x08170182, /* 21 Ll, hasUpper (subtract 32), identifier start */
+0xE1D70182, /* 22 Ll, hasUpper (subtract -121), identifier start */
+0x00670181, /* 23 Lu, hasLower (add 1), identifier start */
+0x00570182, /* 24 Ll, hasUpper (subtract 1), identifier start */
+0xCE670181, /* 25 Lu, hasLower (add -199), identifier start */
+0x3A170182, /* 26 Ll, hasUpper (subtract 232), identifier start */
+0xE1E70181, /* 27 Lu, hasLower (add -121), identifier start */
+0x4B170182, /* 28 Ll, hasUpper (subtract 300), identifier start */
+0x34A70181, /* 29 Lu, hasLower (add 210), identifier start */
+0x33A70181, /* 30 Lu, hasLower (add 206), identifier start */
+0x33670181, /* 31 Lu, hasLower (add 205), identifier start */
+0x32A70181, /* 32 Lu, hasLower (add 202), identifier start */
+0x32E70181, /* 33 Lu, hasLower (add 203), identifier start */
+0x33E70181, /* 34 Lu, hasLower (add 207), identifier start */
+0x34E70181, /* 35 Lu, hasLower (add 211), identifier start */
+0x34670181, /* 36 Lu, hasLower (add 209), identifier start */
+0x35670181, /* 37 Lu, hasLower (add 213), identifier start */
+0x00070181, /* 38 Lu, identifier start */
+0x36A70181, /* 39 Lu, hasLower (add 218), identifier start */
+0x00070185, /* 40 Lo, identifier start */
+0x36670181, /* 41 Lu, hasLower (add 217), identifier start */
+0x36E70181, /* 42 Lu, hasLower (add 219), identifier start */
+0x00AF0181, /* 43 Lu, hasLower (add 2), hasTitle, identifier start */
+0x007F0183, /* 44 Lt, hasUpper (subtract 1), hasLower (add 1), hasTitle, identifier start */
+0x009F0182, /* 45 Ll, hasUpper (subtract 2), hasTitle, identifier start */
+0x00000000, /* 46 unassigned */
+0x34970182, /* 47 Ll, hasUpper (subtract 210), identifier start */
+0x33970182, /* 48 Ll, hasUpper (subtract 206), identifier start */
+0x33570182, /* 49 Ll, hasUpper (subtract 205), identifier start */
+0x32970182, /* 50 Ll, hasUpper (subtract 202), identifier start */
+0x32D70182, /* 51 Ll, hasUpper (subtract 203), identifier start */
+0x33D70182, /* 52 Ll, hasUpper (subtract 207), identifier start */
+0x34570182, /* 53 Ll, hasUpper (subtract 209), identifier start */
+0x34D70182, /* 54 Ll, hasUpper (subtract 211), identifier start */
+0x35570182, /* 55 Ll, hasUpper (subtract 213), identifier start */
+0x36970182, /* 56 Ll, hasUpper (subtract 218), identifier start */
+0x36570182, /* 57 Ll, hasUpper (subtract 217), identifier start */
+0x36D70182, /* 58 Ll, hasUpper (subtract 219), identifier start */
+0x00070084, /* 59 Lm, identifier start */
+0x00030086, /* 60 Mn, identifier part */
+0x09A70181, /* 61 Lu, hasLower (add 38), identifier start */
+0x09670181, /* 62 Lu, hasLower (add 37), identifier start */
+0x10270181, /* 63 Lu, hasLower (add 64), identifier start */
+0x0FE70181, /* 64 Lu, hasLower (add 63), identifier start */
+0x09970182, /* 65 Ll, hasUpper (subtract 38), identifier start */
+0x09570182, /* 66 Ll, hasUpper (subtract 37), identifier start */
+0x10170182, /* 67 Ll, hasUpper (subtract 64), identifier start */
+0x0FD70182, /* 68 Ll, hasUpper (subtract 63), identifier start */
+0x0F970182, /* 69 Ll, hasUpper (subtract 62), identifier start */
+0x0E570182, /* 70 Ll, hasUpper (subtract 57), identifier start */
+0x0BD70182, /* 71 Ll, hasUpper (subtract 47), identifier start */
+0x0D970182, /* 72 Ll, hasUpper (subtract 54), identifier start */
+0x15970182, /* 73 Ll, hasUpper (subtract 86), identifier start */
+0x14170182, /* 74 Ll, hasUpper (subtract 80), identifier start */
+0x14270181, /* 75 Lu, hasLower (add 80), identifier start */
+0x0C270181, /* 76 Lu, hasLower (add 48), identifier start */
+0x0C170182, /* 77 Ll, hasUpper (subtract 48), identifier start */
+0x00034089, /* 78 Nd, identifier part, decimal 0 */
+0x00000087, /* 79 Me */
+0x00030088, /* 80 Mc, identifier part */
+0x00037489, /* 81 Nd, identifier part, decimal 26 */
+0x00005A0B, /* 82 No, decimal 13 */
+0x00006E0B, /* 83 No, decimal 23 */
+0x0000740B, /* 84 No, decimal 26 */
+0x0000000B, /* 85 No */
+0xFE170182, /* 86 Ll, hasUpper (subtract -8), identifier start */
+0xFE270181, /* 87 Lu, hasLower (add -8), identifier start */
+0xED970182, /* 88 Ll, hasUpper (subtract -74), identifier start */
+0xEA970182, /* 89 Ll, hasUpper (subtract -86), identifier start */
+0xE7170182, /* 90 Ll, hasUpper (subtract -100), identifier start */
+0xE0170182, /* 91 Ll, hasUpper (subtract -128), identifier start */
+0xE4170182, /* 92 Ll, hasUpper (subtract -112), identifier start */
+0xE0970182, /* 93 Ll, hasUpper (subtract -126), identifier start */
+0xFDD70182, /* 94 Ll, hasUpper (subtract -9), identifier start */
+0xEDA70181, /* 95 Lu, hasLower (add -74), identifier start */
+0xFDE70181, /* 96 Lu, hasLower (add -9), identifier start */
+0xEAA70181, /* 97 Lu, hasLower (add -86), identifier start */
+0xE7270181, /* 98 Lu, hasLower (add -100), identifier start */
+0xFE570182, /* 99 Ll, hasUpper (subtract -7), identifier start */
+0xE4270181, /* 100 Lu, hasLower (add -112), identifier start */
+0xFE670181, /* 101 Lu, hasLower (add -7), identifier start */
+0xE0270181, /* 102 Lu, hasLower (add -128), identifier start */
+0xE0A70181, /* 103 Lu, hasLower (add -126), identifier start */
+0x00010010, /* 104 Cf, ignorable */
+0x0004000D, /* 105 Zl, whitespace */
+0x0004000E, /* 106 Zp, whitespace */
+0x0000400B, /* 107 No, decimal 0 */
+0x0000440B, /* 108 No, decimal 2 */
+0x0427438A, /* 109 Nl, hasLower (add 16), identifier start, decimal 1 */
+0x0427818A, /* 110 Nl, hasLower (add 16), identifier start, strange */
+0x0417638A, /* 111 Nl, hasUpper (subtract 16), identifier start, decimal 17 */
+0x0417818A, /* 112 Nl, hasUpper (subtract 16), identifier start, strange */
+0x0007818A, /* 113 Nl, identifier start, strange */
+0x0000420B, /* 114 No, decimal 1 */
+0x0000720B, /* 115 No, decimal 25 */
+0x06A0001C, /* 116 So, hasLower (add 26) */
+0x0690001C, /* 117 So, hasUpper (subtract 26) */
+0x00006C0B, /* 118 No, decimal 22 */
+0x0000560B, /* 119 No, decimal 11 */
+0x0007738A, /* 120 Nl, identifier start, decimal 25 */
+0x0007418A, /* 121 Nl, identifier start, decimal 0 */
+0x00000013, /* 122 Cs */
+0x00000012 /* 123 Co */
+};
+
+const jschar js_uriReservedPlusPound_ucstr[] =
+ {';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#', 0};
+const jschar js_uriUnescaped_ucstr[] =
+ {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '-', '_', '.', '!', '~', '*', '\'', '(', ')', 0};
+
+#define URI_CHUNK 64U
+
+/* Concatenate jschars onto the buffer */
+static JSBool
+AddCharsToURI(JSContext *cx, JSCharBuffer *buf,
+ const jschar *chars, size_t length)
+{
+ size_t total;
+ jschar *newchars;
+
+ total = buf->length + length + 1;
+ if (!buf->chars ||
+ JS_HOWMANY(total, URI_CHUNK) > JS_HOWMANY(buf->length + 1, URI_CHUNK)) {
+ total = JS_ROUNDUP(total, URI_CHUNK);
+ newchars = (jschar *) JS_realloc(cx, buf->chars,
+ total * sizeof(jschar));
+ if (!newchars)
+ return JS_FALSE;
+ buf->chars = newchars;
+ }
+ js_strncpy(buf->chars + buf->length, chars, length);
+ buf->length += length;
+ buf->chars[buf->length] = 0;
+ return JS_TRUE;
+}
+
+static JSBool
+TransferBufferToString(JSContext *cx, JSCharBuffer *cb, jsval *rval)
+{
+ jschar *chars;
+ size_t n;
+ JSString *str;
+
+ /*
+ * Shrinking realloc can fail (e.g., with a BSD-style allocator), but we
+ * don't worry about that case here.
+ */
+ n = cb->length;
+ chars = (jschar *) JS_realloc(cx, cb->chars, (n + 1) * sizeof(jschar));
+ if (!chars)
+ chars = cb->chars;
+ str = js_NewString(cx, chars, n);
+ if (!str)
+ return JS_FALSE;
+
+ /* Successful allocation transfer ownership of cb->chars to the string. */
+#ifdef DEBUG
+ memset(cb, JS_FREE_PATTERN, sizeof *cb);
+#endif
+
+ *rval = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/*
+ * ECMA 3, 15.1.3 URI Handling Function Properties
+ *
+ * The following are implementations of the algorithms
+ * given in the ECMA specification for the hidden functions
+ * 'Encode' and 'Decode'.
+ */
+static JSBool
+Encode(JSContext *cx, JSString *str, const jschar *unescapedSet,
+ const jschar *unescapedSet2, jsval *rval)
+{
+ size_t length, j, k, L;
+ JSCharBuffer cb;
+ jschar *chars, c, c2;
+ uint32 v;
+ uint8 utf8buf[6];
+ jschar hexBuf[4];
+ static const char HexDigits[] = "0123456789ABCDEF"; /* NB: uppercase */
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0) {
+ *rval = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ cb.length = 0;
+ cb.chars = NULL;
+
+ /* From this point the control must goto bad on failures. */
+ hexBuf[0] = '%';
+ hexBuf[3] = 0;
+ for (k = 0; k < length; k++) {
+ c = chars[k];
+ if (js_strchr(unescapedSet, c) ||
+ (unescapedSet2 && js_strchr(unescapedSet2, c))) {
+ if (!AddCharsToURI(cx, &cb, &c, 1))
+ goto bad;
+ } else {
+ if ((c >= 0xDC00) && (c <= 0xDFFF)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_URI, NULL);
+ goto bad;
+ }
+ if (c < 0xD800 || c > 0xDBFF) {
+ v = c;
+ } else {
+ k++;
+ if (k == length) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_URI, NULL);
+ goto bad;
+ }
+ c2 = chars[k];
+ if ((c2 < 0xDC00) || (c2 > 0xDFFF)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_URI, NULL);
+ goto bad;
+ }
+ v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
+ }
+ L = js_OneUcs4ToUtf8Char(utf8buf, v);
+ for (j = 0; j < L; j++) {
+ hexBuf[1] = HexDigits[utf8buf[j] >> 4];
+ hexBuf[2] = HexDigits[utf8buf[j] & 0xf];
+ if (!AddCharsToURI(cx, &cb, hexBuf, 3))
+ goto bad;
+ }
+ }
+ }
+
+ if (!TransferBufferToString(cx, &cb, rval))
+ goto bad;
+
+ return JS_TRUE;
+
+ bad:
+ JS_free(cx, cb.chars);
+ return JS_FALSE;
+}
+
+static JSBool
+Decode(JSContext *cx, JSString *str, const jschar *reservedSet, jsval *rval)
+{
+ size_t length, start, k;
+ JSCharBuffer cb;
+ jschar *chars, c, H;
+ uint32 v;
+ jsuint B;
+ uint8 octets[6];
+ intN j, n;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length == 0) {
+ *rval = STRING_TO_JSVAL(cx->runtime->emptyString);
+ return JS_TRUE;
+ }
+
+ cb.length = 0;
+ cb.chars = NULL;
+
+ /* From this point the control must goto bad on failures. */
+ for (k = 0; k < length; k++) {
+ c = chars[k];
+ if (c == '%') {
+ start = k;
+ if ((k + 2) >= length)
+ goto report_bad_uri;
+ if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2]))
+ goto report_bad_uri;
+ B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]);
+ k += 2;
+ if (!(B & 0x80)) {
+ c = (jschar)B;
+ } else {
+ n = 1;
+ while (B & (0x80 >> n))
+ n++;
+ if (n == 1 || n > 6)
+ goto report_bad_uri;
+ octets[0] = (uint8)B;
+ if (k + 3 * (n - 1) >= length)
+ goto report_bad_uri;
+ for (j = 1; j < n; j++) {
+ k++;
+ if (chars[k] != '%')
+ goto report_bad_uri;
+ if (!JS7_ISHEX(chars[k+1]) || !JS7_ISHEX(chars[k+2]))
+ goto report_bad_uri;
+ B = JS7_UNHEX(chars[k+1]) * 16 + JS7_UNHEX(chars[k+2]);
+ if ((B & 0xC0) != 0x80)
+ goto report_bad_uri;
+ k += 2;
+ octets[j] = (char)B;
+ }
+ v = Utf8ToOneUcs4Char(octets, n);
+ if (v >= 0x10000) {
+ v -= 0x10000;
+ if (v > 0xFFFFF)
+ goto report_bad_uri;
+ c = (jschar)((v & 0x3FF) + 0xDC00);
+ H = (jschar)((v >> 10) + 0xD800);
+ if (!AddCharsToURI(cx, &cb, &H, 1))
+ goto bad;
+ } else {
+ c = (jschar)v;
+ }
+ }
+ if (js_strchr(reservedSet, c)) {
+ if (!AddCharsToURI(cx, &cb, &chars[start], (k - start + 1)))
+ goto bad;
+ } else {
+ if (!AddCharsToURI(cx, &cb, &c, 1))
+ goto bad;
+ }
+ } else {
+ if (!AddCharsToURI(cx, &cb, &c, 1))
+ return JS_FALSE;
+ }
+ }
+
+ if (!TransferBufferToString(cx, &cb, rval))
+ goto bad;
+
+ return JS_TRUE;
+
+ report_bad_uri:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_URI);
+ /* FALL THROUGH */
+
+ bad:
+ JS_free(cx, cb.chars);
+ return JS_FALSE;
+}
+
+static JSBool
+str_decodeURI(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Decode(cx, str, js_uriReservedPlusPound_ucstr, vp);
+}
+
+static JSBool
+str_decodeURI_Component(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Decode(cx, str, js_empty_ucstr, vp);
+}
+
+static JSBool
+str_encodeURI(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Encode(cx, str, js_uriReservedPlusPound_ucstr, js_uriUnescaped_ucstr,
+ vp);
+}
+
+static JSBool
+str_encodeURI_Component(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ str = ArgToRootedString(cx, argc, vp, 0);
+ if (!str)
+ return JS_FALSE;
+ return Encode(cx, str, js_uriUnescaped_ucstr, NULL, vp);
+}
+
+/*
+ * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
+ * least 6 bytes long. Return the number of UTF-8 bytes of data written.
+ */
+int
+js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char)
+{
+ int utf8Length = 1;
+
+ JS_ASSERT(ucs4Char <= 0x7FFFFFFF);
+ if (ucs4Char < 0x80) {
+ *utf8Buffer = (uint8)ucs4Char;
+ } else {
+ int i;
+ uint32 a = ucs4Char >> 11;
+ utf8Length = 2;
+ while (a) {
+ a >>= 5;
+ utf8Length++;
+ }
+ i = utf8Length;
+ while (--i) {
+ utf8Buffer[i] = (uint8)((ucs4Char & 0x3F) | 0x80);
+ ucs4Char >>= 6;
+ }
+ *utf8Buffer = (uint8)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
+ }
+ return utf8Length;
+}
+
+/*
+ * Convert a utf8 character sequence into a UCS-4 character and return that
+ * character. It is assumed that the caller already checked that the sequence
+ * is valid.
+ */
+static uint32
+Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length)
+{
+ uint32 ucs4Char;
+ uint32 minucs4Char;
+ /* from Unicode 3.1, non-shortest form is illegal */
+ static const uint32 minucs4Table[] = {
+ 0x00000080, 0x00000800, 0x0001000, 0x0020000, 0x0400000
+ };
+
+ JS_ASSERT(utf8Length >= 1 && utf8Length <= 6);
+ if (utf8Length == 1) {
+ ucs4Char = *utf8Buffer;
+ JS_ASSERT(!(ucs4Char & 0x80));
+ } else {
+ JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) ==
+ (0x100 - (1 << (8-utf8Length))));
+ ucs4Char = *utf8Buffer++ & ((1<<(7-utf8Length))-1);
+ minucs4Char = minucs4Table[utf8Length-2];
+ while (--utf8Length) {
+ JS_ASSERT((*utf8Buffer & 0xC0) == 0x80);
+ ucs4Char = ucs4Char<<6 | (*utf8Buffer++ & 0x3F);
+ }
+ if (ucs4Char < minucs4Char ||
+ ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) {
+ ucs4Char = 0xFFFD;
+ }
+ }
+ return ucs4Char;
+}
+
+#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
+
+JS_FRIEND_API(size_t)
+js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
+ JSString *str, uint32 quote)
+{
+ jschar *chars, *charsEnd;
+ size_t n;
+ const char *escape;
+ char c;
+ uintN u, hex, shift;
+ enum {
+ STOP, FIRST_QUOTE, LAST_QUOTE, CHARS, ESCAPE_START, ESCAPE_MORE
+ } state;
+
+ JS_ASSERT(quote == 0 || quote == '\'' || quote == '"');
+ JS_ASSERT_IF(buffer, bufferSize != 0);
+ JS_ASSERT_IF(!buffer, bufferSize == 0);
+ JS_ASSERT_IF(fp, !buffer);
+
+ JSSTRING_CHARS_AND_END(str, chars, charsEnd);
+ n = 0;
+ --bufferSize;
+ state = FIRST_QUOTE;
+ shift = 0;
+ hex = 0;
+ u = 0;
+ c = 0; /* to quell GCC warnings */
+
+ for (;;) {
+ switch (state) {
+ case STOP:
+ goto stop;
+ case FIRST_QUOTE:
+ state = CHARS;
+ goto do_quote;
+ case LAST_QUOTE:
+ state = STOP;
+ do_quote:
+ if (quote == 0)
+ continue;
+ c = (char)quote;
+ break;
+ case CHARS:
+ if (chars == charsEnd) {
+ state = LAST_QUOTE;
+ continue;
+ }
+ u = *chars++;
+ if (u < ' ') {
+ if (u != 0) {
+ escape = strchr(js_EscapeMap, (int)u);
+ if (escape) {
+ u = escape[1];
+ goto do_escape;
+ }
+ }
+ goto do_hex_escape;
+ }
+ if (u < 127) {
+ if (u == quote || u == '\\')
+ goto do_escape;
+ c = (char)u;
+ } else if (u < 0x100) {
+ goto do_hex_escape;
+ } else {
+ shift = 16;
+ hex = u;
+ u = 'u';
+ goto do_escape;
+ }
+ break;
+ do_hex_escape:
+ shift = 8;
+ hex = u;
+ u = 'x';
+ do_escape:
+ c = '\\';
+ state = ESCAPE_START;
+ break;
+ case ESCAPE_START:
+ JS_ASSERT(' ' <= u && u < 127);
+ c = (char)u;
+ state = ESCAPE_MORE;
+ break;
+ case ESCAPE_MORE:
+ if (shift == 0) {
+ state = CHARS;
+ continue;
+ }
+ shift -= 4;
+ u = 0xF & (hex >> shift);
+ c = (char)(u + (u < 10 ? '0' : 'A' - 10));
+ break;
+ }
+ if (buffer) {
+ if (n == bufferSize)
+ break;
+ buffer[n] = c;
+ } else if (fp) {
+ fputc(c, fp);
+ }
+ n++;
+ }
+ stop:
+ if (buffer)
+ buffer[n] = '\0';
+ return n;
+}
+
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsstr.h b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.h
new file mode 100644
index 0000000..349754e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsstr.h
@@ -0,0 +1,662 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsstr_h___
+#define jsstr_h___
+/*
+ * JS string type implementation.
+ *
+ * A JS string is a counted array of unicode characters. To support handoff
+ * of API client memory, the chars are allocated separately from the length,
+ * necessitating a pointer after the count, to form a separately allocated
+ * string descriptor. String descriptors are GC'ed, while their chars are
+ * allocated from the malloc heap.
+ */
+#include <ctype.h>
+#include "jspubtd.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * The GC-thing "string" type.
+ *
+ * When the JSSTRFLAG_DEPENDENT bit of the length field is unset, the u.chars
+ * field points to a flat character array owned by its GC-thing descriptor.
+ * The array is terminated at index length by a zero character and the size of
+ * the array in bytes is (length + 1) * sizeof(jschar). The terminator is
+ * purely a backstop, in case the chars pointer flows out to native code that
+ * requires \u0000 termination.
+ *
+ * A flat string with JSSTRFLAG_MUTABLE set means that the string is accessible
+ * only from one thread and it is possible to turn it into a dependent string
+ * of the same length to optimize js_ConcatStrings. It is also possible to grow
+ * such a string, but extreme care must be taken to ensure that no other code
+ * relies on the original length of the string.
+ *
+ * A flat string with JSSTRFLAG_ATOMIZED set means that the string is hashed as
+ * an atom. This flag is used to avoid re-hashing the already-atomized string.
+ *
+ * When JSSTRFLAG_DEPENDENT is set, the string depends on characters of another
+ * string strongly referenced by the u.base field. The base member may point to
+ * another dependent string if JSSTRING_CHARS has not been called yet.
+ *
+ * JSSTRFLAG_PREFIX determines the kind of the dependent string. When the flag
+ * is unset, the length field encodes both starting position relative to the
+ * base string and the number of characters in the dependent string, see
+ * JSSTRDEP_START_MASK and JSSTRDEP_LENGTH_MASK macros below for details.
+ *
+ * When JSSTRFLAG_PREFIX is set, the dependent string is a prefix of the base
+ * string. The number of characters in the prefix is encoded using all non-flag
+ * bits of the length field and spans the same 0 .. SIZE_T_MAX/4 range as the
+ * length of the flat string.
+ *
+ * NB: Always use the JSSTRING_LENGTH and JSSTRING_CHARS accessor macros.
+ */
+struct JSString {
+ size_t length;
+ union {
+ jschar *chars;
+ JSString *base;
+ } u;
+};
+
+/*
+ * Definitions for flags stored in the high order bits of JSString.length.
+ * JSSTRFLAG_PREFIX and JSSTRFLAG_MUTABLE are two aliases for the same value.
+ * JSSTRFLAG_PREFIX should be used only if JSSTRFLAG_DEPENDENT is set and
+ * JSSTRFLAG_MUTABLE should be used only if the string is flat.
+ * JSSTRFLAG_ATOMIZED is used only with the flat immutable strings.
+ */
+#define JSSTRFLAG_DEPENDENT JSSTRING_BIT(JS_BITS_PER_WORD - 1)
+#define JSSTRFLAG_PREFIX JSSTRING_BIT(JS_BITS_PER_WORD - 2)
+#define JSSTRFLAG_MUTABLE JSSTRFLAG_PREFIX
+#define JSSTRFLAG_ATOMIZED JSSTRING_BIT(JS_BITS_PER_WORD - 3)
+
+#define JSSTRING_LENGTH_BITS (JS_BITS_PER_WORD - 3)
+#define JSSTRING_LENGTH_MASK JSSTRING_BITMASK(JSSTRING_LENGTH_BITS)
+
+/* Universal JSString type inquiry and accessor macros. */
+#define JSSTRING_BIT(n) ((size_t)1 << (n))
+#define JSSTRING_BITMASK(n) (JSSTRING_BIT(n) - 1)
+#define JSSTRING_HAS_FLAG(str,flg) ((str)->length & (flg))
+#define JSSTRING_IS_DEPENDENT(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_DEPENDENT)
+#define JSSTRING_IS_FLAT(str) (!JSSTRING_IS_DEPENDENT(str))
+#define JSSTRING_IS_MUTABLE(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \
+ JSSTRFLAG_MUTABLE)) == \
+ JSSTRFLAG_MUTABLE)
+#define JSSTRING_IS_ATOMIZED(str) (((str)->length & (JSSTRFLAG_DEPENDENT | \
+ JSSTRFLAG_ATOMIZED)) ==\
+ JSSTRFLAG_ATOMIZED)
+
+#define JSSTRING_CHARS(str) (JSSTRING_IS_DEPENDENT(str) \
+ ? JSSTRDEP_CHARS(str) \
+ : JSFLATSTR_CHARS(str))
+#define JSSTRING_LENGTH(str) (JSSTRING_IS_DEPENDENT(str) \
+ ? JSSTRDEP_LENGTH(str) \
+ : JSFLATSTR_LENGTH(str))
+
+#define JSSTRING_CHARS_AND_LENGTH(str, chars_, length_) \
+ ((void)(JSSTRING_IS_DEPENDENT(str) \
+ ? ((length_) = JSSTRDEP_LENGTH(str), \
+ (chars_) = JSSTRDEP_CHARS(str)) \
+ : ((length_) = JSFLATSTR_LENGTH(str), \
+ (chars_) = JSFLATSTR_CHARS(str))))
+
+#define JSSTRING_CHARS_AND_END(str, chars_, end) \
+ ((void)((end) = JSSTRING_IS_DEPENDENT(str) \
+ ? JSSTRDEP_LENGTH(str) + ((chars_) = JSSTRDEP_CHARS(str)) \
+ : JSFLATSTR_LENGTH(str) + ((chars_) = JSFLATSTR_CHARS(str))))
+
+/* Specific flat string initializer and accessor macros. */
+#define JSFLATSTR_INIT(str, chars_, length_) \
+ ((void)(JS_ASSERT(((length_) & ~JSSTRING_LENGTH_MASK) == 0), \
+ (str)->length = (length_), (str)->u.chars = (chars_)))
+
+#define JSFLATSTR_LENGTH(str) \
+ (JS_ASSERT(JSSTRING_IS_FLAT(str)), (str)->length & JSSTRING_LENGTH_MASK)
+
+#define JSFLATSTR_CHARS(str) \
+ (JS_ASSERT(JSSTRING_IS_FLAT(str)), (str)->u.chars)
+
+/*
+ * Macros to manipulate atomized and mutable flags of flat strings. It is safe
+ * to use these without extra locking due to the following properties:
+ *
+ * * We do not have a macro like JSFLATSTR_CLEAR_ATOMIZED as a string
+ * remains atomized until the GC collects it.
+ *
+ * * A thread may call JSFLATSTR_SET_MUTABLE only when it is the only thread
+ * accessing the string until a later call to JSFLATSTR_CLEAR_MUTABLE.
+ *
+ * * Multiple threads can call JSFLATSTR_CLEAR_MUTABLE but the macro
+ * actually clears the mutable flag only when the flag is set -- in which
+ * case only one thread can access the string (see previous property).
+ *
+ * Thus, when multiple threads access the string, JSFLATSTR_SET_ATOMIZED is
+ * the only macro that can update the length field of the string by changing
+ * the mutable bit from 0 to 1. We call the macro only after the string has
+ * been hashed. When some threads in js_ValueToStringId see that the flag is
+ * set, it knows that the string was atomized.
+ *
+ * On the other hand, if the thread sees that the flag is unset, it could be
+ * seeing a stale value when another thread has just atomized the string and
+ * set the flag. But this can lead only to an extra call to js_AtomizeString.
+ * This function would find that the string was already hashed and return it
+ * with the atomized bit set.
+ */
+#define JSFLATSTR_SET_ATOMIZED(str) \
+ ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_MUTABLE(str)), \
+ (str)->length |= JSSTRFLAG_ATOMIZED))
+
+#define JSFLATSTR_SET_MUTABLE(str) \
+ ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str) && !JSSTRING_IS_ATOMIZED(str)), \
+ (str)->length |= JSSTRFLAG_MUTABLE))
+
+#define JSFLATSTR_CLEAR_MUTABLE(str) \
+ ((void)(JS_ASSERT(JSSTRING_IS_FLAT(str)), \
+ JSSTRING_HAS_FLAG(str, JSSTRFLAG_MUTABLE) && \
+ ((str)->length &= ~JSSTRFLAG_MUTABLE)))
+
+/* Specific dependent string shift/mask accessor and mutator macros. */
+#define JSSTRDEP_START_BITS (JSSTRING_LENGTH_BITS-JSSTRDEP_LENGTH_BITS)
+#define JSSTRDEP_START_SHIFT JSSTRDEP_LENGTH_BITS
+#define JSSTRDEP_START_MASK JSSTRING_BITMASK(JSSTRDEP_START_BITS)
+#define JSSTRDEP_LENGTH_BITS (JSSTRING_LENGTH_BITS / 2)
+#define JSSTRDEP_LENGTH_MASK JSSTRING_BITMASK(JSSTRDEP_LENGTH_BITS)
+
+#define JSSTRDEP_IS_PREFIX(str) JSSTRING_HAS_FLAG(str, JSSTRFLAG_PREFIX)
+
+#define JSSTRDEP_START(str) (JSSTRDEP_IS_PREFIX(str) ? 0 \
+ : (((str)->length \
+ >> JSSTRDEP_START_SHIFT) \
+ & JSSTRDEP_START_MASK))
+#define JSSTRDEP_LENGTH(str) ((str)->length \
+ & (JSSTRDEP_IS_PREFIX(str) \
+ ? JSSTRING_LENGTH_MASK \
+ : JSSTRDEP_LENGTH_MASK))
+
+#define JSSTRDEP_INIT(str,bstr,off,len) \
+ ((str)->length = JSSTRFLAG_DEPENDENT \
+ | ((off) << JSSTRDEP_START_SHIFT) \
+ | (len), \
+ (str)->u.base = (bstr))
+
+#define JSPREFIX_INIT(str,bstr,len) \
+ ((str)->length = JSSTRFLAG_DEPENDENT | JSSTRFLAG_PREFIX | (len), \
+ (str)->u.base = (bstr))
+
+#define JSSTRDEP_BASE(str) ((str)->u.base)
+#define JSPREFIX_BASE(str) JSSTRDEP_BASE(str)
+#define JSPREFIX_SET_BASE(str,bstr) ((str)->u.base = (bstr))
+
+#define JSSTRDEP_CHARS(str) \
+ (JSSTRING_IS_DEPENDENT(JSSTRDEP_BASE(str)) \
+ ? js_GetDependentStringChars(str) \
+ : JSFLATSTR_CHARS(JSSTRDEP_BASE(str)) + JSSTRDEP_START(str))
+
+extern size_t
+js_MinimizeDependentStrings(JSString *str, int level, JSString **basep);
+
+extern jschar *
+js_GetDependentStringChars(JSString *str);
+
+extern const jschar *
+js_GetStringChars(JSContext *cx, JSString *str);
+
+extern JSString * JS_FASTCALL
+js_ConcatStrings(JSContext *cx, JSString *left, JSString *right);
+
+extern const jschar *
+js_UndependString(JSContext *cx, JSString *str);
+
+extern JSBool
+js_MakeStringImmutable(JSContext *cx, JSString *str);
+
+extern JSString* JS_FASTCALL
+js_toLowerCase(JSContext *cx, JSString *str);
+
+extern JSString* JS_FASTCALL
+js_toUpperCase(JSContext *cx, JSString *str);
+
+typedef struct JSCharBuffer {
+ size_t length;
+ jschar *chars;
+} JSCharBuffer;
+
+struct JSSubString {
+ size_t length;
+ const jschar *chars;
+};
+
+extern jschar js_empty_ucstr[];
+extern JSSubString js_EmptySubString;
+
+/* Unicode character attribute lookup tables. */
+extern const uint8 js_X[];
+extern const uint8 js_Y[];
+extern const uint32 js_A[];
+
+/* Enumerated Unicode general category types. */
+typedef enum JSCharType {
+ JSCT_UNASSIGNED = 0,
+ JSCT_UPPERCASE_LETTER = 1,
+ JSCT_LOWERCASE_LETTER = 2,
+ JSCT_TITLECASE_LETTER = 3,
+ JSCT_MODIFIER_LETTER = 4,
+ JSCT_OTHER_LETTER = 5,
+ JSCT_NON_SPACING_MARK = 6,
+ JSCT_ENCLOSING_MARK = 7,
+ JSCT_COMBINING_SPACING_MARK = 8,
+ JSCT_DECIMAL_DIGIT_NUMBER = 9,
+ JSCT_LETTER_NUMBER = 10,
+ JSCT_OTHER_NUMBER = 11,
+ JSCT_SPACE_SEPARATOR = 12,
+ JSCT_LINE_SEPARATOR = 13,
+ JSCT_PARAGRAPH_SEPARATOR = 14,
+ JSCT_CONTROL = 15,
+ JSCT_FORMAT = 16,
+ JSCT_PRIVATE_USE = 18,
+ JSCT_SURROGATE = 19,
+ JSCT_DASH_PUNCTUATION = 20,
+ JSCT_START_PUNCTUATION = 21,
+ JSCT_END_PUNCTUATION = 22,
+ JSCT_CONNECTOR_PUNCTUATION = 23,
+ JSCT_OTHER_PUNCTUATION = 24,
+ JSCT_MATH_SYMBOL = 25,
+ JSCT_CURRENCY_SYMBOL = 26,
+ JSCT_MODIFIER_SYMBOL = 27,
+ JSCT_OTHER_SYMBOL = 28
+} JSCharType;
+
+/* Character classifying and mapping macros, based on java.lang.Character. */
+#define JS_CCODE(c) (js_A[js_Y[(js_X[(uint16)(c)>>6]<<6)|((c)&0x3F)]])
+#define JS_CTYPE(c) (JS_CCODE(c) & 0x1F)
+
+#define JS_ISALPHA(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER)) \
+ >> JS_CTYPE(c)) & 1)
+
+#define JS_ISALNUM(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER) | \
+ (1 << JSCT_DECIMAL_DIGIT_NUMBER)) \
+ >> JS_CTYPE(c)) & 1)
+
+/* A unicode letter, suitable for use in an identifier. */
+#define JS_ISLETTER(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER) | \
+ (1 << JSCT_LETTER_NUMBER)) \
+ >> JS_CTYPE(c)) & 1)
+
+/*
+ * 'IdentifierPart' from ECMA grammar, is Unicode letter or combining mark or
+ * digit or connector punctuation.
+ */
+#define JS_ISIDPART(c) ((((1 << JSCT_UPPERCASE_LETTER) | \
+ (1 << JSCT_LOWERCASE_LETTER) | \
+ (1 << JSCT_TITLECASE_LETTER) | \
+ (1 << JSCT_MODIFIER_LETTER) | \
+ (1 << JSCT_OTHER_LETTER) | \
+ (1 << JSCT_LETTER_NUMBER) | \
+ (1 << JSCT_NON_SPACING_MARK) | \
+ (1 << JSCT_COMBINING_SPACING_MARK) | \
+ (1 << JSCT_DECIMAL_DIGIT_NUMBER) | \
+ (1 << JSCT_CONNECTOR_PUNCTUATION)) \
+ >> JS_CTYPE(c)) & 1)
+
+/* Unicode control-format characters, ignored in input */
+#define JS_ISFORMAT(c) (((1 << JSCT_FORMAT) >> JS_CTYPE(c)) & 1)
+
+/*
+ * Per ECMA-262 15.10.2.6, these characters are the only ones that make up a
+ * "word", as far as a RegExp is concerned. If we want a Unicode-friendlier
+ * definition of "word", we should rename this macro to something regexp-y.
+ */
+#define JS_ISWORD(c) ((c) < 128 && (isalnum(c) || (c) == '_'))
+
+#define JS_ISIDSTART(c) (JS_ISLETTER(c) || (c) == '_' || (c) == '$')
+#define JS_ISIDENT(c) (JS_ISIDPART(c) || (c) == '_' || (c) == '$')
+
+#define JS_ISXMLSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || \
+ (c) == '\n')
+#define JS_ISXMLNSSTART(c) ((JS_CCODE(c) & 0x00000100) || (c) == '_')
+#define JS_ISXMLNS(c) ((JS_CCODE(c) & 0x00000080) || (c) == '.' || \
+ (c) == '-' || (c) == '_')
+#define JS_ISXMLNAMESTART(c) (JS_ISXMLNSSTART(c) || (c) == ':')
+#define JS_ISXMLNAME(c) (JS_ISXMLNS(c) || (c) == ':')
+
+#define JS_ISDIGIT(c) (JS_CTYPE(c) == JSCT_DECIMAL_DIGIT_NUMBER)
+
+/* XXXbe unify on A/X/Y tbls, avoid ctype.h? */
+/* XXXbe fs, etc. ? */
+#define JS_ISSPACE(c) ((JS_CCODE(c) & 0x00070000) == 0x00040000)
+#define JS_ISPRINT(c) ((c) < 128 && isprint(c))
+
+#define JS_ISUPPER(c) (JS_CTYPE(c) == JSCT_UPPERCASE_LETTER)
+#define JS_ISLOWER(c) (JS_CTYPE(c) == JSCT_LOWERCASE_LETTER)
+
+#define JS_TOUPPER(c) ((jschar) ((JS_CCODE(c) & 0x00100000) \
+ ? (c) - ((int32)JS_CCODE(c) >> 22) \
+ : (c)))
+#define JS_TOLOWER(c) ((jschar) ((JS_CCODE(c) & 0x00200000) \
+ ? (c) + ((int32)JS_CCODE(c) >> 22) \
+ : (c)))
+
+/*
+ * Shorthands for ASCII (7-bit) decimal and hex conversion.
+ * Manually inline isdigit for performance; MSVC doesn't do this for us.
+ */
+#define JS7_ISDEC(c) ((((unsigned)(c)) - '0') <= 9)
+#define JS7_UNDEC(c) ((c) - '0')
+#define JS7_ISHEX(c) ((c) < 128 && isxdigit(c))
+#define JS7_UNHEX(c) (uintN)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a')
+#define JS7_ISLET(c) ((c) < 128 && isalpha(c))
+
+/* Initialize per-runtime string state for the first context in the runtime. */
+extern JSBool
+js_InitRuntimeStringState(JSContext *cx);
+
+extern JSBool
+js_InitDeflatedStringCache(JSRuntime *rt);
+
+/*
+ * Maximum character code for which we will create a pinned unit string on
+ * demand -- see JSRuntime.unitStrings in jscntxt.h.
+ */
+#define UNIT_STRING_LIMIT 256U
+
+/*
+ * Get the independent string containing only character code at index in str
+ * (backstopped with a zero character as usual for independent strings).
+ */
+extern JSString *
+js_GetUnitString(JSContext *cx, JSString *str, size_t index);
+
+/*
+ * Get the independent string containing only the character code c, which must
+ * be less than UNIT_STRING_LIMIT.
+ */
+extern JSString *
+js_GetUnitStringForChar(JSContext *cx, jschar c);
+
+extern void
+js_FinishUnitStrings(JSRuntime *rt);
+
+extern void
+js_FinishRuntimeStringState(JSContext *cx);
+
+extern void
+js_FinishDeflatedStringCache(JSRuntime *rt);
+
+/* Initialize the String class, returning its prototype object. */
+extern JSClass js_StringClass;
+
+extern JSObject *
+js_InitStringClass(JSContext *cx, JSObject *obj);
+
+extern const char js_escape_str[];
+extern const char js_unescape_str[];
+extern const char js_uneval_str[];
+extern const char js_decodeURI_str[];
+extern const char js_encodeURI_str[];
+extern const char js_decodeURIComponent_str[];
+extern const char js_encodeURIComponent_str[];
+
+/* GC-allocate a string descriptor for the given malloc-allocated chars. */
+extern JSString *
+js_NewString(JSContext *cx, jschar *chars, size_t length);
+
+extern JSString *
+js_NewDependentString(JSContext *cx, JSString *base, size_t start,
+ size_t length);
+
+/* Copy a counted string and GC-allocate a descriptor for it. */
+extern JSString *
+js_NewStringCopyN(JSContext *cx, const jschar *s, size_t n);
+
+/* Copy a C string and GC-allocate a descriptor for it. */
+extern JSString *
+js_NewStringCopyZ(JSContext *cx, const jschar *s);
+
+/*
+ * Free the chars held by str when it is finalized by the GC. When type is
+ * less then zero, it denotes an internal string. Otherwise it denotes the
+ * type of the external string allocated with JS_NewExternalString.
+ *
+ * This function always needs rt but can live with null cx.
+ */
+extern void
+js_FinalizeStringRT(JSRuntime *rt, JSString *str, intN type, JSContext *cx);
+
+/*
+ * Convert a value to a printable C string.
+ */
+typedef JSString *(*JSValueToStringFun)(JSContext *cx, jsval v);
+
+extern JS_FRIEND_API(const char *)
+js_ValueToPrintable(JSContext *cx, jsval v, JSValueToStringFun v2sfun);
+
+#define js_ValueToPrintableString(cx,v) \
+ js_ValueToPrintable(cx, v, js_ValueToString)
+
+#define js_ValueToPrintableSource(cx,v) \
+ js_ValueToPrintable(cx, v, js_ValueToSource)
+
+/*
+ * Convert a value to a string, returning null after reporting an error,
+ * otherwise returning a new string reference.
+ */
+extern JS_FRIEND_API(JSString *)
+js_ValueToString(JSContext *cx, jsval v);
+
+/*
+ * Convert a value to its source expression, returning null after reporting
+ * an error, otherwise returning a new string reference.
+ */
+extern JS_FRIEND_API(JSString *)
+js_ValueToSource(JSContext *cx, jsval v);
+
+/*
+ * Compute a hash function from str. The caller can call this function even if
+ * str is not a GC-allocated thing.
+ */
+extern uint32
+js_HashString(JSString *str);
+
+/*
+ * Test if strings are equal. The caller can call the function even if str1
+ * or str2 are not GC-allocated things.
+ */
+extern JSBool JS_FASTCALL
+js_EqualStrings(JSString *str1, JSString *str2);
+
+/*
+ * Return less than, equal to, or greater than zero depending on whether
+ * str1 is less than, equal to, or greater than str2.
+ */
+extern int32 JS_FASTCALL
+js_CompareStrings(JSString *str1, JSString *str2);
+
+/*
+ * Boyer-Moore-Horspool superlinear search for pat:patlen in text:textlen.
+ * The patlen argument must be positive and no greater than BMH_PATLEN_MAX.
+ * The start argument tells where in text to begin the search.
+ *
+ * Return the index of pat in text, or -1 if not found.
+ */
+#define BMH_CHARSET_SIZE 256 /* ISO-Latin-1 */
+#define BMH_PATLEN_MAX 255 /* skip table element is uint8 */
+
+#define BMH_BAD_PATTERN (-2) /* return value if pat is not ISO-Latin-1 */
+
+extern jsint
+js_BoyerMooreHorspool(const jschar *text, jsint textlen,
+ const jschar *pat, jsint patlen,
+ jsint start);
+
+extern size_t
+js_strlen(const jschar *s);
+
+extern jschar *
+js_strchr(const jschar *s, jschar c);
+
+extern jschar *
+js_strchr_limit(const jschar *s, jschar c, const jschar *limit);
+
+#define js_strncpy(t, s, n) memcpy((t), (s), (n) * sizeof(jschar))
+
+/*
+ * Return s advanced past any Unicode white space characters.
+ */
+extern const jschar *
+js_SkipWhiteSpace(const jschar *s, const jschar *end);
+
+/*
+ * Inflate bytes to JS chars and vice versa. Report out of memory via cx
+ * and return null on error, otherwise return the jschar or byte vector that
+ * was JS_malloc'ed. length is updated with the length of the new string in jschars.
+ */
+extern jschar *
+js_InflateString(JSContext *cx, const char *bytes, size_t *length);
+
+extern char *
+js_DeflateString(JSContext *cx, const jschar *chars, size_t length);
+
+/*
+ * Inflate bytes to JS chars into a buffer. 'chars' must be large enough for
+ * 'length' jschars. The buffer is NOT null-terminated. The destination length
+ * must be be initialized with the buffer size and will contain on return the
+ * number of copied chars.
+ */
+extern JSBool
+js_InflateStringToBuffer(JSContext* cx, const char *bytes, size_t length,
+ jschar *chars, size_t* charsLength);
+
+/*
+ * Get number of bytes in the deflated sequence of characters.
+ */
+extern size_t
+js_GetDeflatedStringLength(JSContext *cx, const jschar *chars,
+ size_t charsLength);
+
+/*
+ * Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
+ * 'length chars. The buffer is NOT null-terminated. The destination length
+ * must to be initialized with the buffer size and will contain on return the
+ * number of copied bytes.
+ */
+extern JSBool
+js_DeflateStringToBuffer(JSContext* cx, const jschar *chars,
+ size_t charsLength, char *bytes, size_t* length);
+
+/*
+ * Associate bytes with str in the deflated string cache, returning true on
+ * successful association, false on out of memory.
+ */
+extern JSBool
+js_SetStringBytes(JSContext *cx, JSString *str, char *bytes, size_t length);
+
+/*
+ * Find or create a deflated string cache entry for str that contains its
+ * characters chopped from Unicode code points into bytes.
+ */
+extern const char *
+js_GetStringBytes(JSContext *cx, JSString *str);
+
+/* Remove a deflated string cache entry associated with str if any. */
+extern void
+js_PurgeDeflatedStringCache(JSRuntime *rt, JSString *str);
+
+/* Export a few natives and a helper to other files in SpiderMonkey. */
+extern JSBool
+js_str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval);
+
+extern JSBool
+js_StringMatchHelper(JSContext *cx, uintN argc, jsval *vp, jsbytecode *pc);
+
+extern JSBool
+js_StringReplaceHelper(JSContext *cx, uintN argc, JSObject *lambda,
+ JSString *repstr, jsval *vp);
+
+/*
+ * Convert one UCS-4 char and write it into a UTF-8 buffer, which must be at
+ * least 6 bytes long. Return the number of UTF-8 bytes of data written.
+ */
+extern int
+js_OneUcs4ToUtf8Char(uint8 *utf8Buffer, uint32 ucs4Char);
+
+/*
+ * Write str into buffer escaping any non-printable or non-ASCII character.
+ * Guarantees that a NUL is at the end of the buffer. Returns the length of
+ * the written output, NOT including the NUL. If buffer is null, just returns
+ * the length of the output. If quote is not 0, it must be a single or double
+ * quote character that will quote the output.
+ *
+ * The function is only defined for debug builds.
+*/
+#define js_PutEscapedString(buffer, bufferSize, str, quote) \
+ js_PutEscapedStringImpl(buffer, bufferSize, NULL, str, quote)
+
+/*
+ * Write str into file escaping any non-printable or non-ASCII character.
+ * Returns the number of bytes written to file. If quote is not 0, it must
+ * be a single or double quote character that will quote the output.
+ *
+ * The function is only defined for debug builds.
+*/
+#define js_FileEscapedString(file, str, quote) \
+ (JS_ASSERT(file), js_PutEscapedStringImpl(NULL, 0, file, str, quote))
+
+extern JS_FRIEND_API(size_t)
+js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
+ JSString *str, uint32 quote);
+
+JS_END_EXTERN_C
+
+#endif /* jsstr_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp
new file mode 100644
index 0000000..7cfb474
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.cpp
@@ -0,0 +1,8276 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ * Andreas Gal <gal@mozilla.com>
+ * Mike Shaver <shaver@mozilla.org>
+ * David Anderson <danderson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h" // always first
+#include "jsbit.h" // low-level (NSPR-based) headers next
+#include "jsprf.h"
+#include <math.h> // standard headers next
+#ifdef _MSC_VER
+#include <malloc.h>
+#define alloca _alloca
+#endif
+#ifdef SOLARIS
+#include <alloca.h>
+#endif
+
+#include "nanojit/nanojit.h"
+#include "jsarray.h" // higher-level library and API headers
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsdbgapi.h"
+#include "jsemit.h"
+#include "jsfun.h"
+#include "jsinterp.h"
+#include "jsiter.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsregexp.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsdate.h"
+#include "jsstaticcheck.h"
+#include "jstracer.h"
+
+#include "jsautooplen.h" // generated headers last
+
+/* Never use JSVAL_IS_BOOLEAN because it restricts the value (true, false) and
+ the type. What you want to use is JSVAL_TAG(x) == JSVAL_BOOLEAN and then
+ handle the undefined case properly (bug 457363). */
+#undef JSVAL_IS_BOOLEAN
+#define JSVAL_IS_BOOLEAN(x) JS_STATIC_ASSERT(0)
+
+/* Use a fake tag to represent boxed values, borrowing from the integer tag
+ range since we only use JSVAL_INT to indicate integers. */
+#define JSVAL_BOXED 3
+
+/* Map to translate a type tag into a printable representation. */
+static const char typeChar[] = "OIDVS?B?";
+
+/* Number of iterations of a loop where we start tracing. That is, we don't
+ start tracing until the beginning of the HOTLOOP-th iteration. */
+#define HOTLOOP 2
+
+/* Number of times we wait to exit on a side exit before we try to extend the tree. */
+#define HOTEXIT 1
+
+/* Max call depths for inlining. */
+#define MAX_CALLDEPTH 10
+
+/* Max number of type mismatchs before we trash the tree. */
+#define MAX_MISMATCH 20
+
+/* Max blacklist level of inner tree immediate recompiling */
+#define MAX_INNER_RECORD_BLACKLIST -16
+
+/* Max native stack size. */
+#define MAX_NATIVE_STACK_SLOTS 1024
+
+/* Max call stack size. */
+#define MAX_CALL_STACK_ENTRIES 64
+
+/* Max number of branches per tree. */
+#define MAX_BRANCHES 16
+
+/* Macros for demote slot lists */
+#define ALLOCA_UNDEMOTE_SLOTLIST(num) (unsigned*)alloca(((num) + 1) * sizeof(unsigned))
+#define ADD_UNDEMOTE_SLOT(list, slot) list[++list[0]] = slot
+#define NUM_UNDEMOTE_SLOTS(list) list[0]
+#define CLEAR_UNDEMOTE_SLOTLIST(list) list[0] = 0
+
+#ifdef JS_JIT_SPEW
+#define ABORT_TRACE(msg) do { debug_only_v(fprintf(stdout, "abort: %d: %s\n", __LINE__, msg);) return false; } while (0)
+#else
+#define ABORT_TRACE(msg) return false
+#endif
+
+#ifdef JS_JIT_SPEW
+struct __jitstats {
+#define JITSTAT(x) uint64 x;
+#include "jitstats.tbl"
+#undef JITSTAT
+} jitstats = { 0LL, };
+
+JS_STATIC_ASSERT(sizeof(jitstats) % sizeof(uint64) == 0);
+
+enum jitstat_ids {
+#define JITSTAT(x) STAT ## x ## ID,
+#include "jitstats.tbl"
+#undef JITSTAT
+ STAT_IDS_TOTAL
+};
+
+static JSPropertySpec jitstats_props[] = {
+#define JITSTAT(x) { #x, STAT ## x ## ID, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT },
+#include "jitstats.tbl"
+#undef JITSTAT
+ { 0 }
+};
+
+static JSBool
+jitstats_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ int index = -1;
+
+ if (JSVAL_IS_STRING(id)) {
+ JSString* str = JSVAL_TO_STRING(id);
+ if (strcmp(JS_GetStringBytes(str), "HOTLOOP") == 0) {
+ *vp = INT_TO_JSVAL(HOTLOOP);
+ return JS_TRUE;
+ }
+ }
+
+ if (JSVAL_IS_INT(id))
+ index = JSVAL_TO_INT(id);
+
+ uint64 result = 0;
+ switch (index) {
+#define JITSTAT(x) case STAT ## x ## ID: result = jitstats.x; break;
+#include "jitstats.tbl"
+#undef JITSTAT
+ default:
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ if (result < JSVAL_INT_MAX) {
+ *vp = INT_TO_JSVAL(result);
+ return JS_TRUE;
+ }
+ char retstr[64];
+ JS_snprintf(retstr, sizeof retstr, "%llu", result);
+ *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, retstr));
+ return JS_TRUE;
+}
+
+JSClass jitstats_class = {
+ "jitstats",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub,
+ jitstats_getProperty, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub,
+ JS_ConvertStub, JS_FinalizeStub,
+ JSCLASS_NO_OPTIONAL_MEMBERS
+};
+
+void
+js_InitJITStatsClass(JSContext *cx, JSObject *glob)
+{
+ JS_InitClass(cx, glob, NULL, &jitstats_class, NULL, 0, jitstats_props, NULL, NULL, NULL);
+}
+
+#define AUDIT(x) (jitstats.x++)
+#else
+#define AUDIT(x) ((void)0)
+#endif /* JS_JIT_SPEW */
+
+#define INS_CONST(c) addName(lir->insImm(c), #c)
+#define INS_CONSTPTR(p) addName(lir->insImmPtr((void*) (p)), #p)
+
+using namespace avmplus;
+using namespace nanojit;
+
+static GC gc = GC();
+static avmplus::AvmCore s_core = avmplus::AvmCore();
+static avmplus::AvmCore* core = &s_core;
+
+#ifdef JS_JIT_SPEW
+void
+js_DumpPeerStability(Fragmento* frago, const void* ip);
+#endif
+
+/* We really need a better way to configure the JIT. Shaver, where is my fancy JIT object? */
+static bool nesting_enabled = true;
+#if defined(NANOJIT_IA32)
+static bool did_we_check_sse2 = false;
+#endif
+
+#ifdef JS_JIT_SPEW
+static bool verbose_debug = getenv("TRACEMONKEY") && strstr(getenv("TRACEMONKEY"), "verbose");
+#define debug_only_v(x) if (verbose_debug) { x; }
+#else
+#define debug_only_v(x)
+#endif
+
+/* The entire VM shares one oracle. Collisions and concurrent updates are tolerated and worst
+ case cause performance regressions. */
+static Oracle oracle;
+
+/* Blacklists the root peer fragment at a fragment's PC. This is so blacklisting stays at the
+ top of the peer list and not scattered around. */
+void
+js_BlacklistPC(Fragmento* frago, Fragment* frag);
+
+Tracker::Tracker()
+{
+ pagelist = 0;
+}
+
+Tracker::~Tracker()
+{
+ clear();
+}
+
+jsuword
+Tracker::getPageBase(const void* v) const
+{
+ return jsuword(v) & ~jsuword(NJ_PAGE_SIZE-1);
+}
+
+struct Tracker::Page*
+Tracker::findPage(const void* v) const
+{
+ jsuword base = getPageBase(v);
+ struct Tracker::Page* p = pagelist;
+ while (p) {
+ if (p->base == base) {
+ return p;
+ }
+ p = p->next;
+ }
+ return 0;
+}
+
+struct Tracker::Page*
+Tracker::addPage(const void* v) {
+ jsuword base = getPageBase(v);
+ struct Tracker::Page* p = (struct Tracker::Page*)
+ GC::Alloc(sizeof(*p) - sizeof(p->map) + (NJ_PAGE_SIZE >> 2) * sizeof(LIns*));
+ p->base = base;
+ p->next = pagelist;
+ pagelist = p;
+ return p;
+}
+
+void
+Tracker::clear()
+{
+ while (pagelist) {
+ Page* p = pagelist;
+ pagelist = pagelist->next;
+ GC::Free(p);
+ }
+}
+
+bool
+Tracker::has(const void *v) const
+{
+ return get(v) != NULL;
+}
+
+#if defined NANOJIT_64BIT
+#define PAGEMASK 0x7ff
+#else
+#define PAGEMASK 0xfff
+#endif
+
+LIns*
+Tracker::get(const void* v) const
+{
+ struct Tracker::Page* p = findPage(v);
+ if (!p)
+ return NULL;
+ return p->map[(jsuword(v) & PAGEMASK) >> 2];
+}
+
+void
+Tracker::set(const void* v, LIns* i)
+{
+ struct Tracker::Page* p = findPage(v);
+ if (!p)
+ p = addPage(v);
+ p->map[(jsuword(v) & PAGEMASK) >> 2] = i;
+}
+
+static inline bool isNumber(jsval v)
+{
+ return JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v);
+}
+
+static inline jsdouble asNumber(jsval v)
+{
+ JS_ASSERT(isNumber(v));
+ if (JSVAL_IS_DOUBLE(v))
+ return *JSVAL_TO_DOUBLE(v);
+ return (jsdouble)JSVAL_TO_INT(v);
+}
+
+static inline bool isInt32(jsval v)
+{
+ if (!isNumber(v))
+ return false;
+ jsdouble d = asNumber(v);
+ jsint i;
+ return JSDOUBLE_IS_INT(d, i);
+}
+
+/* Return JSVAL_DOUBLE for all numbers (int and double) and the tag otherwise. */
+static inline uint8 getPromotedType(jsval v)
+{
+ return JSVAL_IS_INT(v) ? JSVAL_DOUBLE : uint8(JSVAL_TAG(v));
+}
+
+/* Return JSVAL_INT for all whole numbers that fit into signed 32-bit and the tag otherwise. */
+static inline uint8 getCoercedType(jsval v)
+{
+ return isInt32(v) ? JSVAL_INT : (uint8) JSVAL_TAG(v);
+}
+
+/* Tell the oracle that a certain global variable should not be demoted. */
+void
+Oracle::markGlobalSlotUndemotable(JSScript* script, unsigned slot)
+{
+ _dontDemote.set(&gc, (slot % ORACLE_SIZE));
+}
+
+/* Consult with the oracle whether we shouldn't demote a certain global variable. */
+bool
+Oracle::isGlobalSlotUndemotable(JSScript* script, unsigned slot) const
+{
+ return _dontDemote.get(slot % ORACLE_SIZE);
+}
+
+/* Tell the oracle that a certain slot at a certain bytecode location should not be demoted. */
+void
+Oracle::markStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot)
+{
+ uint32 hash = uint32(intptr_t(ip)) + (slot << 5);
+ hash %= ORACLE_SIZE;
+ _dontDemote.set(&gc, hash);
+}
+
+/* Consult with the oracle whether we shouldn't demote a certain slot. */
+bool
+Oracle::isStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot) const
+{
+ uint32 hash = uint32(intptr_t(ip)) + (slot << 5);
+ hash %= ORACLE_SIZE;
+ return _dontDemote.get(hash);
+}
+
+/* Clear the oracle. */
+void
+Oracle::clear()
+{
+ _dontDemote.reset();
+}
+
+#if defined(NJ_SOFTFLOAT)
+JS_DEFINE_CALLINFO_1(static, DOUBLE, i2f, INT32, 1, 1)
+JS_DEFINE_CALLINFO_1(static, DOUBLE, u2f, UINT32, 1, 1)
+#endif
+
+static bool isi2f(LInsp i)
+{
+ if (i->isop(LIR_i2f))
+ return true;
+
+#if defined(NJ_SOFTFLOAT)
+ if (i->isop(LIR_qjoin) &&
+ i->oprnd1()->isop(LIR_call) &&
+ i->oprnd2()->isop(LIR_callh))
+ {
+ if (i->oprnd1()->callInfo() == &i2f_ci)
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static bool isu2f(LInsp i)
+{
+ if (i->isop(LIR_u2f))
+ return true;
+
+#if defined(NJ_SOFTFLOAT)
+ if (i->isop(LIR_qjoin) &&
+ i->oprnd1()->isop(LIR_call) &&
+ i->oprnd2()->isop(LIR_callh))
+ {
+ if (i->oprnd1()->callInfo() == &u2f_ci)
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+static LInsp iu2fArg(LInsp i)
+{
+#if defined(NJ_SOFTFLOAT)
+ if (i->isop(LIR_qjoin))
+ return i->oprnd1()->arg(0);
+#endif
+
+ return i->oprnd1();
+}
+
+
+static LIns* demote(LirWriter *out, LInsp i)
+{
+ if (i->isCall())
+ return callArgN(i, 0);
+ if (isi2f(i) || isu2f(i))
+ return iu2fArg(i);
+ if (i->isconst())
+ return i;
+ AvmAssert(i->isconstq());
+ double cf = i->constvalf();
+ int32_t ci = cf > 0x7fffffff ? uint32_t(cf) : int32_t(cf);
+ return out->insImm(ci);
+}
+
+static bool isPromoteInt(LIns* i)
+{
+ jsdouble d;
+ return isi2f(i) || i->isconst() ||
+ (i->isconstq() && (d = i->constvalf()) == jsdouble(jsint(d)) && !JSDOUBLE_IS_NEGZERO(d));
+}
+
+static bool isPromoteUint(LIns* i)
+{
+ jsdouble d;
+ return isu2f(i) || i->isconst() ||
+ (i->isconstq() && (d = i->constvalf()) == (jsdouble)(jsuint)d && !JSDOUBLE_IS_NEGZERO(d));
+}
+
+static bool isPromote(LIns* i)
+{
+ return isPromoteInt(i) || isPromoteUint(i);
+}
+
+static bool isconst(LIns* i, int32_t c)
+{
+ return i->isconst() && i->constval() == c;
+}
+
+static bool overflowSafe(LIns* i)
+{
+ LIns* c;
+ return (i->isop(LIR_and) && ((c = i->oprnd2())->isconst()) &&
+ ((c->constval() & 0xc0000000) == 0)) ||
+ (i->isop(LIR_rsh) && ((c = i->oprnd2())->isconst()) &&
+ ((c->constval() > 0)));
+}
+
+#if defined(NJ_SOFTFLOAT)
+/* soft float */
+
+JS_DEFINE_CALLINFO_1(static, DOUBLE, fneg, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmpeq, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmplt, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmple, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmpgt, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, INT32, fcmpge, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fmul, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fadd, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fdiv, DOUBLE, DOUBLE, 1, 1)
+JS_DEFINE_CALLINFO_2(static, DOUBLE, fsub, DOUBLE, DOUBLE, 1, 1)
+
+jsdouble FASTCALL
+fneg(jsdouble x)
+{
+ return -x;
+}
+
+jsdouble FASTCALL
+i2f(int32 i)
+{
+ return i;
+}
+
+jsdouble FASTCALL
+u2f(jsuint u)
+{
+ return u;
+}
+
+int32 FASTCALL
+fcmpeq(jsdouble x, jsdouble y)
+{
+ return x==y;
+}
+
+int32 FASTCALL
+fcmplt(jsdouble x, jsdouble y)
+{
+ return x < y;
+}
+
+int32 FASTCALL
+fcmple(jsdouble x, jsdouble y)
+{
+ return x <= y;
+}
+
+int32 FASTCALL
+fcmpgt(jsdouble x, jsdouble y)
+{
+ return x > y;
+}
+
+int32 FASTCALL
+fcmpge(jsdouble x, jsdouble y)
+{
+ return x >= y;
+}
+
+jsdouble FASTCALL
+fmul(jsdouble x, jsdouble y)
+{
+ return x * y;
+}
+
+jsdouble FASTCALL
+fadd(jsdouble x, jsdouble y)
+{
+ return x + y;
+}
+
+jsdouble FASTCALL
+fdiv(jsdouble x, jsdouble y)
+{
+ return x / y;
+}
+
+jsdouble FASTCALL
+fsub(jsdouble x, jsdouble y)
+{
+ return x - y;
+}
+
+class SoftFloatFilter: public LirWriter
+{
+public:
+ SoftFloatFilter(LirWriter* out):
+ LirWriter(out)
+ {
+ }
+
+ LInsp quadCall(const CallInfo *ci, LInsp args[]) {
+ LInsp qlo, qhi;
+
+ qlo = out->insCall(ci, args);
+ qhi = out->ins1(LIR_callh, qlo);
+ return out->qjoin(qlo, qhi);
+ }
+
+ LInsp ins1(LOpcode v, LInsp s0)
+ {
+ if (v == LIR_fneg)
+ return quadCall(&fneg_ci, &s0);
+
+ if (v == LIR_i2f)
+ return quadCall(&i2f_ci, &s0);
+
+ if (v == LIR_u2f)
+ return quadCall(&u2f_ci, &s0);
+
+ return out->ins1(v, s0);
+ }
+
+ LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
+ {
+ LInsp args[2];
+ LInsp bv;
+
+ // change the numeric value and order of these LIR opcodes and die
+ if (LIR_fadd <= v && v <= LIR_fdiv) {
+ static const CallInfo *fmap[] = { &fadd_ci, &fsub_ci, &fmul_ci, &fdiv_ci };
+
+ args[0] = s1;
+ args[1] = s0;
+
+ return quadCall(fmap[v - LIR_fadd], args);
+ }
+
+ if (LIR_feq <= v && v <= LIR_fge) {
+ static const CallInfo *fmap[] = { &fcmpeq_ci, &fcmplt_ci, &fcmpgt_ci, &fcmple_ci, &fcmpge_ci };
+
+ args[0] = s1;
+ args[1] = s0;
+
+ bv = out->insCall(fmap[v - LIR_feq], args);
+ return out->ins2(LIR_eq, bv, out->insImm(1));
+ }
+
+ return out->ins2(v, s0, s1);
+ }
+
+ LInsp insCall(const CallInfo *ci, LInsp args[])
+ {
+ // if the return type is ARGSIZE_F, we have
+ // to do a quadCall ( qjoin(call,callh) )
+ if ((ci->_argtypes & 3) == ARGSIZE_F)
+ return quadCall(ci, args);
+
+ return out->insCall(ci, args);
+ }
+};
+
+#endif // NJ_SOFTFLOAT
+
+class FuncFilter: public LirWriter
+{
+public:
+ FuncFilter(LirWriter* out):
+ LirWriter(out)
+ {
+ }
+
+ LInsp ins2(LOpcode v, LInsp s0, LInsp s1)
+ {
+ if (s0 == s1 && v == LIR_feq) {
+ if (isPromote(s0)) {
+ // double(int) and double(uint) cannot be nan
+ return insImm(1);
+ }
+ if (s0->isop(LIR_fmul) || s0->isop(LIR_fsub) || s0->isop(LIR_fadd)) {
+ LInsp lhs = s0->oprnd1();
+ LInsp rhs = s0->oprnd2();
+ if (isPromote(lhs) && isPromote(rhs)) {
+ // add/sub/mul promoted ints can't be nan
+ return insImm(1);
+ }
+ }
+ } else if (LIR_feq <= v && v <= LIR_fge) {
+ if (isPromoteInt(s0) && isPromoteInt(s1)) {
+ // demote fcmp to cmp
+ v = LOpcode(v + (LIR_eq - LIR_feq));
+ return out->ins2(v, demote(out, s0), demote(out, s1));
+ } else if (isPromoteUint(s0) && isPromoteUint(s1)) {
+ // uint compare
+ v = LOpcode(v + (LIR_eq - LIR_feq));
+ if (v != LIR_eq)
+ v = LOpcode(v + (LIR_ult - LIR_lt)); // cmp -> ucmp
+ return out->ins2(v, demote(out, s0), demote(out, s1));
+ }
+ } else if (v == LIR_or &&
+ s0->isop(LIR_lsh) && isconst(s0->oprnd2(), 16) &&
+ s1->isop(LIR_and) && isconst(s1->oprnd2(), 0xffff)) {
+ LIns* msw = s0->oprnd1();
+ LIns* lsw = s1->oprnd1();
+ LIns* x;
+ LIns* y;
+ if (lsw->isop(LIR_add) &&
+ lsw->oprnd1()->isop(LIR_and) &&
+ lsw->oprnd2()->isop(LIR_and) &&
+ isconst(lsw->oprnd1()->oprnd2(), 0xffff) &&
+ isconst(lsw->oprnd2()->oprnd2(), 0xffff) &&
+ msw->isop(LIR_add) &&
+ msw->oprnd1()->isop(LIR_add) &&
+ msw->oprnd2()->isop(LIR_rsh) &&
+ msw->oprnd1()->oprnd1()->isop(LIR_rsh) &&
+ msw->oprnd1()->oprnd2()->isop(LIR_rsh) &&
+ isconst(msw->oprnd2()->oprnd2(), 16) &&
+ isconst(msw->oprnd1()->oprnd1()->oprnd2(), 16) &&
+ isconst(msw->oprnd1()->oprnd2()->oprnd2(), 16) &&
+ (x = lsw->oprnd1()->oprnd1()) == msw->oprnd1()->oprnd1()->oprnd1() &&
+ (y = lsw->oprnd2()->oprnd1()) == msw->oprnd1()->oprnd2()->oprnd1() &&
+ lsw == msw->oprnd2()->oprnd1()) {
+ return out->ins2(LIR_add, x, y);
+ }
+ }
+#ifdef NANOJIT_ARM
+ else if (v == LIR_lsh ||
+ v == LIR_rsh ||
+ v == LIR_ush)
+ {
+ // needed on ARM -- arm doesn't mask shifts to 31 like x86 does
+ if (s1->isconst())
+ s1->setimm16(s1->constval() & 31);
+ else
+ s1 = out->ins2(LIR_and, s1, out->insImm(31));
+ return out->ins2(v, s0, s1);
+ }
+#endif
+
+ return out->ins2(v, s0, s1);
+ }
+
+ LInsp insCall(const CallInfo *ci, LInsp args[])
+ {
+ LInsp s0 = args[0];
+ if (ci == &js_DoubleToUint32_ci) {
+ if (s0->isconstq())
+ return out->insImm(js_DoubleToECMAUint32(s0->constvalf()));
+ if (isi2f(s0) || isu2f(s0))
+ return iu2fArg(s0);
+ } else if (ci == &js_DoubleToInt32_ci) {
+ if (s0->isconstq())
+ return out->insImm(js_DoubleToECMAInt32(s0->constvalf()));
+ if (s0->isop(LIR_fadd) || s0->isop(LIR_fsub)) {
+ LInsp lhs = s0->oprnd1();
+ LInsp rhs = s0->oprnd2();
+ if (isPromote(lhs) && isPromote(rhs)) {
+ LOpcode op = LOpcode(s0->opcode() & ~LIR64);
+ return out->ins2(op, demote(out, lhs), demote(out, rhs));
+ }
+ }
+ if (isi2f(s0) || isu2f(s0))
+ return iu2fArg(s0);
+ // XXX ARM -- check for qjoin(call(UnboxDouble),call(UnboxDouble))
+ if (s0->isCall() && s0->callInfo() == &js_UnboxDouble_ci) {
+ LIns* args2[] = { callArgN(s0, 0) };
+ return out->insCall(&js_UnboxInt32_ci, args2);
+ }
+ if (s0->isCall() && s0->callInfo() == &js_StringToNumber_ci) {
+ // callArgN's ordering is that as seen by the builtin, not as stored in args here.
+ // True story!
+ LIns* args2[] = { callArgN(s0, 1), callArgN(s0, 0) };
+ return out->insCall(&js_StringToInt32_ci, args2);
+ }
+ } else if (ci == &js_BoxDouble_ci) {
+ JS_ASSERT(s0->isQuad());
+ if (s0->isop(LIR_i2f)) {
+ LIns* args2[] = { s0->oprnd1(), args[1] };
+ return out->insCall(&js_BoxInt32_ci, args2);
+ }
+ if (s0->isCall() && s0->callInfo() == &js_UnboxDouble_ci)
+ return callArgN(s0, 0);
+ }
+ return out->insCall(ci, args);
+ }
+};
+
+/* In debug mode vpname contains a textual description of the type of the
+ slot during the forall iteration over al slots. */
+#ifdef JS_JIT_SPEW
+#define DEF_VPNAME const char* vpname; unsigned vpnum
+#define SET_VPNAME(name) do { vpname = name; vpnum = 0; } while(0)
+#define INC_VPNUM() do { ++vpnum; } while(0)
+#else
+#define DEF_VPNAME do {} while (0)
+#define vpname ""
+#define vpnum 0
+#define SET_VPNAME(name) ((void)0)
+#define INC_VPNUM() ((void)0)
+#endif
+
+/* Iterate over all interned global variables. */
+#define FORALL_GLOBAL_SLOTS(cx, ngslots, gslots, code) \
+ JS_BEGIN_MACRO \
+ DEF_VPNAME; \
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain); \
+ unsigned n; \
+ jsval* vp; \
+ SET_VPNAME("global"); \
+ for (n = 0; n < ngslots; ++n) { \
+ vp = &STOBJ_GET_SLOT(globalObj, gslots[n]); \
+ { code; } \
+ INC_VPNUM(); \
+ } \
+ JS_END_MACRO
+
+/* Iterate over all slots in the frame, consisting of args, vars, and stack
+ (except for the top-level frame which does not have args or vars. */
+#define FORALL_FRAME_SLOTS(fp, depth, code) \
+ JS_BEGIN_MACRO \
+ jsval* vp; \
+ jsval* vpstop; \
+ if (fp->callee) { \
+ if (depth == 0) { \
+ SET_VPNAME("callee"); \
+ vp = &fp->argv[-2]; \
+ { code; } \
+ SET_VPNAME("this"); \
+ vp = &fp->argv[-1]; \
+ { code; } \
+ SET_VPNAME("argv"); \
+ vp = &fp->argv[0]; vpstop = &fp->argv[fp->fun->nargs]; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ } \
+ SET_VPNAME("vars"); \
+ vp = fp->slots; vpstop = &fp->slots[fp->script->nfixed]; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ } \
+ SET_VPNAME("stack"); \
+ vp = StackBase(fp); vpstop = fp->regs->sp; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ if (fsp < fspstop - 1) { \
+ JSStackFrame* fp2 = fsp[1]; \
+ int missing = fp2->fun->nargs - fp2->argc; \
+ if (missing > 0) { \
+ SET_VPNAME("missing"); \
+ vp = fp->regs->sp; \
+ vpstop = vp + missing; \
+ while (vp < vpstop) { code; ++vp; INC_VPNUM(); } \
+ } \
+ } \
+ JS_END_MACRO
+
+/* Iterate over all slots in each pending frame. */
+#define FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth, code) \
+ JS_BEGIN_MACRO \
+ DEF_VPNAME; \
+ unsigned n; \
+ JSStackFrame* currentFrame = cx->fp; \
+ JSStackFrame* entryFrame; \
+ JSStackFrame* fp = currentFrame; \
+ for (n = 0; n < callDepth; ++n) { fp = fp->down; } \
+ entryFrame = fp; \
+ unsigned frames = callDepth+1; \
+ JSStackFrame** fstack = \
+ (JSStackFrame**) alloca(frames * sizeof (JSStackFrame*)); \
+ JSStackFrame** fspstop = &fstack[frames]; \
+ JSStackFrame** fsp = fspstop-1; \
+ fp = currentFrame; \
+ for (;; fp = fp->down) { *fsp-- = fp; if (fp == entryFrame) break; } \
+ unsigned depth; \
+ for (depth = 0, fsp = fstack; fsp < fspstop; ++fsp, ++depth) { \
+ fp = *fsp; \
+ FORALL_FRAME_SLOTS(fp, depth, code); \
+ } \
+ JS_END_MACRO
+
+#define FORALL_SLOTS(cx, ngslots, gslots, callDepth, code) \
+ JS_BEGIN_MACRO \
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots, code); \
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth, code); \
+ JS_END_MACRO
+
+/* Calculate the total number of native frame slots we need from this frame
+ all the way back to the entry frame, including the current stack usage. */
+unsigned
+js_NativeStackSlots(JSContext *cx, unsigned callDepth)
+{
+ JSStackFrame* fp = cx->fp;
+ unsigned slots = 0;
+#if defined _DEBUG
+ unsigned int origCallDepth = callDepth;
+#endif
+ for (;;) {
+ unsigned operands = fp->regs->sp - StackBase(fp);
+ slots += operands;
+ if (fp->callee)
+ slots += fp->script->nfixed;
+ if (callDepth-- == 0) {
+ if (fp->callee)
+ slots += 2/*callee,this*/ + fp->fun->nargs;
+#if defined _DEBUG
+ unsigned int m = 0;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, origCallDepth, m++);
+ JS_ASSERT(m == slots);
+#endif
+ return slots;
+ }
+ JSStackFrame* fp2 = fp;
+ fp = fp->down;
+ int missing = fp2->fun->nargs - fp2->argc;
+ if (missing > 0)
+ slots += missing;
+ }
+ JS_NOT_REACHED("js_NativeStackSlots");
+}
+
+/* Capture the type map for the selected slots of the global object. */
+void
+TypeMap::captureGlobalTypes(JSContext* cx, SlotList& slots)
+{
+ unsigned ngslots = slots.length();
+ uint16* gslots = slots.data();
+ setLength(ngslots);
+ uint8* map = data();
+ uint8* m = map;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ uint8 type = getCoercedType(*vp);
+ if ((type == JSVAL_INT) && oracle.isGlobalSlotUndemotable(cx->fp->script, gslots[n]))
+ type = JSVAL_DOUBLE;
+ JS_ASSERT(type != JSVAL_BOXED);
+ *m++ = type;
+ );
+}
+
+/* Capture the type map for the currently pending stack frames. */
+void
+TypeMap::captureStackTypes(JSContext* cx, unsigned callDepth)
+{
+ setLength(js_NativeStackSlots(cx, callDepth));
+ uint8* map = data();
+ uint8* m = map;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ uint8 type = getCoercedType(*vp);
+ if ((type == JSVAL_INT) &&
+ oracle.isStackSlotUndemotable(cx->fp->script, cx->fp->regs->pc, unsigned(m - map))) {
+ type = JSVAL_DOUBLE;
+ }
+ debug_only_v(printf("capture %s%d: %d\n", vpname, vpnum, type);)
+ *m++ = type;
+ );
+}
+
+/* Compare this type map to another one and see whether they match. */
+bool
+TypeMap::matches(TypeMap& other) const
+{
+ if (length() != other.length())
+ return false;
+ return !memcmp(data(), other.data(), length());
+}
+
+/* Use the provided storage area to create a new type map that contains the partial type map
+ with the rest of it filled up from the complete type map. */
+static void
+mergeTypeMaps(uint8** partial, unsigned* plength, uint8* complete, unsigned clength, uint8* mem)
+{
+ unsigned l = *plength;
+ JS_ASSERT(l < clength);
+ memcpy(mem, *partial, l * sizeof(uint8));
+ memcpy(mem + l, complete + l, (clength - l) * sizeof(uint8));
+ *partial = mem;
+ *plength = clength;
+}
+
+static void
+js_TrashTree(JSContext* cx, Fragment* f);
+
+TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* _anchor, Fragment* _fragment,
+ TreeInfo* ti, unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
+ VMSideExit* innermostNestedGuard, Fragment* outerToBlacklist)
+{
+ JS_ASSERT(!_fragment->vmprivate && ti);
+
+ this->cx = cx;
+ this->traceMonitor = &JS_TRACE_MONITOR(cx);
+ this->globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ this->anchor = _anchor;
+ this->fragment = _fragment;
+ this->lirbuf = _fragment->lirbuf;
+ this->treeInfo = ti;
+ this->callDepth = _anchor ? _anchor->calldepth : 0;
+ this->atoms = cx->fp->script->atomMap.vector;
+ this->deepAborted = false;
+ this->applyingArguments = false;
+ this->trashTree = false;
+ this->whichTreeToTrash = _fragment->root;
+ this->global_dslots = this->globalObj->dslots;
+ this->terminate = false;
+ this->outerToBlacklist = outerToBlacklist;
+ this->wasRootFragment = _fragment == _fragment->root;
+
+ debug_only_v(printf("recording starting from %s:%u@%u\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+ debug_only_v(printf("globalObj=%p, shape=%d\n", this->globalObj, OBJ_SHAPE(this->globalObj));)
+
+ lir = lir_buf_writer = new (&gc) LirBufWriter(lirbuf);
+#ifdef DEBUG
+ if (verbose_debug)
+ lir = verbose_filter = new (&gc) VerboseWriter(&gc, lir, lirbuf->names);
+#endif
+#ifdef NJ_SOFTFLOAT
+ lir = float_filter = new (&gc) SoftFloatFilter(lir);
+#endif
+ lir = cse_filter = new (&gc) CseFilter(lir, &gc);
+ lir = expr_filter = new (&gc) ExprFilter(lir);
+ lir = func_filter = new (&gc) FuncFilter(lir);
+ lir->ins0(LIR_start);
+
+ if (!nanojit::AvmCore::config.tree_opt || fragment->root == fragment)
+ lirbuf->state = addName(lir->insParam(0, 0), "state");
+
+ lirbuf->sp = addName(lir->insLoad(LIR_ldp, lirbuf->state, (int)offsetof(InterpState, sp)), "sp");
+ lirbuf->rp = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, rp)), "rp");
+ cx_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, cx)), "cx");
+ gp_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, gp)), "gp");
+ eos_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eos)), "eos");
+ eor_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state, offsetof(InterpState, eor)), "eor");
+
+ /* read into registers all values on the stack and all globals we know so far */
+ import(treeInfo, lirbuf->sp, ngslots, callDepth, globalTypeMap, stackTypeMap);
+
+ /* If we are attached to a tree call guard, make sure the guard the inner tree exited from
+ is what we expect it to be. */
+ if (_anchor && _anchor->exitType == NESTED_EXIT) {
+ LIns* nested_ins = addName(lir->insLoad(LIR_ldp, lirbuf->state,
+ offsetof(InterpState, lastTreeExitGuard)),
+ "lastTreeExitGuard");
+ guard(true, lir->ins2(LIR_eq, nested_ins, INS_CONSTPTR(innermostNestedGuard)), NESTED_EXIT);
+ }
+}
+
+TreeInfo::~TreeInfo()
+{
+ UnstableExit* temp;
+
+ while (unstableExits) {
+ temp = unstableExits->next;
+ delete unstableExits;
+ unstableExits = temp;
+ }
+}
+
+TraceRecorder::~TraceRecorder()
+{
+ JS_ASSERT(nextRecorderToAbort == NULL);
+ JS_ASSERT(treeInfo && (fragment || wasDeepAborted()));
+#ifdef DEBUG
+ TraceRecorder* tr = JS_TRACE_MONITOR(cx).abortStack;
+ while (tr != NULL)
+ {
+ JS_ASSERT(this != tr);
+ tr = tr->nextRecorderToAbort;
+ }
+#endif
+ if (fragment) {
+ if (wasRootFragment && !fragment->root->code()) {
+ JS_ASSERT(!fragment->root->vmprivate);
+ delete treeInfo;
+ }
+ if (trashTree)
+ js_TrashTree(cx, whichTreeToTrash);
+ } else if (wasRootFragment) {
+ delete treeInfo;
+ }
+#ifdef DEBUG
+ delete verbose_filter;
+#endif
+ delete cse_filter;
+ delete expr_filter;
+ delete func_filter;
+#ifdef NJ_SOFTFLOAT
+ delete float_filter;
+#endif
+ delete lir_buf_writer;
+}
+
+void TraceRecorder::removeFragmentoReferences()
+{
+ fragment = NULL;
+}
+
+/* Add debug information to a LIR instruction as we emit it. */
+inline LIns*
+TraceRecorder::addName(LIns* ins, const char* name)
+{
+#ifdef DEBUG
+ lirbuf->names->addName(ins, name);
+#endif
+ return ins;
+}
+
+/* Determine the current call depth (starting with the entry frame.) */
+unsigned
+TraceRecorder::getCallDepth() const
+{
+ return callDepth;
+}
+
+/* Determine the offset in the native global frame for a jsval we track */
+ptrdiff_t
+TraceRecorder::nativeGlobalOffset(jsval* p) const
+{
+ JS_ASSERT(isGlobal(p));
+ if (size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS)
+ return size_t(p - globalObj->fslots) * sizeof(double);
+ return ((p - globalObj->dslots) + JS_INITIAL_NSLOTS) * sizeof(double);
+}
+
+/* Determine whether a value is a global stack slot */
+bool
+TraceRecorder::isGlobal(jsval* p) const
+{
+ return ((size_t(p - globalObj->fslots) < JS_INITIAL_NSLOTS) ||
+ (size_t(p - globalObj->dslots) < (STOBJ_NSLOTS(globalObj) - JS_INITIAL_NSLOTS)));
+}
+
+/* Determine the offset in the native stack for a jsval we track */
+ptrdiff_t
+TraceRecorder::nativeStackOffset(jsval* p) const
+{
+#ifdef DEBUG
+ size_t slow_offset = 0;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ if (vp == p) goto done;
+ slow_offset += sizeof(double)
+ );
+
+ /*
+ * If it's not in a pending frame, it must be on the stack of the current frame above
+ * sp but below fp->slots + script->nslots.
+ */
+ JS_ASSERT(size_t(p - cx->fp->slots) < cx->fp->script->nslots);
+ slow_offset += size_t(p - cx->fp->regs->sp) * sizeof(double);
+
+done:
+#define RETURN(offset) { JS_ASSERT((offset) == slow_offset); return offset; }
+#else
+#define RETURN(offset) { return offset; }
+#endif
+ size_t offset = 0;
+ JSStackFrame* currentFrame = cx->fp;
+ JSStackFrame* entryFrame;
+ JSStackFrame* fp = currentFrame;
+ for (unsigned n = 0; n < callDepth; ++n) { fp = fp->down; }
+ entryFrame = fp;
+ unsigned frames = callDepth+1;
+ JSStackFrame** fstack = (JSStackFrame **)alloca(frames * sizeof (JSStackFrame *));
+ JSStackFrame** fspstop = &fstack[frames];
+ JSStackFrame** fsp = fspstop-1;
+ fp = currentFrame;
+ for (;; fp = fp->down) { *fsp-- = fp; if (fp == entryFrame) break; }
+ for (fsp = fstack; fsp < fspstop; ++fsp) {
+ fp = *fsp;
+ if (fp->callee) {
+ if (fsp == fstack) {
+ if (size_t(p - &fp->argv[-2]) < size_t(2/*callee,this*/ + fp->fun->nargs))
+ RETURN(offset + size_t(p - &fp->argv[-2]) * sizeof(double));
+ offset += (2/*callee,this*/ + fp->fun->nargs) * sizeof(double);
+ }
+ if (size_t(p - &fp->slots[0]) < fp->script->nfixed)
+ RETURN(offset + size_t(p - &fp->slots[0]) * sizeof(double));
+ offset += fp->script->nfixed * sizeof(double);
+ }
+ jsval* spbase = StackBase(fp);
+ if (size_t(p - spbase) < size_t(fp->regs->sp - spbase))
+ RETURN(offset + size_t(p - spbase) * sizeof(double));
+ offset += size_t(fp->regs->sp - spbase) * sizeof(double);
+ if (fsp < fspstop - 1) {
+ JSStackFrame* fp2 = fsp[1];
+ int missing = fp2->fun->nargs - fp2->argc;
+ if (missing > 0) {
+ if (size_t(p - fp->regs->sp) < size_t(missing))
+ RETURN(offset + size_t(p - fp->regs->sp) * sizeof(double));
+ offset += size_t(missing) * sizeof(double);
+ }
+ }
+ }
+
+ /*
+ * If it's not in a pending frame, it must be on the stack of the current frame above
+ * sp but below fp->slots + script->nslots.
+ */
+ JS_ASSERT(size_t(p - currentFrame->slots) < currentFrame->script->nslots);
+ offset += size_t(p - currentFrame->regs->sp) * sizeof(double);
+ RETURN(offset);
+#undef RETURN
+}
+
+/* Track the maximum number of native frame slots we need during
+ execution. */
+void
+TraceRecorder::trackNativeStackUse(unsigned slots)
+{
+ if (slots > treeInfo->maxNativeStackSlots)
+ treeInfo->maxNativeStackSlots = slots;
+}
+
+/* Unbox a jsval into a slot. Slots are wide enough to hold double values directly (instead of
+ storing a pointer to them). We now assert instead of type checking, the caller must ensure the
+ types are compatible. */
+static void
+ValueToNative(JSContext* cx, jsval v, uint8 type, double* slot)
+{
+ unsigned tag = JSVAL_TAG(v);
+ switch (type) {
+ case JSVAL_INT:
+ jsint i;
+ if (JSVAL_IS_INT(v))
+ *(jsint*)slot = JSVAL_TO_INT(v);
+ else if ((tag == JSVAL_DOUBLE) && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(v), i))
+ *(jsint*)slot = i;
+ else
+ JS_ASSERT(JSVAL_IS_INT(v));
+ debug_only_v(printf("int<%d> ", *(jsint*)slot);)
+ return;
+ case JSVAL_DOUBLE:
+ jsdouble d;
+ if (JSVAL_IS_INT(v))
+ d = JSVAL_TO_INT(v);
+ else
+ d = *JSVAL_TO_DOUBLE(v);
+ JS_ASSERT(JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v));
+ *(jsdouble*)slot = d;
+ debug_only_v(printf("double<%g> ", d);)
+ return;
+ case JSVAL_BOOLEAN:
+ JS_ASSERT(tag == JSVAL_BOOLEAN);
+ *(JSBool*)slot = JSVAL_TO_BOOLEAN(v);
+ debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
+ return;
+ case JSVAL_STRING:
+ JS_ASSERT(tag == JSVAL_STRING);
+ *(JSString**)slot = JSVAL_TO_STRING(v);
+ debug_only_v(printf("string<%p> ", *(JSString**)slot);)
+ return;
+ default:
+ /* Note: we should never see JSVAL_BOXED in an entry type map. */
+ JS_ASSERT(type == JSVAL_OBJECT);
+ JS_ASSERT(tag == JSVAL_OBJECT);
+ *(JSObject**)slot = JSVAL_TO_OBJECT(v);
+ debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
+ JSVAL_IS_NULL(v)
+ ? "null"
+ : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);)
+ return;
+ }
+}
+
+/* We maintain an emergency recovery pool of doubles so we can recover safely if a trace runs
+ out of memory (doubles or objects). */
+static jsval
+AllocateDoubleFromRecoveryPool(JSContext* cx)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ JS_ASSERT(tm->recoveryDoublePoolPtr > tm->recoveryDoublePool);
+ return *--tm->recoveryDoublePoolPtr;
+}
+
+static bool
+js_ReplenishRecoveryPool(JSContext* cx, JSTraceMonitor* tm)
+{
+ /* We should not be called with a full pool. */
+ JS_ASSERT((size_t) (tm->recoveryDoublePoolPtr - tm->recoveryDoublePool) <
+ MAX_NATIVE_STACK_SLOTS);
+
+ /*
+ * When the GC runs in js_NewDoubleInRootedValue, it resets
+ * tm->recoveryDoublePoolPtr back to tm->recoveryDoublePool.
+ */
+ JSRuntime* rt = cx->runtime;
+ uintN gcNumber = rt->gcNumber;
+ jsval* ptr = tm->recoveryDoublePoolPtr;
+ while (ptr < tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS) {
+ if (!js_NewDoubleInRootedValue(cx, 0.0, ptr))
+ goto oom;
+ if (rt->gcNumber != gcNumber) {
+ JS_ASSERT(tm->recoveryDoublePoolPtr == tm->recoveryDoublePool);
+ ptr = tm->recoveryDoublePool;
+ if (uintN(rt->gcNumber - gcNumber) > uintN(1))
+ goto oom;
+ continue;
+ }
+ ++ptr;
+ }
+ tm->recoveryDoublePoolPtr = ptr;
+ return true;
+
+oom:
+ /*
+ * Already massive GC pressure, no need to hold doubles back.
+ * We won't run any native code anyway.
+ */
+ tm->recoveryDoublePoolPtr = tm->recoveryDoublePool;
+ return false;
+}
+
+/* Box a value from the native stack back into the jsval format. Integers
+ that are too large to fit into a jsval are automatically boxed into
+ heap-allocated doubles. */
+static bool
+NativeToValue(JSContext* cx, jsval& v, uint8 type, double* slot)
+{
+ jsint i;
+ jsdouble d;
+ switch (type) {
+ case JSVAL_BOOLEAN:
+ v = BOOLEAN_TO_JSVAL(*(JSBool*)slot);
+ debug_only_v(printf("boolean<%d> ", *(JSBool*)slot);)
+ break;
+ case JSVAL_INT:
+ i = *(jsint*)slot;
+ debug_only_v(printf("int<%d> ", i);)
+ store_int:
+ if (INT_FITS_IN_JSVAL(i)) {
+ v = INT_TO_JSVAL(i);
+ break;
+ }
+ d = (jsdouble)i;
+ goto store_double;
+ case JSVAL_DOUBLE:
+ d = *slot;
+ debug_only_v(printf("double<%g> ", d);)
+ if (JSDOUBLE_IS_INT(d, i))
+ goto store_int;
+ store_double: {
+ /* Its not safe to trigger the GC here, so use an emergency heap if we are out of
+ double boxes. */
+ if (cx->doubleFreeList) {
+#ifdef DEBUG
+ bool ok =
+#endif
+ js_NewDoubleInRootedValue(cx, d, &v);
+ JS_ASSERT(ok);
+ return true;
+ }
+ v = AllocateDoubleFromRecoveryPool(cx);
+ JS_ASSERT(JSVAL_IS_DOUBLE(v) && *JSVAL_TO_DOUBLE(v) == 0.0);
+ *JSVAL_TO_DOUBLE(v) = d;
+ return true;
+ }
+ case JSVAL_STRING:
+ v = STRING_TO_JSVAL(*(JSString**)slot);
+ JS_ASSERT(JSVAL_TAG(v) == JSVAL_STRING); /* if this fails the pointer was not aligned */
+ debug_only_v(printf("string<%p> ", *(JSString**)slot);)
+ break;
+ case JSVAL_BOXED:
+ v = *(jsval*)slot;
+ debug_only_v(printf("box<%lx> ", v));
+ break;
+ default:
+ JS_ASSERT(type == JSVAL_OBJECT);
+ v = OBJECT_TO_JSVAL(*(JSObject**)slot);
+ JS_ASSERT(JSVAL_TAG(v) == JSVAL_OBJECT); /* if this fails the pointer was not aligned */
+ debug_only_v(printf("object<%p:%s> ", JSVAL_TO_OBJECT(v),
+ JSVAL_IS_NULL(v)
+ ? "null"
+ : STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v))->name);)
+ break;
+ }
+ return true;
+}
+
+/* Attempt to unbox the given list of interned globals onto the native global frame. */
+static void
+BuildNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* mp, double* np)
+{
+ debug_only_v(printf("global: ");)
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ ValueToNative(cx, *vp, *mp, np + gslots[n]);
+ ++mp;
+ );
+ debug_only_v(printf("\n");)
+}
+
+/* Attempt to unbox the given JS frame onto a native frame. */
+static void
+BuildNativeStackFrame(JSContext* cx, unsigned callDepth, uint8* mp, double* np)
+{
+ debug_only_v(printf("stack: ");)
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ debug_only_v(printf("%s%u=", vpname, vpnum);)
+ ValueToNative(cx, *vp, *mp, np);
+ ++mp; ++np;
+ );
+ debug_only_v(printf("\n");)
+}
+
+/* Box the given native frame into a JS frame. This only fails due to a hard error
+ (out of memory for example). */
+static int
+FlushNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* mp, double* np)
+{
+ uint8* mp_base = mp;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ if (!NativeToValue(cx, *vp, *mp, np + gslots[n]))
+ return -1;
+ ++mp;
+ );
+ debug_only_v(printf("\n");)
+ return mp - mp_base;
+}
+
+/**
+ * Box the given native stack frame into the virtual machine stack. This fails
+ * only due to a hard error (out of memory for example).
+ *
+ * @param callDepth the distance between the entry frame into our trace and
+ * cx->fp when we make this call. If this is not called as a
+ * result of a nested exit, callDepth is 0.
+ * @param mp pointer to an array of type tags (JSVAL_INT, etc.) that indicate
+ * what the types of the things on the stack are.
+ * @param np pointer to the native stack. We want to copy values from here to
+ * the JS stack as needed.
+ * @param stopFrame if non-null, this frame and everything above it should not
+ * be restored.
+ * @return the number of things we popped off of np.
+ */
+static int
+FlushNativeStackFrame(JSContext* cx, unsigned callDepth, uint8* mp, double* np,
+ JSStackFrame* stopFrame)
+{
+ jsval* stopAt = stopFrame ? &stopFrame->argv[-2] : NULL;
+ uint8* mp_base = mp;
+ /* Root all string and object references first (we don't need to call the GC for this). */
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ if (vp == stopAt) goto skip;
+ debug_only_v(printf("%s%u=", vpname, vpnum);)
+ if (!NativeToValue(cx, *vp, *mp, np))
+ return -1;
+ ++mp; ++np
+ );
+skip:
+ // Restore thisp from the now-restored argv[-1] in each pending frame.
+ // Keep in mind that we didn't restore frames at stopFrame and above!
+ // Scope to keep |fp| from leaking into the macros we're using.
+ {
+ unsigned n = callDepth+1; // +1 to make sure we restore the entry frame
+ JSStackFrame* fp = cx->fp;
+ if (stopFrame) {
+ for (; fp != stopFrame; fp = fp->down) {
+ JS_ASSERT(n != 0);
+ --n;
+ }
+ // Skip over stopFrame itself.
+ JS_ASSERT(n != 0);
+ --n;
+ fp = fp->down;
+ }
+ for (; n != 0; fp = fp->down) {
+ --n;
+ if (fp->callee) { // might not have it if the entry frame is global
+ JS_ASSERT(JSVAL_IS_OBJECT(fp->argv[-1]));
+ fp->thisp = JSVAL_TO_OBJECT(fp->argv[-1]);
+ }
+ }
+ }
+ debug_only_v(printf("\n");)
+ return mp - mp_base;
+}
+
+/* Emit load instructions onto the trace that read the initial stack state. */
+void
+TraceRecorder::import(LIns* base, ptrdiff_t offset, jsval* p, uint8& t,
+ const char *prefix, uintN index, JSStackFrame *fp)
+{
+ LIns* ins;
+ if (t == JSVAL_INT) { /* demoted */
+ JS_ASSERT(isInt32(*p));
+ /* Ok, we have a valid demotion attempt pending, so insert an integer
+ read and promote it to double since all arithmetic operations expect
+ to see doubles on entry. The first op to use this slot will emit a
+ f2i cast which will cancel out the i2f we insert here. */
+ ins = lir->insLoadi(base, offset);
+ ins = lir->ins1(LIR_i2f, ins);
+ } else {
+ JS_ASSERT(t == JSVAL_BOXED || isNumber(*p) == (t == JSVAL_DOUBLE));
+ if (t == JSVAL_DOUBLE) {
+ ins = lir->insLoad(LIR_ldq, base, offset);
+ } else if (t == JSVAL_BOOLEAN) {
+ ins = lir->insLoad(LIR_ld, base, offset);
+ } else {
+ ins = lir->insLoad(LIR_ldp, base, offset);
+ }
+ }
+ tracker.set(p, ins);
+#ifdef DEBUG
+ char name[64];
+ JS_ASSERT(strlen(prefix) < 10);
+ void* mark = NULL;
+ jsuword* localNames = NULL;
+ const char* funName = NULL;
+ if (*prefix == 'a' || *prefix == 'v') {
+ mark = JS_ARENA_MARK(&cx->tempPool);
+ if (JS_GET_LOCAL_NAME_COUNT(fp->fun) != 0)
+ localNames = js_GetLocalNameArray(cx, fp->fun, &cx->tempPool);
+ funName = fp->fun->atom ? js_AtomToPrintableString(cx, fp->fun->atom) : "<anonymous>";
+ }
+ if (!strcmp(prefix, "argv")) {
+ if (index < fp->fun->nargs) {
+ JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[index]);
+ JS_snprintf(name, sizeof name, "$%s.%s", funName, js_AtomToPrintableString(cx, atom));
+ } else {
+ JS_snprintf(name, sizeof name, "$%s.<arg%d>", funName, index);
+ }
+ } else if (!strcmp(prefix, "vars")) {
+ JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(localNames[fp->fun->nargs + index]);
+ JS_snprintf(name, sizeof name, "$%s.%s", funName, js_AtomToPrintableString(cx, atom));
+ } else {
+ JS_snprintf(name, sizeof name, "$%s%d", prefix, index);
+ }
+
+ if (mark)
+ JS_ARENA_RELEASE(&cx->tempPool, mark);
+ addName(ins, name);
+
+ static const char* typestr[] = {
+ "object", "int", "double", "3", "string", "5", "boolean", "any"
+ };
+ debug_only_v(printf("import vp=%p name=%s type=%s flags=%d\n",
+ p, name, typestr[t & 7], t >> 3);)
+#endif
+}
+
+void
+TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned ngslots, unsigned callDepth,
+ uint8* globalTypeMap, uint8* stackTypeMap)
+{
+ /* If we get a partial list that doesn't have all the types (i.e. recording from a side
+ exit that was recorded but we added more global slots later), merge the missing types
+ from the entry type map. This is safe because at the loop edge we verify that we
+ have compatible types for all globals (entry type and loop edge type match). While
+ a different trace of the tree might have had a guard with a different type map for
+ these slots we just filled in here (the guard we continue from didn't know about them),
+ since we didn't take that particular guard the only way we could have ended up here
+ is if that other trace had at its end a compatible type distribution with the entry
+ map. Since thats exactly what we used to fill in the types our current side exit
+ didn't provide, this is always safe to do. */
+ unsigned length;
+ if (ngslots < (length = traceMonitor->globalTypeMap->length()))
+ mergeTypeMaps(&globalTypeMap, &ngslots,
+ traceMonitor->globalTypeMap->data(), length,
+ (uint8*)alloca(sizeof(uint8) * length));
+ JS_ASSERT(ngslots == traceMonitor->globalTypeMap->length());
+
+ /* the first time we compile a tree this will be empty as we add entries lazily */
+ uint16* gslots = traceMonitor->globalSlots->data();
+ uint8* m = globalTypeMap;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ import(gp_ins, nativeGlobalOffset(vp), vp, *m, vpname, vpnum, NULL);
+ m++;
+ );
+ ptrdiff_t offset = -treeInfo->nativeStackBase;
+ m = stackTypeMap;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
+ import(sp, offset, vp, *m, vpname, vpnum, fp);
+ m++; offset += sizeof(double);
+ );
+}
+
+/* Lazily import a global slot if we don't already have it in the tracker. */
+bool
+TraceRecorder::lazilyImportGlobalSlot(unsigned slot)
+{
+ if (slot != uint16(slot)) /* we use a table of 16-bit ints, bail out if that's not enough */
+ return false;
+ jsval* vp = &STOBJ_GET_SLOT(globalObj, slot);
+ if (tracker.has(vp))
+ return true; /* we already have it */
+ unsigned index = traceMonitor->globalSlots->length();
+ /* If this the first global we are adding, remember the shape of the global object. */
+ if (index == 0)
+ traceMonitor->globalShape = OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain));
+ /* Add the slot to the list of interned global slots. */
+ traceMonitor->globalSlots->add(slot);
+ uint8 type = getCoercedType(*vp);
+ if ((type == JSVAL_INT) && oracle.isGlobalSlotUndemotable(cx->fp->script, slot))
+ type = JSVAL_DOUBLE;
+ traceMonitor->globalTypeMap->add(type);
+ import(gp_ins, slot*sizeof(double), vp, type, "global", index, NULL);
+ return true;
+}
+
+/* Write back a value onto the stack or global frames. */
+LIns*
+TraceRecorder::writeBack(LIns* i, LIns* base, ptrdiff_t offset)
+{
+ /* Sink all type casts targeting the stack into the side exit by simply storing the original
+ (uncasted) value. Each guard generates the side exit map based on the types of the
+ last stores to every stack location, so its safe to not perform them on-trace. */
+ if (isPromoteInt(i))
+ i = ::demote(lir, i);
+ return lir->insStorei(i, base, offset);
+}
+
+/* Update the tracker, then issue a write back store. */
+void
+TraceRecorder::set(jsval* p, LIns* i, bool initializing)
+{
+ JS_ASSERT(initializing || tracker.has(p));
+ tracker.set(p, i);
+ /* If we are writing to this location for the first time, calculate the offset into the
+ native frame manually, otherwise just look up the last load or store associated with
+ the same source address (p) and use the same offset/base. */
+ LIns* x = nativeFrameTracker.get(p);
+ if (!x) {
+ if (isGlobal(p))
+ x = writeBack(i, gp_ins, nativeGlobalOffset(p));
+ else
+ x = writeBack(i, lirbuf->sp, -treeInfo->nativeStackBase + nativeStackOffset(p));
+ nativeFrameTracker.set(p, x);
+ } else {
+#define ASSERT_VALID_CACHE_HIT(base, offset) \
+ JS_ASSERT(base == lirbuf->sp || base == gp_ins); \
+ JS_ASSERT(offset == ((base == lirbuf->sp) \
+ ? -treeInfo->nativeStackBase + nativeStackOffset(p) \
+ : nativeGlobalOffset(p))); \
+
+ if (x->isop(LIR_st) || x->isop(LIR_stq)) {
+ ASSERT_VALID_CACHE_HIT(x->oprnd2(), x->oprnd3()->constval());
+ writeBack(i, x->oprnd2(), x->oprnd3()->constval());
+ } else {
+ JS_ASSERT(x->isop(LIR_sti) || x->isop(LIR_stqi));
+ ASSERT_VALID_CACHE_HIT(x->oprnd2(), x->immdisp());
+ writeBack(i, x->oprnd2(), x->immdisp());
+ }
+ }
+#undef ASSERT_VALID_CACHE_HIT
+}
+
+LIns*
+TraceRecorder::get(jsval* p) const
+{
+ return tracker.get(p);
+}
+
+/* Determine whether the current branch instruction terminates the loop. */
+static bool
+js_IsLoopExit(jsbytecode* pc, jsbytecode* header)
+{
+ switch (*pc) {
+ case JSOP_LT:
+ case JSOP_GT:
+ case JSOP_LE:
+ case JSOP_GE:
+ case JSOP_NE:
+ case JSOP_EQ:
+ /* These ops try to dispatch a JSOP_IFEQ or JSOP_IFNE that follows. */
+ JS_ASSERT(js_CodeSpec[*pc].length == 1);
+ pc++;
+ break;
+
+ default:
+ for (;;) {
+ if (*pc == JSOP_AND || *pc == JSOP_OR)
+ pc += GET_JUMP_OFFSET(pc);
+ else if (*pc == JSOP_ANDX || *pc == JSOP_ORX)
+ pc += GET_JUMPX_OFFSET(pc);
+ else
+ break;
+ }
+ }
+
+ switch (*pc) {
+ case JSOP_IFEQ:
+ case JSOP_IFNE:
+ /*
+ * Forward jumps are usually intra-branch, but for-in loops jump to the
+ * trailing enditer to clean up, so check for that case here.
+ */
+ if (pc[GET_JUMP_OFFSET(pc)] == JSOP_ENDITER)
+ return true;
+ return pc + GET_JUMP_OFFSET(pc) == header;
+
+ case JSOP_IFEQX:
+ case JSOP_IFNEX:
+ if (pc[GET_JUMPX_OFFSET(pc)] == JSOP_ENDITER)
+ return true;
+ return pc + GET_JUMPX_OFFSET(pc) == header;
+
+ default:;
+ }
+ return false;
+}
+
+/* Determine whether the current branch is a loop edge (taken or not taken). */
+static bool
+js_IsLoopEdge(jsbytecode* pc, jsbytecode* header)
+{
+ switch (*pc) {
+ case JSOP_IFEQ:
+ case JSOP_IFNE:
+ return ((pc + GET_JUMP_OFFSET(pc)) == header);
+ case JSOP_IFEQX:
+ case JSOP_IFNEX:
+ return ((pc + GET_JUMPX_OFFSET(pc)) == header);
+ default:
+ JS_ASSERT((*pc == JSOP_AND) || (*pc == JSOP_ANDX) ||
+ (*pc == JSOP_OR) || (*pc == JSOP_ORX));
+ }
+ return false;
+}
+
+/* Promote slots if necessary to match the called tree' type map and report error if thats
+ impossible. */
+bool
+TraceRecorder::adjustCallerTypes(Fragment* f, unsigned* demote_slots, bool& trash)
+{
+ JSTraceMonitor* tm = traceMonitor;
+ uint8* m = tm->globalTypeMap->data();
+ uint16* gslots = traceMonitor->globalSlots->data();
+ unsigned ngslots = traceMonitor->globalSlots->length();
+ uint8* map = ((TreeInfo*)f->vmprivate)->stackTypeMap.data();
+ bool ok = true;
+ trash = false;
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ LIns* i = get(vp);
+ bool isPromote = isPromoteInt(i);
+ if (isPromote && *m == JSVAL_DOUBLE)
+ lir->insStorei(get(vp), gp_ins, nativeGlobalOffset(vp));
+ else if (!isPromote && *m == JSVAL_INT) {
+ oracle.markGlobalSlotUndemotable(cx->fp->script, nativeGlobalOffset(vp)/sizeof(double));
+ trash = true;
+ ok = false;
+ }
+ ++m;
+ );
+ m = map;
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ LIns* i = get(vp);
+ bool isPromote = isPromoteInt(i);
+ if (isPromote && *m == JSVAL_DOUBLE) {
+ lir->insStorei(get(vp), lirbuf->sp,
+ -treeInfo->nativeStackBase + nativeStackOffset(vp));
+ /* Aggressively undo speculation so the inner tree will compile if this fails. */
+ ADD_UNDEMOTE_SLOT(demote_slots, unsigned(m - map));
+ } else if (!isPromote && *m == JSVAL_INT) {
+ debug_only_v(printf("adjusting will fail, %s%d, slot %d\n", vpname, vpnum, m - map);)
+ ok = false;
+ ADD_UNDEMOTE_SLOT(demote_slots, unsigned(m - map));
+ } else if (JSVAL_IS_INT(*vp) && *m == JSVAL_DOUBLE) {
+ /* Aggressively undo speculation so the inner tree will compile if this fails. */
+ ADD_UNDEMOTE_SLOT(demote_slots, unsigned(m - map));
+ }
+ ++m;
+ );
+ /* If this isn't okay, tell the oracle. */
+ if (!ok) {
+ for (unsigned i = 1; i <= NUM_UNDEMOTE_SLOTS(demote_slots); i++)
+ oracle.markStackSlotUndemotable(cx->fp->script, cx->fp->regs->pc, demote_slots[i]);
+ }
+ JS_ASSERT(f == f->root);
+ return ok;
+}
+
+uint8
+TraceRecorder::determineSlotType(jsval* vp) const
+{
+ uint8 m;
+ LIns* i = get(vp);
+ m = isNumber(*vp)
+ ? (isPromoteInt(i) ? JSVAL_INT : JSVAL_DOUBLE)
+ : JSVAL_TAG(*vp);
+ JS_ASSERT((m != JSVAL_INT) || isInt32(*vp));
+ return m;
+}
+
+#define IMACRO_PC_ADJ_BITS 8
+#define SCRIPT_PC_ADJ_BITS (32 - IMACRO_PC_ADJ_BITS)
+
+// The stored imacro_pc_adj byte offset is biased by 1.
+#define IMACRO_PC_ADJ_LIMIT (JS_BIT(IMACRO_PC_ADJ_BITS) - 1)
+#define SCRIPT_PC_ADJ_LIMIT JS_BIT(SCRIPT_PC_ADJ_BITS)
+
+#define IMACRO_PC_ADJ(ip) ((uintptr_t)(ip) >> SCRIPT_PC_ADJ_BITS)
+#define SCRIPT_PC_ADJ(ip) ((ip) & JS_BITMASK(SCRIPT_PC_ADJ_BITS))
+
+#define FI_SCRIPT_PC(fi,fp) ((fp)->script->code + SCRIPT_PC_ADJ((fi).ip_adj))
+
+#define FI_IMACRO_PC(fi,fp) (IMACRO_PC_ADJ((fi).ip_adj) \
+ ? imacro_code[*FI_SCRIPT_PC(fi, fp)] + \
+ IMACRO_PC_ADJ((fi).ip_adj) \
+ : NULL)
+
+#define IMACRO_PC_OK(fp,pc) JS_ASSERT(uintN((pc)-imacro_code[*(fp)->imacpc]) \
+ < JS_BIT(IMACRO_PC_ADJ_BITS))
+#define ENCODE_IP_ADJ(fp,pc) ((fp)->imacpc \
+ ? (IMACRO_PC_OK(fp, pc), \
+ (((pc) - imacro_code[*(fp)->imacpc]) \
+ << SCRIPT_PC_ADJ_BITS) + \
+ (fp)->imacpc - (fp)->script->code) \
+ : (pc) - (fp)->script->code)
+
+#define DECODE_IP_ADJ(ip,fp) (IMACRO_PC_ADJ(ip) \
+ ? (fp)->imacpc = (fp)->script->code + \
+ SCRIPT_PC_ADJ(ip), \
+ (fp)->regs->pc = imacro_code[*(fp)->imacpc] + \
+ IMACRO_PC_ADJ(ip) \
+ : (fp)->regs->pc = (fp)->script->code + (ip))
+
+static jsbytecode* imacro_code[JSOP_LIMIT];
+
+LIns*
+TraceRecorder::snapshot(ExitType exitType)
+{
+ JSStackFrame* fp = cx->fp;
+ JSFrameRegs* regs = fp->regs;
+ jsbytecode* pc = regs->pc;
+ if (exitType == BRANCH_EXIT && js_IsLoopExit(pc, (jsbytecode*)fragment->root->ip))
+ exitType = LOOP_EXIT;
+
+ /* Check for a return-value opcode that needs to restart at the next instruction. */
+ const JSCodeSpec& cs = js_CodeSpec[*pc];
+
+ /* WARNING: don't return before restoring the original pc if (resumeAfter). */
+ bool resumeAfter = (pendingTraceableNative &&
+ JSTN_ERRTYPE(pendingTraceableNative) == FAIL_JSVAL);
+ if (resumeAfter) {
+ JS_ASSERT(*pc == JSOP_CALL || *pc == JSOP_APPLY || *pc == JSOP_NEXTITER);
+ pc += cs.length;
+ regs->pc = pc;
+ MUST_FLOW_THROUGH("restore_pc");
+ }
+
+ /* Generate the entry map for the (possibly advanced) pc and stash it in the trace. */
+ unsigned stackSlots = js_NativeStackSlots(cx, callDepth);
+
+ /* It's sufficient to track the native stack use here since all stores above the
+ stack watermark defined by guards are killed. */
+ trackNativeStackUse(stackSlots + 1);
+
+ /* Capture the type map into a temporary location. */
+ unsigned ngslots = traceMonitor->globalSlots->length();
+ unsigned typemap_size = (stackSlots + ngslots) * sizeof(uint8);
+ uint8* typemap = (uint8*)alloca(typemap_size);
+ uint8* m = typemap;
+
+ /* Determine the type of a store by looking at the current type of the actual value the
+ interpreter is using. For numbers we have to check what kind of store we used last
+ (integer or double) to figure out what the side exit show reflect in its typemap. */
+ FORALL_SLOTS(cx, ngslots, traceMonitor->globalSlots->data(), callDepth,
+ *m++ = determineSlotType(vp);
+ );
+ JS_ASSERT(unsigned(m - typemap) == ngslots + stackSlots);
+
+ /* If we are capturing the stack state on a specific instruction, the value on or near
+ the top of the stack is a boxed value. Either pc[-cs.length] is JSOP_NEXTITER and we
+ want one below top of stack, or else it's JSOP_CALL and we want top of stack. */
+ if (resumeAfter) {
+ m[(pc[-cs.length] == JSOP_NEXTITER) ? -2 : -1] = JSVAL_BOXED;
+
+ /* Now restore the the original pc (after which early returns are ok). */
+ MUST_FLOW_LABEL(restore_pc);
+ regs->pc = pc - cs.length;
+ } else {
+ /* If we take a snapshot on a goto, advance to the target address. This avoids inner
+ trees returning on a break goto, which the outer recorder then would confuse with
+ a break in the outer tree. */
+ if (*pc == JSOP_GOTO)
+ pc += GET_JUMP_OFFSET(pc);
+ else if (*pc == JSOP_GOTOX)
+ pc += GET_JUMPX_OFFSET(pc);
+ }
+ intptr_t ip_adj = ENCODE_IP_ADJ(fp, pc);
+
+ /* Check if we already have a matching side exit. If so use that side exit structure,
+ otherwise we have to create our own. */
+ VMSideExit** exits = treeInfo->sideExits.data();
+ unsigned nexits = treeInfo->sideExits.length();
+ if (exitType == LOOP_EXIT) {
+ for (unsigned n = 0; n < nexits; ++n) {
+ VMSideExit* e = exits[n];
+ if (e->ip_adj == ip_adj &&
+ !memcmp(getTypeMap(exits[n]), typemap, typemap_size)) {
+ LIns* data = lir_buf_writer->skip(sizeof(GuardRecord));
+ GuardRecord* rec = (GuardRecord*)data->payload();
+ /* setup guard record structure with shared side exit */
+ memset(rec, 0, sizeof(GuardRecord));
+ VMSideExit* exit = exits[n];
+ rec->exit = exit;
+ exit->addGuard(rec);
+ AUDIT(mergedLoopExits);
+ return data;
+ }
+ }
+ }
+
+ /* We couldn't find a matching side exit, so create our own side exit structure. */
+ LIns* data = lir_buf_writer->skip(sizeof(GuardRecord) +
+ sizeof(VMSideExit) +
+ (stackSlots + ngslots) * sizeof(uint8));
+ GuardRecord* rec = (GuardRecord*)data->payload();
+ VMSideExit* exit = (VMSideExit*)(rec + 1);
+ /* setup guard record structure */
+ memset(rec, 0, sizeof(GuardRecord));
+ rec->exit = exit;
+ /* setup side exit structure */
+ memset(exit, 0, sizeof(VMSideExit));
+ exit->from = fragment;
+ exit->calldepth = callDepth;
+ exit->numGlobalSlots = ngslots;
+ exit->numStackSlots = stackSlots;
+ exit->numStackSlotsBelowCurrentFrame = cx->fp->callee
+ ? nativeStackOffset(&cx->fp->argv[-2])/sizeof(double)
+ : 0;
+ exit->exitType = exitType;
+ exit->addGuard(rec);
+ exit->ip_adj = ip_adj;
+ exit->sp_adj = (stackSlots * sizeof(double)) - treeInfo->nativeStackBase;
+ exit->rp_adj = exit->calldepth * sizeof(FrameInfo);
+ memcpy(getTypeMap(exit), typemap, typemap_size);
+
+ /* BIG FAT WARNING: If compilation fails, we currently don't reset the lirbuf so its safe
+ to keep references to the side exits here. If we ever start rewinding those lirbufs,
+ we have to make sure we purge the side exits that then no longer will be in valid
+ memory. */
+ if (exitType == LOOP_EXIT)
+ treeInfo->sideExits.add(exit);
+ return data;
+}
+
+/* Emit a guard for condition (cond), expecting to evaluate to boolean result (expected)
+ and using the supplied side exit if the conditon doesn't hold. */
+LIns*
+TraceRecorder::guard(bool expected, LIns* cond, LIns* exit)
+{
+ return lir->insGuard(expected ? LIR_xf : LIR_xt, cond, exit);
+}
+
+/* Emit a guard for condition (cond), expecting to evaluate to boolean result (expected)
+ and generate a side exit with type exitType to jump to if the condition does not hold. */
+LIns*
+TraceRecorder::guard(bool expected, LIns* cond, ExitType exitType)
+{
+ return guard(expected, cond, snapshot(exitType));
+}
+
+/* Try to match the type of a slot to type t. checkType is used to verify that the type of
+ * values flowing into the loop edge is compatible with the type we expect in the loop header.
+ *
+ * @param v Value.
+ * @param t Typemap entry for value.
+ * @param stage_val Outparam for set() address.
+ * @param stage_ins Outparam for set() instruction.
+ * @param stage_count Outparam for set() buffer count.
+ * @return True if types are compatible, false otherwise.
+ */
+bool
+TraceRecorder::checkType(jsval& v, uint8 t, jsval*& stage_val, LIns*& stage_ins,
+ unsigned& stage_count)
+{
+ if (t == JSVAL_INT) { /* initially all whole numbers cause the slot to be demoted */
+ debug_only_v(printf("checkType(tag=1, t=%d, isnum=%d, i2f=%d) stage_count=%d\n",
+ t,
+ isNumber(v),
+ isPromoteInt(get(&v)),
+ stage_count);)
+ if (!isNumber(v))
+ return false; /* not a number? type mismatch */
+ LIns* i = get(&v);
+ /* This is always a type mismatch, we can't close a double to an int. */
+ if (!isPromoteInt(i))
+ return false;
+ /* Looks good, slot is an int32, the last instruction should be promotable. */
+ JS_ASSERT(isInt32(v) && isPromoteInt(i));
+ /* Overwrite the value in this slot with the argument promoted back to an integer. */
+ stage_val = &v;
+ stage_ins = f2i(i);
+ stage_count++;
+ return true;
+ }
+ if (t == JSVAL_DOUBLE) {
+ debug_only_v(printf("checkType(tag=2, t=%d, isnum=%d, promote=%d) stage_count=%d\n",
+ t,
+ isNumber(v),
+ isPromoteInt(get(&v)),
+ stage_count);)
+ if (!isNumber(v))
+ return false; /* not a number? type mismatch */
+ LIns* i = get(&v);
+ /* We sink i2f conversions into the side exit, but at the loop edge we have to make
+ sure we promote back to double if at loop entry we want a double. */
+ if (isPromoteInt(i)) {
+ stage_val = &v;
+ stage_ins = lir->ins1(LIR_i2f, i);
+ stage_count++;
+ }
+ return true;
+ }
+ /* for non-number types we expect a precise match of the type */
+#ifdef DEBUG
+ if (JSVAL_TAG(v) != t) {
+ debug_only_v(printf("Type mismatch: val %c, map %c ", typeChar[JSVAL_TAG(v)],
+ typeChar[t]);)
+ }
+#endif
+ debug_only_v(printf("checkType(tag=%d, t=%d) stage_count=%d\n",
+ (int) JSVAL_TAG(v), t, stage_count);)
+ return JSVAL_TAG(v) == t;
+}
+
+/**
+ * Make sure that the current values in the given stack frame and all stack frames
+ * up and including entryFrame are type-compatible with the entry map.
+ *
+ * @param root_peer First fragment in peer list.
+ * @param stable_peer Outparam for first type stable peer.
+ * @param trash Whether to trash the tree (demotion).
+ * @param demotes Array to store demotable stack slots.
+ * @return True if type stable, false otherwise.
+ */
+bool
+TraceRecorder::deduceTypeStability(Fragment* root_peer, Fragment** stable_peer, unsigned* demotes)
+{
+ uint8* m;
+ uint8* typemap;
+ unsigned ngslots = traceMonitor->globalSlots->length();
+ uint16* gslots = traceMonitor->globalSlots->data();
+ JS_ASSERT(traceMonitor->globalTypeMap->length() == ngslots);
+
+ if (stable_peer)
+ *stable_peer = NULL;
+
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+
+ /*
+ * Rather than calculate all of this stuff twice, it gets cached locally. The "stage" buffers
+ * are for calls to set() that will change the exit types.
+ */
+ bool success;
+ bool unstable_from_undemotes;
+ unsigned stage_count;
+ jsval** stage_vals = (jsval**)alloca(sizeof(jsval*) * (ngslots + treeInfo->stackTypeMap.length()));
+ LIns** stage_ins = (LIns**)alloca(sizeof(LIns*) * (ngslots + treeInfo->stackTypeMap.length()));
+
+ /* First run through and see if we can close ourselves - best case! */
+ stage_count = 0;
+ success = false;
+ unstable_from_undemotes = false;
+
+ debug_only_v(printf("Checking type stability against self=%p\n", fragment);)
+
+ m = typemap = traceMonitor->globalTypeMap->data();
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ debug_only_v(printf("%s%d ", vpname, vpnum);)
+ if (!checkType(*vp, *m, stage_vals[stage_count], stage_ins[stage_count], stage_count)) {
+ /* If the failure was an int->double, tell the oracle. */
+ if (*m == JSVAL_INT && isNumber(*vp) && !isPromoteInt(get(vp)))
+ oracle.markGlobalSlotUndemotable(cx->fp->script, gslots[n]);
+ trashTree = true;
+ goto checktype_fail_1;
+ }
+ ++m;
+ );
+ m = typemap = treeInfo->stackTypeMap.data();
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ debug_only_v(printf("%s%d ", vpname, vpnum);)
+ if (!checkType(*vp, *m, stage_vals[stage_count], stage_ins[stage_count], stage_count)) {
+ if (*m == JSVAL_INT && isNumber(*vp) && !isPromoteInt(get(vp)))
+ ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
+ else
+ goto checktype_fail_1;
+ }
+ ++m;
+ );
+
+ /*
+ * If there's an exit that's unstable because of undemotable slots, we want to search for
+ * peers just in case we can make a connection.
+ */
+ if (NUM_UNDEMOTE_SLOTS(demotes))
+ unstable_from_undemotes = true;
+ else
+ success = true;
+
+checktype_fail_1:
+ /* If we got a success and we don't need to recompile, we should just close here. */
+ if (success) {
+ for (unsigned i = 0; i < stage_count; i++)
+ set(stage_vals[i], stage_ins[i]);
+ return true;
+ /* If we need to trash, don't bother checking peers. */
+ } else if (trashTree) {
+ return false;
+ } else {
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+ }
+
+ /* At this point the tree is about to be incomplete, so let's see if we can connect to any
+ * peer fragment that is type stable.
+ */
+ Fragment* f;
+ TreeInfo* ti;
+ for (f = root_peer; f != NULL; f = f->peer) {
+ debug_only_v(printf("Checking type stability against peer=%p (code=%p)\n", f, f->code());)
+ if (!f->code())
+ continue;
+ ti = (TreeInfo*)f->vmprivate;
+ /* Don't allow varying stack depths */
+ if (ti->stackTypeMap.length() != treeInfo->stackTypeMap.length())
+ continue;
+ stage_count = 0;
+ success = false;
+ m = ti->stackTypeMap.data();
+
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ if (!checkType(*vp, *m, stage_vals[stage_count], stage_ins[stage_count], stage_count))
+ goto checktype_fail_2;
+ ++m;
+ );
+
+ success = true;
+
+checktype_fail_2:
+ if (success) {
+ /*
+ * There was a successful match. We don't care about restoring the saved staging, but
+ * we do need to clear the original undemote list.
+ */
+ for (unsigned i = 0; i < stage_count; i++)
+ set(stage_vals[i], stage_ins[i]);
+ if (stable_peer)
+ *stable_peer = f;
+ return false;
+ }
+ }
+
+ JS_ASSERT(NUM_UNDEMOTE_SLOTS(demotes) == 0);
+
+ /*
+ * If this is a loop trace and it would be stable with demotions, build an undemote list
+ * and return true. Our caller should sniff this and trash the tree, recording a new one
+ * that will assumedly stabilize.
+ */
+ if (unstable_from_undemotes && fragment->kind == LoopTrace) {
+ typemap = m = treeInfo->stackTypeMap.data();
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ if (*m == JSVAL_INT) {
+ JS_ASSERT(isNumber(*vp));
+ if (!isPromoteInt(get(vp)))
+ ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
+ } else if (*m == JSVAL_DOUBLE) {
+ JS_ASSERT(isNumber(*vp));
+ ADD_UNDEMOTE_SLOT(demotes, unsigned(m - typemap));
+ } else {
+ JS_ASSERT(*m == JSVAL_TAG(*vp));
+ }
+ m++;
+ );
+ return true;
+ }
+
+ return false;
+}
+
+/* Check whether the current pc location is the loop header of the loop this recorder records. */
+bool
+TraceRecorder::isLoopHeader(JSContext* cx) const
+{
+ return cx->fp->regs->pc == fragment->root->ip;
+}
+
+/* Compile the current fragment. */
+void
+TraceRecorder::compile(Fragmento* fragmento)
+{
+ if (treeInfo->maxNativeStackSlots >= MAX_NATIVE_STACK_SLOTS) {
+ debug_only_v(printf("Trace rejected: excessive stack use.\n"));
+ js_BlacklistPC(fragmento, fragment);
+ return;
+ }
+ ++treeInfo->branchCount;
+ if (lirbuf->outOmem()) {
+ fragmento->assm()->setError(nanojit::OutOMem);
+ return;
+ }
+ ::compile(fragmento->assm(), fragment);
+ if (anchor)
+ fragmento->assm()->patch(anchor);
+ if (fragmento->assm()->error() != nanojit::None)
+ return;
+ JS_ASSERT(fragment->code());
+ JS_ASSERT(!fragment->vmprivate);
+ if (fragment == fragment->root)
+ fragment->vmprivate = treeInfo;
+ /* :TODO: windows support */
+#if defined DEBUG && !defined WIN32
+ const char* filename = cx->fp->script->filename;
+ char* label = (char*)malloc((filename ? strlen(filename) : 7) + 16);
+ sprintf(label, "%s:%u", filename ? filename : "<stdin>",
+ js_FramePCToLineNumber(cx, cx->fp));
+ fragmento->labels->add(fragment, sizeof(Fragment), 0, label);
+ free(label);
+#endif
+ AUDIT(traceCompleted);
+}
+
+static bool
+js_JoinPeersIfCompatible(Fragmento* frago, Fragment* stableFrag, TreeInfo* stableTree,
+ VMSideExit* exit)
+{
+ JS_ASSERT(exit->numStackSlots == stableTree->stackTypeMap.length());
+ /* Must have a matching type unstable exit. */
+ if (memcmp(getTypeMap(exit) + exit->numGlobalSlots,
+ stableTree->stackTypeMap.data(),
+ stableTree->stackTypeMap.length()) != 0) {
+ return false;
+ }
+
+ exit->target = stableFrag;
+ frago->assm()->patch(exit);
+
+ stableTree->dependentTrees.addUnique(exit->from->root);
+
+ return true;
+}
+
+/* Complete and compile a trace and link it to the existing tree if appropriate. */
+bool
+TraceRecorder::closeLoop(Fragmento* fragmento, bool& demote, unsigned *demotes)
+{
+ bool stable;
+ LIns* exitIns;
+ Fragment* peer;
+ VMSideExit* exit;
+ Fragment* peer_root;
+
+ demote = false;
+
+ exitIns = snapshot(UNSTABLE_LOOP_EXIT);
+ exit = (VMSideExit*)((GuardRecord*)exitIns->payload())->exit;
+
+ if (callDepth != 0) {
+ debug_only_v(printf("Stack depth mismatch, possible recursion\n");)
+ js_BlacklistPC(fragmento, fragment);
+ trashTree = true;
+ return false;
+ }
+
+ JS_ASSERT(exit->numStackSlots == treeInfo->stackTypeMap.length());
+
+ peer_root = fragmento->getLoop(fragment->root->ip);
+ JS_ASSERT(peer_root != NULL);
+ stable = deduceTypeStability(peer_root, &peer, demotes);
+
+ #if DEBUG
+ if (!stable || NUM_UNDEMOTE_SLOTS(demotes))
+ AUDIT(unstableLoopVariable);
+ #endif
+
+ if (trashTree) {
+ debug_only_v(printf("Trashing tree from type instability.\n");)
+ return false;
+ }
+
+ if (stable && NUM_UNDEMOTE_SLOTS(demotes)) {
+ JS_ASSERT(fragment->kind == LoopTrace);
+ demote = true;
+ return false;
+ }
+
+ if (!stable) {
+ fragment->lastIns = lir->insGuard(LIR_x, lir->insImm(1), exitIns);
+
+ /*
+ * If we didn't find a type stable peer, we compile the loop anyway and
+ * hope it becomes stable later.
+ */
+ if (!peer) {
+ /*
+ * If such a fragment does not exist, let's compile the loop ahead
+ * of time anyway. Later, if the loop becomes type stable, we will
+ * connect these two fragments together.
+ */
+ debug_only_v(printf("Trace has unstable loop variable with no stable peer, "
+ "compiling anyway.\n");)
+ UnstableExit* uexit = new UnstableExit;
+ uexit->fragment = fragment;
+ uexit->exit = exit;
+ uexit->next = treeInfo->unstableExits;
+ treeInfo->unstableExits = uexit;
+
+ /*
+ * If we walked out of a loop, this exit is wrong. We need to back
+ * up to the if operation.
+ */
+ if (walkedOutOfLoop())
+ exit->ip_adj = terminate_ip_adj;
+
+ /* If we were trying to stabilize a promotable tree, trash it. */
+ if (promotedPeer)
+ js_TrashTree(cx, promotedPeer);
+ } else {
+ JS_ASSERT(peer->code());
+ exit->target = peer;
+ debug_only_v(printf("Joining type-unstable trace to target fragment %p.\n", peer);)
+ stable = true;
+ ((TreeInfo*)peer->vmprivate)->dependentTrees.addUnique(fragment->root);
+ }
+
+ compile(fragmento);
+ } else {
+ exit->target = fragment->root;
+#if defined(JS_HAS_OPERATION_COUNT) && !JS_HAS_OPERATION_COUNT
+ exit->exitType = TIMEOUT_EXIT;
+ guard(false,
+ lir->ins_eq0(lir->insLoadi(cx_ins,
+ offsetof(JSContext, operationCount))),
+ exitIns);
+#endif
+ fragment->lastIns = lir->insGuard(LIR_loop, lir->insImm(1), exitIns);
+ compile(fragmento);
+ }
+
+ if (fragmento->assm()->error() != nanojit::None)
+ return false;
+
+ joinEdgesToEntry(fragmento, peer_root);
+
+ debug_only_v(printf("recording completed at %s:%u@%u via closeLoop\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+ return true;
+}
+
+void
+TraceRecorder::joinEdgesToEntry(Fragmento* fragmento, Fragment* peer_root)
+{
+ if (fragment->kind == LoopTrace) {
+ TreeInfo* ti;
+ Fragment* peer;
+ uint8* t1, *t2;
+ UnstableExit* uexit, **unext;
+
+ unsigned* demotes = (unsigned*)alloca(treeInfo->stackTypeMap.length() * sizeof(unsigned));
+ for (peer = peer_root; peer != NULL; peer = peer->peer) {
+ if (!peer->code())
+ continue;
+ ti = (TreeInfo*)peer->vmprivate;
+ uexit = ti->unstableExits;
+ unext = &ti->unstableExits;
+ while (uexit != NULL) {
+ bool remove = js_JoinPeersIfCompatible(fragmento, fragment, treeInfo, uexit->exit);
+ JS_ASSERT(!remove || fragment != peer);
+ debug_only_v(if (remove) {
+ printf("Joining type-stable trace to target exit %p->%p.\n",
+ uexit->fragment, uexit->exit); });
+ if (!remove) {
+ /* See if this exit contains mismatch demotions, which imply trashing a tree.
+ This is actually faster than trashing the original tree as soon as the
+ instability is detected, since we could have compiled a fairly stable
+ tree that ran faster with integers. */
+ unsigned count = 0;
+ t1 = treeInfo->stackTypeMap.data();
+ t2 = getTypeMap(uexit->exit) + uexit->exit->numGlobalSlots;
+ for (unsigned i = 0; i < uexit->exit->numStackSlots; i++) {
+ if (t2[i] == JSVAL_INT && t1[i] == JSVAL_DOUBLE) {
+ demotes[count++] = i;
+ } else if (t2[i] != t1[i]) {
+ count = 0;
+ break;
+ }
+ }
+ if (count) {
+ for (unsigned i = 0; i < count; i++)
+ oracle.markStackSlotUndemotable(cx->fp->script,
+ cx->fp->regs->pc, demotes[i]);
+ js_TrashTree(cx, uexit->fragment->root);
+ break;
+ }
+ }
+ if (remove) {
+ *unext = uexit->next;
+ delete uexit;
+ uexit = *unext;
+ } else {
+ unext = &uexit->next;
+ uexit = uexit->next;
+ }
+ }
+ }
+ }
+
+ debug_only_v(js_DumpPeerStability(fragmento, peer_root->ip);)
+}
+
+/* Emit an always-exit guard and compile the tree (used for break statements. */
+void
+TraceRecorder::endLoop(Fragmento* fragmento)
+{
+ LIns* exitIns = snapshot(LOOP_EXIT);
+
+ if (callDepth != 0) {
+ debug_only_v(printf("Stack depth mismatch, possible recursion\n");)
+ js_BlacklistPC(fragmento, fragment);
+ trashTree = true;
+ return;
+ }
+
+ fragment->lastIns = lir->insGuard(LIR_x, lir->insImm(1), exitIns);
+ compile(fragmento);
+
+ if (fragmento->assm()->error() != nanojit::None)
+ return;
+
+ joinEdgesToEntry(fragmento, fragmento->getLoop(fragment->root->ip));
+
+ debug_only_v(printf("recording completed at %s:%u@%u via endLoop\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+}
+
+/* Emit code to adjust the stack to match the inner tree's stack expectations. */
+void
+TraceRecorder::prepareTreeCall(Fragment* inner)
+{
+ TreeInfo* ti = (TreeInfo*)inner->vmprivate;
+ inner_sp_ins = lirbuf->sp;
+ /* The inner tree expects to be called from the current frame. If the outer tree (this
+ trace) is currently inside a function inlining code (calldepth > 0), we have to advance
+ the native stack pointer such that we match what the inner trace expects to see. We
+ move it back when we come out of the inner tree call. */
+ if (callDepth > 0) {
+ /* Calculate the amount we have to lift the native stack pointer by to compensate for
+ any outer frames that the inner tree doesn't expect but the outer tree has. */
+ ptrdiff_t sp_adj = nativeStackOffset(&cx->fp->argv[-2]);
+ /* Calculate the amount we have to lift the call stack by */
+ ptrdiff_t rp_adj = callDepth * sizeof(FrameInfo);
+ /* Guard that we have enough stack space for the tree we are trying to call on top
+ of the new value for sp. */
+ debug_only_v(printf("sp_adj=%d outer=%d inner=%d\n",
+ sp_adj, treeInfo->nativeStackBase, ti->nativeStackBase));
+ LIns* sp_top = lir->ins2i(LIR_piadd, lirbuf->sp,
+ - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */
+ + sp_adj /* adjust for stack in outer frame inner tree can't see */
+ + ti->maxNativeStackSlots * sizeof(double)); /* plus the inner tree's stack */
+ guard(true, lir->ins2(LIR_lt, sp_top, eos_ins), OOM_EXIT);
+ /* Guard that we have enough call stack space. */
+ LIns* rp_top = lir->ins2i(LIR_piadd, lirbuf->rp, rp_adj +
+ ti->maxCallDepth * sizeof(FrameInfo));
+ guard(true, lir->ins2(LIR_lt, rp_top, eor_ins), OOM_EXIT);
+ /* We have enough space, so adjust sp and rp to their new level. */
+ lir->insStorei(inner_sp_ins = lir->ins2i(LIR_piadd, lirbuf->sp,
+ - treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */
+ + sp_adj /* adjust for stack in outer frame inner tree can't see */
+ + ti->nativeStackBase), /* plus the inner tree's stack base */
+ lirbuf->state, offsetof(InterpState, sp));
+ lir->insStorei(lir->ins2i(LIR_piadd, lirbuf->rp, rp_adj),
+ lirbuf->state, offsetof(InterpState, rp));
+ }
+}
+
+/* Record a call to an inner tree. */
+void
+TraceRecorder::emitTreeCall(Fragment* inner, VMSideExit* exit)
+{
+ TreeInfo* ti = (TreeInfo*)inner->vmprivate;
+ /* Invoke the inner tree. */
+ LIns* args[] = { INS_CONSTPTR(inner), lirbuf->state }; /* reverse order */
+ LIns* ret = lir->insCall(&js_CallTree_ci, args);
+ /* Read back all registers, in case the called tree changed any of them. */
+ import(ti, inner_sp_ins, exit->numGlobalSlots, exit->calldepth,
+ getTypeMap(exit), getTypeMap(exit) + exit->numGlobalSlots);
+ /* Restore sp and rp to their original values (we still have them in a register). */
+ if (callDepth > 0) {
+ lir->insStorei(lirbuf->sp, lirbuf->state, offsetof(InterpState, sp));
+ lir->insStorei(lirbuf->rp, lirbuf->state, offsetof(InterpState, rp));
+ }
+ /* Guard that we come out of the inner tree along the same side exit we came out when
+ we called the inner tree at recording time. */
+ guard(true, lir->ins2(LIR_eq, ret, INS_CONSTPTR(exit)), NESTED_EXIT);
+ /* Register us as a dependent tree of the inner tree. */
+ ((TreeInfo*)inner->vmprivate)->dependentTrees.addUnique(fragment->root);
+}
+
+/* Add a if/if-else control-flow merge point to the list of known merge points. */
+void
+TraceRecorder::trackCfgMerges(jsbytecode* pc)
+{
+ /* If we hit the beginning of an if/if-else, then keep track of the merge point after it. */
+ JS_ASSERT((*pc == JSOP_IFEQ) || (*pc == JSOP_IFEQX));
+ jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
+ if (sn != NULL) {
+ if (SN_TYPE(sn) == SRC_IF) {
+ cfgMerges.add((*pc == JSOP_IFEQ)
+ ? pc + GET_JUMP_OFFSET(pc)
+ : pc + GET_JUMPX_OFFSET(pc));
+ } else if (SN_TYPE(sn) == SRC_IF_ELSE)
+ cfgMerges.add(pc + js_GetSrcNoteOffset(sn, 0));
+ }
+}
+
+/* Invert the direction of the guard if this is a loop edge that is not
+ taken (thin loop). */
+void
+TraceRecorder::flipIf(jsbytecode* pc, bool& cond)
+{
+ if (js_IsLoopEdge(pc, (jsbytecode*)fragment->root->ip)) {
+ switch (*pc) {
+ case JSOP_IFEQ:
+ case JSOP_IFEQX:
+ if (!cond)
+ return;
+ break;
+ case JSOP_IFNE:
+ case JSOP_IFNEX:
+ if (cond)
+ return;
+ break;
+ default:
+ JS_NOT_REACHED("flipIf");
+ }
+ /* We are about to walk out of the loop, so terminate it with
+ an inverse loop condition. */
+ debug_only_v(printf("Walking out of the loop, terminating it anyway.\n");)
+ cond = !cond;
+ terminate = true;
+ /* If when we get to closeLoop the tree is decided to be type unstable, we need to
+ reverse this logic because the loop won't be closed after all. Store the real
+ value of the IP the interpreter expects, so we can use it in our final LIR_x.
+ */
+ if (*pc == JSOP_IFEQX || *pc == JSOP_IFNEX)
+ pc += GET_JUMPX_OFFSET(pc);
+ else
+ pc += GET_JUMP_OFFSET(pc);
+ terminate_ip_adj = ENCODE_IP_ADJ(cx->fp, pc);
+ }
+}
+
+/* Emit code for a fused IFEQ/IFNE. */
+void
+TraceRecorder::fuseIf(jsbytecode* pc, bool cond, LIns* x)
+{
+ if (x->isconst()) // no need to guard if condition is constant
+ return;
+ if (*pc == JSOP_IFEQ) {
+ flipIf(pc, cond);
+ guard(cond, x, BRANCH_EXIT);
+ trackCfgMerges(pc);
+ } else if (*pc == JSOP_IFNE) {
+ flipIf(pc, cond);
+ guard(cond, x, BRANCH_EXIT);
+ }
+}
+
+bool
+TraceRecorder::hasMethod(JSObject* obj, jsid id)
+{
+ if (!obj)
+ return false;
+
+ JSObject* pobj;
+ JSProperty* prop;
+ int protoIndex = OBJ_LOOKUP_PROPERTY(cx, obj, id, &pobj, &prop);
+ if (protoIndex < 0 || !prop)
+ return false;
+
+ bool found = false;
+ if (OBJ_IS_NATIVE(pobj)) {
+ JSScope* scope = OBJ_SCOPE(pobj);
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+
+ if (SPROP_HAS_STUB_GETTER(sprop) &&
+ SPROP_HAS_VALID_SLOT(sprop, scope)) {
+ jsval v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
+ if (VALUE_IS_FUNCTION(cx, v)) {
+ found = true;
+ if (!SCOPE_IS_BRANDED(scope)) {
+ SCOPE_MAKE_UNIQUE_SHAPE(cx, scope);
+ SCOPE_SET_BRANDED(scope);
+ }
+ }
+ }
+ }
+
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ return found;
+}
+
+bool
+TraceRecorder::hasToStringMethod(JSObject* obj)
+{
+ JS_ASSERT(cx->fp->regs->sp + 1 <= cx->fp->slots + cx->fp->script->nslots);
+
+ return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.toStringAtom));
+}
+
+bool
+TraceRecorder::hasValueOfMethod(JSObject* obj)
+{
+ JS_ASSERT(cx->fp->regs->sp + 2 <= cx->fp->slots + cx->fp->script->nslots);
+
+ return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.valueOfAtom));
+}
+
+bool
+TraceRecorder::hasIteratorMethod(JSObject* obj)
+{
+ JS_ASSERT(cx->fp->regs->sp + 2 <= cx->fp->slots + cx->fp->script->nslots);
+
+ return hasMethod(obj, ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom));
+}
+
+int
+nanojit::StackFilter::getTop(LInsp guard)
+{
+ VMSideExit* e = (VMSideExit*)guard->record()->exit;
+ if (sp == lirbuf->sp)
+ return e->sp_adj;
+ JS_ASSERT(sp == lirbuf->rp);
+ return e->rp_adj;
+}
+
+#if defined NJ_VERBOSE
+void
+nanojit::LirNameMap::formatGuard(LIns *i, char *out)
+{
+ VMSideExit *x;
+
+ x = (VMSideExit *)i->record()->exit;
+ sprintf(out,
+ "%s: %s %s -> %lu:%lu sp%+ld rp%+ld",
+ formatRef(i),
+ lirNames[i->opcode()],
+ i->oprnd1()->isCond() ? formatRef(i->oprnd1()) : "",
+ IMACRO_PC_ADJ(x->ip_adj),
+ SCRIPT_PC_ADJ(x->ip_adj),
+ (long int)x->sp_adj,
+ (long int)x->rp_adj);
+}
+#endif
+
+void
+nanojit::Fragment::onDestroy()
+{
+ if (root == this) {
+ delete mergeCounts;
+ delete lirbuf;
+ }
+ delete (TreeInfo *)vmprivate;
+}
+
+void
+js_DeleteRecorder(JSContext* cx)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /* Aborting and completing a trace end up here. */
+ JS_ASSERT(tm->onTrace);
+ tm->onTrace = false;
+
+ delete tm->recorder;
+ tm->recorder = NULL;
+}
+
+/**
+ * Checks whether the shape of the global object has changed.
+ */
+static inline bool
+js_CheckGlobalObjectShape(JSContext* cx, JSTraceMonitor* tm, JSObject* globalObj)
+{
+ /* Check the global shape. */
+ if (OBJ_SHAPE(globalObj) != tm->globalShape) {
+ AUDIT(globalShapeMismatchAtEntry);
+ debug_only_v(printf("Global shape mismatch (%u vs. %u), flushing cache.\n",
+ OBJ_SHAPE(globalObj), tm->globalShape);)
+ return false;
+ }
+ return true;
+}
+
+static bool
+js_StartRecorder(JSContext* cx, VMSideExit* anchor, Fragment* f, TreeInfo* ti,
+ unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
+ VMSideExit* expectedInnerExit, Fragment* outer)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /*
+ * Emulate on-trace semantics and avoid rooting headaches while recording,
+ * by suppressing last-ditch GC attempts while recording a trace. This does
+ * means that trace recording must not nest or the following assertion will
+ * botch.
+ */
+ JS_ASSERT(!tm->onTrace);
+ tm->onTrace = true;
+
+ /* start recording if no exception during construction */
+ tm->recorder = new (&gc) TraceRecorder(cx, anchor, f, ti,
+ ngslots, globalTypeMap, stackTypeMap,
+ expectedInnerExit, outer);
+ if (cx->throwing) {
+ js_AbortRecording(cx, "setting up recorder failed");
+ return false;
+ }
+ /* clear any leftover error state */
+ tm->fragmento->assm()->setError(None);
+ return true;
+}
+
+static void
+js_TrashTree(JSContext* cx, Fragment* f)
+{
+ JS_ASSERT((!f->code()) == (!f->vmprivate));
+ JS_ASSERT(f == f->root);
+ if (!f->code())
+ return;
+ AUDIT(treesTrashed);
+ debug_only_v(printf("Trashing tree info.\n");)
+ Fragmento* fragmento = JS_TRACE_MONITOR(cx).fragmento;
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+ f->vmprivate = NULL;
+ f->releaseCode(fragmento);
+ Fragment** data = ti->dependentTrees.data();
+ unsigned length = ti->dependentTrees.length();
+ for (unsigned n = 0; n < length; ++n)
+ js_TrashTree(cx, data[n]);
+ delete ti;
+ JS_ASSERT(!f->code() && !f->vmprivate);
+}
+
+static int
+js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
+{
+ JS_ASSERT(HAS_FUNCTION_CLASS(fi.callee));
+
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, fi.callee);
+ JS_ASSERT(FUN_INTERPRETED(fun));
+
+ /* Assert that we have a correct sp distance from cx->fp->slots in fi. */
+ JS_ASSERT_IF(!FI_IMACRO_PC(fi, cx->fp),
+ js_ReconstructStackDepth(cx, cx->fp->script, FI_SCRIPT_PC(fi, cx->fp))
+ == uintN(fi.s.spdist - cx->fp->script->nfixed));
+
+ uintN nframeslots = JS_HOWMANY(sizeof(JSInlineFrame), sizeof(jsval));
+ JSScript* script = fun->u.i.script;
+ size_t nbytes = (nframeslots + script->nslots) * sizeof(jsval);
+
+ /* Code duplicated from inline_call: case in js_Interpret (FIXME). */
+ JSArena* a = cx->stackPool.current;
+ void* newmark = (void*) a->avail;
+ uintN argc = fi.s.argc & 0x7fff;
+ jsval* vp = cx->fp->slots + fi.s.spdist - (2 + argc);
+ uintN missing = 0;
+ jsval* newsp;
+
+ if (fun->nargs > argc) {
+ const JSFrameRegs& regs = *cx->fp->regs;
+
+ newsp = vp + 2 + fun->nargs;
+ JS_ASSERT(newsp > regs.sp);
+ if ((jsuword) newsp <= a->limit) {
+ if ((jsuword) newsp > a->avail)
+ a->avail = (jsuword) newsp;
+ jsval* argsp = newsp;
+ do {
+ *--argsp = JSVAL_VOID;
+ } while (argsp != regs.sp);
+ missing = 0;
+ } else {
+ missing = fun->nargs - argc;
+ nbytes += (2 + fun->nargs) * sizeof(jsval);
+ }
+ }
+
+ /* Allocate the inline frame with its vars and operands. */
+ if (a->avail + nbytes <= a->limit) {
+ newsp = (jsval *) a->avail;
+ a->avail += nbytes;
+ JS_ASSERT(missing == 0);
+ } else {
+ JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool, nbytes);
+ if (!newsp) {
+ js_ReportOutOfScriptQuota(cx);
+ return 0;
+ }
+
+ /*
+ * Move args if the missing ones overflow arena a, then push
+ * undefined for the missing args.
+ */
+ if (missing) {
+ memcpy(newsp, vp, (2 + argc) * sizeof(jsval));
+ vp = newsp;
+ newsp = vp + 2 + argc;
+ do {
+ *newsp++ = JSVAL_VOID;
+ } while (--missing != 0);
+ }
+ }
+
+ /* Claim space for the stack frame and initialize it. */
+ JSInlineFrame* newifp = (JSInlineFrame *) newsp;
+ newsp += nframeslots;
+
+ newifp->frame.callobj = NULL;
+ newifp->frame.argsobj = NULL;
+ newifp->frame.varobj = NULL;
+ newifp->frame.script = script;
+ newifp->frame.callee = fi.callee;
+ newifp->frame.fun = fun;
+
+ bool constructing = fi.s.argc & 0x8000;
+ newifp->frame.argc = argc;
+
+ jsbytecode* imacro_pc = FI_IMACRO_PC(fi, cx->fp);
+ jsbytecode* script_pc = FI_SCRIPT_PC(fi, cx->fp);
+ newifp->callerRegs.pc = imacro_pc ? imacro_pc : script_pc;
+ newifp->callerRegs.sp = cx->fp->slots + fi.s.spdist;
+ cx->fp->imacpc = imacro_pc ? script_pc : NULL;
+
+ newifp->frame.argv = newifp->callerRegs.sp - argc;
+ JS_ASSERT(newifp->frame.argv);
+#ifdef DEBUG
+ // Initialize argv[-1] to a known-bogus value so we'll catch it if
+ // someone forgets to initialize it later.
+ newifp->frame.argv[-1] = JSVAL_HOLE;
+#endif
+ JS_ASSERT(newifp->frame.argv >= StackBase(cx->fp) + 2);
+
+ newifp->frame.rval = JSVAL_VOID;
+ newifp->frame.down = cx->fp;
+ newifp->frame.annotation = NULL;
+ newifp->frame.scopeChain = OBJ_GET_PARENT(cx, fi.callee);
+ newifp->frame.sharpDepth = 0;
+ newifp->frame.sharpArray = NULL;
+ newifp->frame.flags = constructing ? JSFRAME_CONSTRUCTING : 0;
+ newifp->frame.dormantNext = NULL;
+ newifp->frame.xmlNamespace = NULL;
+ newifp->frame.blockChain = NULL;
+ newifp->mark = newmark;
+ newifp->frame.thisp = NULL; // will be set by js_ExecuteTree -> FlushNativeStackFrame
+
+ newifp->frame.regs = cx->fp->regs;
+ newifp->frame.regs->pc = script->code;
+ newifp->frame.regs->sp = newsp + script->nfixed;
+ newifp->frame.imacpc = NULL;
+ newifp->frame.slots = newsp;
+ if (script->staticDepth < JS_DISPLAY_SIZE) {
+ JSStackFrame **disp = &cx->display[script->staticDepth];
+ newifp->frame.displaySave = *disp;
+ *disp = &newifp->frame;
+ }
+#ifdef DEBUG
+ newifp->frame.pcDisabledSave = 0;
+#endif
+
+ /*
+ * Note that cx->fp->script is still the caller's script; set the callee
+ * inline frame's idea of caller version from its version.
+ */
+ newifp->callerVersion = (JSVersion) cx->fp->script->version;
+
+ cx->fp->regs = &newifp->callerRegs;
+ cx->fp = &newifp->frame;
+
+ if (fun->flags & JSFUN_HEAVYWEIGHT) {
+ /*
+ * Set hookData to null because the failure case for js_GetCallObject
+ * involves it calling the debugger hook.
+ */
+ newifp->hookData = NULL;
+ if (!js_GetCallObject(cx, &newifp->frame, newifp->frame.scopeChain))
+ return -1;
+ }
+
+ /*
+ * If there's a call hook, invoke it to compute the hookData used by
+ * debuggers that cooperate with the interpreter.
+ */
+ JSInterpreterHook hook = cx->debugHooks->callHook;
+ if (hook) {
+ newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,
+ cx->debugHooks->callHookData);
+ } else {
+ newifp->hookData = NULL;
+ }
+
+ // FIXME? we must count stack slots from caller's operand stack up to (but not including)
+ // callee's, including missing arguments. Could we shift everything down to the caller's
+ // fp->slots (where vars start) and avoid some of the complexity?
+ return (fi.s.spdist - cx->fp->down->script->nfixed) +
+ ((fun->nargs > cx->fp->argc) ? fun->nargs - cx->fp->argc : 0) +
+ script->nfixed;
+}
+
+bool
+js_RecordTree(JSContext* cx, JSTraceMonitor* tm, Fragment* f, Fragment* outer, unsigned* demotes)
+{
+ JS_ASSERT(cx->fp->regs->pc == f->ip && f->root == f);
+
+ /* Avoid recording loops in overlarge scripts. */
+ if (cx->fp->script->length >= SCRIPT_PC_ADJ_LIMIT) {
+ js_AbortRecording(cx, "script too large");
+ return false;
+ }
+
+ /* Make sure the global type map didn't change on us. */
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ if (!js_CheckGlobalObjectShape(cx, tm, globalObj)) {
+ js_FlushJITCache(cx);
+ return false;
+ }
+ TypeMap current;
+ current.captureGlobalTypes(cx, *tm->globalSlots);
+ if (!current.matches(*tm->globalTypeMap)) {
+ js_FlushJITCache(cx);
+ debug_only_v(printf("Global type map mismatch in RecordTree, flushing cache.\n");)
+ return false;
+ }
+
+ AUDIT(recorderStarted);
+
+ /* Try to find an unused peer fragment, or allocate a new one. */
+ while (f->code() && f->peer)
+ f = f->peer;
+ if (f->code())
+ f = JS_TRACE_MONITOR(cx).fragmento->getAnchor(f->root->ip);
+
+ f->recordAttempts++;
+ f->root = f;
+ /* allocate space to store the LIR for this tree */
+ if (!f->lirbuf) {
+ f->lirbuf = new (&gc) LirBuffer(tm->fragmento, NULL);
+#ifdef DEBUG
+ f->lirbuf->names = new (&gc) LirNameMap(&gc, NULL, tm->fragmento->labels);
+#endif
+ }
+
+ if (f->lirbuf->outOmem()) {
+ js_FlushJITCache(cx);
+ debug_only_v(printf("Out of memory recording new tree, flushing cache.\n");)
+ return false;
+ }
+
+ JS_ASSERT(!f->code() && !f->vmprivate);
+
+ /* setup the VM-private treeInfo structure for this fragment */
+ TreeInfo* ti = new (&gc) TreeInfo(f);
+
+ /* capture the coerced type of each active slot in the stack type map */
+ ti->stackTypeMap.captureStackTypes(cx, 0/*callDepth*/);
+
+ if (demotes) {
+ /* If we get a list of demotions, an outer tree is telling us our types are not callable. */
+ uint8* typeMap = ti->stackTypeMap.data();
+ for (unsigned i = 1; i <= NUM_UNDEMOTE_SLOTS(demotes); i++) {
+ JS_ASSERT(demotes[i] < ti->stackTypeMap.length());
+ if (typeMap[demotes[i]] == JSVAL_INT)
+ typeMap[demotes[i]] = JSVAL_DOUBLE;
+ }
+ }
+
+ /* Check for duplicate entry type maps. This is always wrong and hints at trace explosion
+ since we are trying to stabilize something without properly connecting peer edges. */
+ #ifdef DEBUG
+ TreeInfo* ti_other;
+ for (Fragment* peer = tm->fragmento->getLoop(f->root->ip); peer != NULL; peer = peer->peer) {
+ if (!peer->code() || peer == f)
+ continue;
+ ti_other = (TreeInfo*)peer->vmprivate;
+ JS_ASSERT(ti_other);
+ JS_ASSERT(!ti->stackTypeMap.matches(ti_other->stackTypeMap));
+ }
+ #endif
+
+ /* determine the native frame layout at the entry point */
+ unsigned entryNativeStackSlots = ti->stackTypeMap.length();
+ JS_ASSERT(entryNativeStackSlots == js_NativeStackSlots(cx, 0/*callDepth*/));
+ ti->nativeStackBase = (entryNativeStackSlots -
+ (cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double);
+ ti->maxNativeStackSlots = entryNativeStackSlots;
+ ti->maxCallDepth = 0;
+ ti->script = cx->fp->script;
+
+ /* recording primary trace */
+ if (!js_StartRecorder(cx, NULL, f, ti,
+ tm->globalSlots->length(), tm->globalTypeMap->data(),
+ ti->stackTypeMap.data(), NULL, outer)) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+js_AttemptToStabilizeTree(JSContext* cx, VMSideExit* exit, Fragment* outer)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ Fragment* from = exit->from->root;
+ unsigned* demotes;
+
+ JS_ASSERT(exit->from->root->code());
+
+ demotes = ALLOCA_UNDEMOTE_SLOTLIST(exit->numStackSlots);
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+
+ uint8* t2 = getTypeMap(exit) + exit->numGlobalSlots;
+ for (unsigned i = 0; i < exit->numStackSlots; i++) {
+ if (t2[i] == JSVAL_DOUBLE)
+ ADD_UNDEMOTE_SLOT(demotes, i);
+ }
+
+ if (!NUM_UNDEMOTE_SLOTS(demotes))
+ demotes = NULL;
+
+ if (!js_RecordTree(cx, tm, from->first, outer, demotes))
+ return false;
+
+ tm->recorder->setPromotedPeer(demotes ? from : NULL);
+
+ return true;
+}
+
+static bool
+js_AttemptToExtendTree(JSContext* cx, VMSideExit* anchor, VMSideExit* exitedFrom, Fragment* outer)
+{
+ Fragment* f = anchor->from->root;
+ JS_ASSERT(f->vmprivate);
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+
+ /* Don't grow trees above a certain size to avoid code explosion due to tail duplication. */
+ if (ti->branchCount >= MAX_BRANCHES)
+ return false;
+
+ Fragment* c;
+ if (!(c = anchor->target)) {
+ c = JS_TRACE_MONITOR(cx).fragmento->createBranch(anchor, cx->fp->regs->pc);
+ c->spawnedFrom = anchor;
+ c->parent = f;
+ anchor->target = c;
+ c->root = f;
+ }
+
+ debug_only_v(printf("trying to attach another branch to the tree (hits = %d)\n", c->hits());)
+
+ if (++c->hits() >= HOTEXIT) {
+ /* start tracing secondary trace from this point */
+ c->lirbuf = f->lirbuf;
+ unsigned ngslots;
+ uint8* globalTypeMap;
+ uint8* stackTypeMap;
+ TypeMap fullMap;
+ if (exitedFrom == NULL) {
+ /* If we are coming straight from a simple side exit, just use that exit's type map
+ as starting point. */
+ ngslots = anchor->numGlobalSlots;
+ globalTypeMap = getTypeMap(anchor);
+ stackTypeMap = globalTypeMap + ngslots;
+ } else {
+ /* If we side-exited on a loop exit and continue on a nesting guard, the nesting
+ guard (anchor) has the type information for everything below the current scope,
+ and the actual guard we exited from has the types for everything in the current
+ scope (and whatever it inlined). We have to merge those maps here. */
+ VMSideExit* e1 = anchor;
+ VMSideExit* e2 = exitedFrom;
+ fullMap.add(getTypeMap(e1) + e1->numGlobalSlots, e1->numStackSlotsBelowCurrentFrame);
+ fullMap.add(getTypeMap(e2) + e2->numGlobalSlots, e2->numStackSlots);
+ ngslots = e2->numGlobalSlots;
+ globalTypeMap = getTypeMap(e2);
+ stackTypeMap = fullMap.data();
+ }
+ return js_StartRecorder(cx, anchor, c, (TreeInfo*)f->vmprivate,
+ ngslots, globalTypeMap, stackTypeMap, exitedFrom, outer);
+ }
+ return false;
+}
+
+static VMSideExit*
+js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
+ VMSideExit** innermostNestedGuardp);
+
+static Fragment*
+js_FindVMCompatiblePeer(JSContext* cx, Fragment* f);
+
+static bool
+js_CloseLoop(JSContext* cx)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ Fragmento* fragmento = tm->fragmento;
+ TraceRecorder* r = tm->recorder;
+ JS_ASSERT(fragmento && r);
+ bool walkedOutOfLoop = r->walkedOutOfLoop();
+
+ if (fragmento->assm()->error()) {
+ js_AbortRecording(cx, "Error during recording");
+
+ /* If we ran out of memory, flush the code cache and abort. */
+ if (fragmento->assm()->error() == OutOMem)
+ js_FlushJITCache(cx);
+ return false;
+ }
+
+ bool demote;
+ Fragment* f = r->getFragment();
+ TreeInfo* ti = r->getTreeInfo();
+ unsigned* demotes = ALLOCA_UNDEMOTE_SLOTLIST(ti->stackTypeMap.length());
+ r->closeLoop(fragmento, demote, demotes);
+ JS_ASSERT(!demote || NUM_UNDEMOTE_SLOTS(demotes));
+ js_DeleteRecorder(cx);
+
+ /*
+ * If we just walked out of a thin loop, we can't immediately start the
+ * compiler again here since we didn't return to the loop header.
+ */
+ if (demote && !walkedOutOfLoop)
+ return js_RecordTree(cx, tm, f, NULL, demotes);
+ return false;
+}
+
+bool
+js_RecordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCallCount)
+{
+#ifdef JS_THREADSAFE
+ if (OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->title.ownercx != cx) {
+ js_AbortRecording(cx, "Global object not owned by this context");
+ return false; /* we stay away from shared global objects */
+ }
+#endif
+ Fragmento* fragmento = JS_TRACE_MONITOR(cx).fragmento;
+ /* If we hit our own loop header, close the loop and compile the trace. */
+ if (r->isLoopHeader(cx))
+ return js_CloseLoop(cx);
+ /* does this branch go to an inner loop? */
+ Fragment* f = fragmento->getLoop(cx->fp->regs->pc);
+ Fragment* peer_root = f;
+ if (nesting_enabled && f) {
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /* Make sure inner tree call will not run into an out-of-memory condition. */
+ if (tm->recoveryDoublePoolPtr < (tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS) &&
+ !js_ReplenishRecoveryPool(cx, tm)) {
+ js_AbortRecording(cx, "Couldn't call inner tree (out of memory)");
+ return false;
+ }
+
+ /* Make sure the shape of the global object still matches (this might flush
+ the JIT cache). */
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ if (!js_CheckGlobalObjectShape(cx, tm, globalObj)) {
+ js_AbortRecording(cx, "Couldn't call inner tree (prep failed)");
+ return false;
+ }
+
+ debug_only_v(printf("Looking for type-compatible peer (%s:%d@%d)\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp));)
+
+ /* Find an acceptable peer, make sure our types fit. */
+ Fragment* empty;
+ bool trash = false;
+ bool success = false;
+ unsigned* demotes = NULL;
+
+ f = r->findNestedCompatiblePeer(f, &empty);
+ if (f && f->code()) {
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+ /* alloca docs says it lasts out of scopes. */
+ demotes = ALLOCA_UNDEMOTE_SLOTLIST(ti->stackTypeMap.length());
+ CLEAR_UNDEMOTE_SLOTLIST(demotes);
+ success = r->adjustCallerTypes(f, demotes, trash);
+ }
+
+ if (!success) {
+ AUDIT(noCompatInnerTrees);
+ debug_only_v(printf("No compatible inner tree (%p).\n", f);)
+
+ if (trash) {
+ js_AbortRecording(cx, "No compatible inner tree (global demotions");
+ return false;
+ }
+
+ Fragment* old = fragmento->getLoop(tm->recorder->getFragment()->root->ip);
+ if (old == NULL)
+ old = tm->recorder->getFragment();
+ js_AbortRecording(cx, "No compatible inner tree");
+ if (!f && ++peer_root->hits() < MAX_INNER_RECORD_BLACKLIST)
+ return false;
+ if (old->recordAttempts < MAX_MISMATCH)
+ old->resetHits();
+ f = empty ? empty : tm->fragmento->getAnchor(cx->fp->regs->pc);
+ return js_RecordTree(cx, tm, f, old, demotes);
+ }
+
+ r->prepareTreeCall(f);
+ VMSideExit* innermostNestedGuard = NULL;
+ VMSideExit* lr = js_ExecuteTree(cx, f, inlineCallCount, &innermostNestedGuard);
+ if (!lr) {
+ js_AbortRecording(cx, "Couldn't call inner tree");
+ return false;
+ }
+ Fragment* old;
+ switch (lr->exitType) {
+ case LOOP_EXIT:
+ /* If the inner tree exited on an unknown loop exit, grow the tree around it. */
+ if (innermostNestedGuard) {
+ js_AbortRecording(cx, "Inner tree took different side exit, abort recording");
+ return js_AttemptToExtendTree(cx, innermostNestedGuard, lr, NULL);
+ }
+ /* emit a call to the inner tree and continue recording the outer tree trace */
+ r->emitTreeCall(f, lr);
+ return true;
+ case UNSTABLE_LOOP_EXIT:
+ /* abort recording so the inner loop can become type stable. */
+ old = fragmento->getLoop(tm->recorder->getFragment()->root->ip);
+ js_AbortRecording(cx, "Inner tree is trying to stabilize, abort outer recording");
+ old->resetHits();
+ return js_AttemptToStabilizeTree(cx, lr, old);
+ case BRANCH_EXIT:
+ /* abort recording the outer tree, extend the inner tree */
+ old = fragmento->getLoop(tm->recorder->getFragment()->root->ip);
+ js_AbortRecording(cx, "Inner tree is trying to grow, abort outer recording");
+ old->resetHits();
+ return js_AttemptToExtendTree(cx, lr, NULL, old);
+ default:
+ debug_only_v(printf("exit_type=%d\n", lr->exitType);)
+ js_AbortRecording(cx, "Inner tree not suitable for calling");
+ return false;
+ }
+ }
+
+ /* not returning to our own loop header, not an inner loop we can call, abort trace */
+ AUDIT(returnToDifferentLoopHeader);
+ JS_ASSERT(!cx->fp->imacpc);
+ debug_only_v(printf("loop edge to %d, header %d\n",
+ cx->fp->regs->pc - cx->fp->script->code,
+ (jsbytecode*)r->getFragment()->root->ip - cx->fp->script->code));
+ js_AbortRecording(cx, "Loop edge does not return to header");
+ return false;
+}
+
+static bool
+js_IsEntryTypeCompatible(jsval* vp, uint8* m)
+{
+ unsigned tag = JSVAL_TAG(*vp);
+
+ debug_only_v(printf("%c/%c ", "OIDISIBI"[tag], "OID?S?B?"[*m]);)
+
+ switch (*m) {
+ case JSVAL_INT:
+ jsint i;
+ if (JSVAL_IS_INT(*vp))
+ return true;
+ if ((tag == JSVAL_DOUBLE) && JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(*vp), i))
+ return true;
+ debug_only_v(printf("int != tag%u(value=%lu) ", tag, *vp);)
+ return false;
+ case JSVAL_DOUBLE:
+ if (JSVAL_IS_INT(*vp) || tag == JSVAL_DOUBLE)
+ return true;
+ debug_only_v(printf("double != tag%u ", tag);)
+ return false;
+ case JSVAL_BOOLEAN:
+ if (tag == JSVAL_BOOLEAN)
+ return true;
+ debug_only_v(printf("bool != tag%u", tag);)
+ return false;
+ case JSVAL_STRING:
+ if (tag == JSVAL_STRING)
+ return true;
+ debug_only_v(printf("string != tag%u", tag);)
+ return false;
+ default:
+ JS_ASSERT(*m == JSVAL_OBJECT);
+ if (tag == JSVAL_OBJECT)
+ return true;
+ debug_only_v(printf("object != tag%u", tag);)
+ return false;
+ }
+}
+
+Fragment* TraceRecorder::findNestedCompatiblePeer(Fragment* f, Fragment** empty)
+{
+ Fragment* demote;
+ JSTraceMonitor* tm;
+ unsigned max_demotes;
+
+ if (empty)
+ *empty = NULL;
+ demote = NULL;
+
+ tm = &JS_TRACE_MONITOR(cx);
+ unsigned int ngslots = tm->globalSlots->length();
+ uint16* gslots = tm->globalSlots->data();
+ uint8* m = tm->globalTypeMap->data();
+
+ if (ngslots) {
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ return NULL;
+ m++;
+ );
+ }
+
+ /* We keep a maximum tally - we want to select the peer most likely to work so we don't keep
+ * recording.
+ */
+ max_demotes = 0;
+
+ TreeInfo* ti;
+ for (; f != NULL; f = f->peer) {
+ if (!f->code()) {
+ if (empty)
+ *empty = f;
+ continue;
+ }
+
+ unsigned demotes = 0;
+ ti = (TreeInfo*)f->vmprivate;
+ m = ti->stackTypeMap.data();
+
+ debug_only_v(printf("checking nested types %p: ", f);)
+
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ goto check_fail;
+ if (*m == JSVAL_STRING && *vp == JSVAL_VOID)
+ goto check_fail;
+ if (*m == JSVAL_INT && !isPromoteInt(get(vp)))
+ demotes++;
+ m++;
+ );
+ JS_ASSERT(unsigned(m - ti->stackTypeMap.data()) == ti->stackTypeMap.length());
+
+ debug_only_v(printf(" (demotes %d)\n", demotes);)
+
+ if (demotes) {
+ if (demotes > max_demotes) {
+ demote = f;
+ max_demotes = demotes;
+ }
+ continue;
+ } else {
+ return f;
+ }
+
+check_fail:
+ debug_only_v(printf("\n"));
+ continue;
+ }
+
+ if (demote)
+ return demote;
+
+ return NULL;
+}
+
+/**
+ * Check if types are usable for trace execution.
+ *
+ * @param cx Context.
+ * @param ti Tree info of peer we're testing.
+ * @return True if compatible (with or without demotions), false otherwise.
+ */
+static bool
+js_CheckEntryTypes(JSContext* cx, TreeInfo* ti)
+{
+ JSTraceMonitor* tm;
+
+ tm = &JS_TRACE_MONITOR(cx);
+ unsigned int ngslots = tm->globalSlots->length();
+ uint16* gslots = tm->globalSlots->data();
+ uint8* m = tm->globalTypeMap->data();
+
+ if (ngslots) {
+ FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ goto check_fail;
+ m++;
+ );
+ }
+
+ m = ti->stackTypeMap.data();
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0,
+ debug_only_v(printf("%s%d=", vpname, vpnum);)
+ if (!js_IsEntryTypeCompatible(vp, m))
+ goto check_fail;
+ m++;
+ );
+ JS_ASSERT(unsigned(m - ti->stackTypeMap.data()) == ti->stackTypeMap.length());
+
+ debug_only_v(printf("\n");)
+ return true;
+
+check_fail:
+ debug_only_v(printf("\n");)
+ return false;
+}
+
+/**
+ * Find an acceptable entry tree given a PC.
+ *
+ * @param cx Context.
+ * @param f First peer fragment.
+ * @param nodemote If true, will try to find a peer that does not require demotion.
+ */
+static Fragment*
+js_FindVMCompatiblePeer(JSContext* cx, Fragment* f)
+{
+ for (; f != NULL; f = f->peer) {
+ if (f->vmprivate == NULL)
+ continue;
+ debug_only_v(printf("checking vm types %p (ip: %p): ", f, f->ip);)
+ if (js_CheckEntryTypes(cx, (TreeInfo*)f->vmprivate))
+ return f;
+ }
+ return NULL;
+}
+
+/**
+ * Executes a tree.
+ */
+static VMSideExit*
+js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount,
+ VMSideExit** innermostNestedGuardp)
+{
+ JS_ASSERT(f->code() && f->vmprivate);
+
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ TreeInfo* ti = (TreeInfo*)f->vmprivate;
+ unsigned ngslots = tm->globalSlots->length();
+ uint16* gslots = tm->globalSlots->data();
+ unsigned globalFrameSize = STOBJ_NSLOTS(globalObj);
+ double* global = (double*)alloca((globalFrameSize+1) * sizeof(double));
+ double stack_buffer[MAX_NATIVE_STACK_SLOTS];
+ double* stack = stack_buffer;
+
+ /* Make sure the global object is sane. */
+ JS_ASSERT(!ngslots || (OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain)) == tm->globalShape));
+ /* Make sure our caller replenished the double pool. */
+ JS_ASSERT(tm->recoveryDoublePoolPtr >= tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS);
+
+#ifdef DEBUG
+ memset(stack_buffer, 0xCD, sizeof(stack_buffer));
+ memset(global, 0xCD, (globalFrameSize+1)*sizeof(double));
+#endif
+
+ debug_only(*(uint64*)&global[globalFrameSize] = 0xdeadbeefdeadbeefLL;)
+ debug_only_v(printf("entering trace at %s:%u@%u, native stack slots: %u code: %p\n",
+ cx->fp->script->filename,
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp),
+ ti->maxNativeStackSlots,
+ f->code());)
+
+ if (ngslots)
+ BuildNativeGlobalFrame(cx, ngslots, gslots, tm->globalTypeMap->data(), global);
+ BuildNativeStackFrame(cx, 0/*callDepth*/, ti->stackTypeMap.data(), stack);
+
+ double* entry_sp = &stack[ti->nativeStackBase/sizeof(double)];
+ FrameInfo callstack_buffer[MAX_CALL_STACK_ENTRIES];
+ FrameInfo* callstack = callstack_buffer;
+
+ InterpState state;
+ state.sp = (void*)entry_sp;
+ state.eos = ((double*)state.sp) + MAX_NATIVE_STACK_SLOTS;
+ state.rp = callstack;
+ state.eor = callstack + MAX_CALL_STACK_ENTRIES;
+ state.gp = global;
+ state.cx = cx;
+ state.lastTreeExitGuard = NULL;
+ state.lastTreeCallGuard = NULL;
+ state.rpAtLastTreeCall = NULL;
+ union { NIns *code; GuardRecord* (FASTCALL *func)(InterpState*, Fragment*); } u;
+ u.code = f->code();
+
+#ifdef JS_JIT_SPEW
+#if defined(NANOJIT_IA32) || (defined(NANOJIT_AMD64) && defined(__GNUC__))
+ uint64 start = rdtsc();
+#endif
+#endif
+
+ /*
+ * We may be called from js_MonitorLoopEdge while not recording, or while
+ * recording. Rather than over-generalize by using a counter instead of a
+ * flag, we simply sample and update tm->onTrace if necessary.
+ */
+ bool onTrace = tm->onTrace;
+ if (!onTrace)
+ tm->onTrace = true;
+ VMSideExit* lr;
+
+ debug_only(fflush(NULL);)
+ GuardRecord* rec;
+#if defined(JS_NO_FASTCALL) && defined(NANOJIT_IA32)
+ SIMULATE_FASTCALL(rec, &state, NULL, u.func);
+#else
+ rec = u.func(&state, NULL);
+#endif
+ lr = (VMSideExit*)rec->exit;
+
+ AUDIT(traceTriggered);
+
+ JS_ASSERT(lr->exitType != LOOP_EXIT || !lr->calldepth);
+
+ tm->onTrace = onTrace;
+
+ /* Except if we find that this is a nested bailout, the guard the call returned is the
+ one we have to use to adjust pc and sp. */
+ VMSideExit* innermost = lr;
+
+ /* While executing a tree we do not update state.sp and state.rp even if they grow. Instead,
+ guards tell us by how much sp and rp should be incremented in case of a side exit. When
+ calling a nested tree, however, we actively adjust sp and rp. If we have such frames
+ from outer trees on the stack, then rp will have been adjusted. Before we can process
+ the stack of the frames of the tree we directly exited from, we have to first work our
+ way through the outer frames and generate interpreter frames for them. Once the call
+ stack (rp) is empty, we can process the final frames (which again are not directly
+ visible and only the guard we exited on will tells us about). */
+ FrameInfo* rp = (FrameInfo*)state.rp;
+ if (lr->exitType == NESTED_EXIT) {
+ VMSideExit* nested = state.lastTreeCallGuard;
+ if (!nested) {
+ /* If lastTreeCallGuard is not set in state, we only have a single level of
+ nesting in this exit, so lr itself is the innermost and outermost nested
+ guard, and hence we set nested to lr. The calldepth of the innermost guard
+ is not added to state.rp, so we do it here manually. For a nesting depth
+ greater than 1 the CallTree builtin already added the innermost guard's
+ calldepth to state.rpAtLastTreeCall. */
+ nested = lr;
+ rp += lr->calldepth;
+ } else {
+ /* During unwinding state.rp gets overwritten at every step and we restore
+ it here to its state at the innermost nested guard. The builtin already
+ added the calldepth of that innermost guard to rpAtLastTreeCall. */
+ rp = (FrameInfo*)state.rpAtLastTreeCall;
+ }
+ innermost = state.lastTreeExitGuard;
+ if (innermostNestedGuardp)
+ *innermostNestedGuardp = nested;
+ JS_ASSERT(nested);
+ JS_ASSERT(nested->exitType == NESTED_EXIT);
+ JS_ASSERT(state.lastTreeExitGuard);
+ JS_ASSERT(state.lastTreeExitGuard->exitType != NESTED_EXIT);
+ }
+
+ while (callstack < rp) {
+ /* Synthesize a stack frame and write out the values in it using the type map pointer
+ on the native call stack. */
+ if (js_SynthesizeFrame(cx, *callstack) < 0)
+ return NULL;
+ int slots = FlushNativeStackFrame(cx, 1/*callDepth*/, callstack->typemap, stack, cx->fp);
+#ifdef DEBUG
+ JSStackFrame* fp = cx->fp;
+ debug_only_v(printf("synthesized deep frame for %s:%u@%u, slots=%d\n",
+ fp->script->filename,
+ js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp),
+ slots);)
+#endif
+ if (slots < 0)
+ return NULL;
+ /* Keep track of the additional frames we put on the interpreter stack and the native
+ stack slots we consumed. */
+ ++inlineCallCount;
+ ++callstack;
+ stack += slots;
+ }
+
+ /* We already synthesized the frames around the innermost guard. Here we just deal
+ with additional frames inside the tree we are bailing out from. */
+ JS_ASSERT(rp == callstack);
+ unsigned calldepth = innermost->calldepth;
+ unsigned calldepth_slots = 0;
+ for (unsigned n = 0; n < calldepth; ++n) {
+ int nslots = js_SynthesizeFrame(cx, callstack[n]);
+ if (nslots < 0)
+ return NULL;
+ calldepth_slots += nslots;
+ ++inlineCallCount;
+#ifdef DEBUG
+ JSStackFrame* fp = cx->fp;
+ debug_only_v(printf("synthesized shallow frame for %s:%u@%u\n",
+ fp->script->filename, js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp));)
+#endif
+ }
+
+ /* Adjust sp and pc relative to the tree we exited from (not the tree we entered into).
+ These are our final values for sp and pc since js_SynthesizeFrame has already taken
+ care of all frames in between. */
+ JSStackFrame* fp = cx->fp;
+
+ /* If we are not exiting from an inlined frame the state->sp is spbase, otherwise spbase
+ is whatever slots frames around us consume. */
+ DECODE_IP_ADJ(innermost->ip_adj, fp);
+ fp->regs->sp = StackBase(fp) + (innermost->sp_adj / sizeof(double)) - calldepth_slots;
+ JS_ASSERT_IF(!fp->imacpc,
+ fp->slots + fp->script->nfixed +
+ js_ReconstructStackDepth(cx, fp->script, fp->regs->pc) == fp->regs->sp);
+
+
+#if defined(JS_JIT_SPEW) && (defined(NANOJIT_IA32) || (defined(NANOJIT_AMD64) && defined(__GNUC__)))
+ uint64 cycles = rdtsc() - start;
+#elif defined(JS_JIT_SPEW)
+ uint64 cycles = 0;
+#endif
+
+ debug_only_v(printf("leaving trace at %s:%u@%u, op=%s, lr=%p, exitType=%d, sp=%d, "
+ "calldepth=%d, cycles=%llu\n",
+ fp->script->filename,
+ js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp),
+ js_CodeName[fp->imacpc ? *fp->imacpc : *fp->regs->pc],
+ lr,
+ lr->exitType,
+ fp->regs->sp - StackBase(fp),
+ calldepth,
+ cycles));
+
+ /* If this trace is part of a tree, later branches might have added additional globals for
+ with we don't have any type information available in the side exit. We merge in this
+ information from the entry type-map. See also comment in the constructor of TraceRecorder
+ why this is always safe to do. */
+ unsigned exit_gslots = innermost->numGlobalSlots;
+ JS_ASSERT(ngslots == tm->globalTypeMap->length());
+ JS_ASSERT(ngslots >= exit_gslots);
+ uint8* globalTypeMap = getTypeMap(innermost);
+ if (exit_gslots < ngslots)
+ mergeTypeMaps(&globalTypeMap, &exit_gslots, tm->globalTypeMap->data(), ngslots,
+ (uint8*)alloca(sizeof(uint8) * ngslots));
+ JS_ASSERT(exit_gslots == tm->globalTypeMap->length());
+
+ /* write back interned globals */
+ int slots = FlushNativeGlobalFrame(cx, exit_gslots, gslots, globalTypeMap, global);
+ if (slots < 0)
+ return NULL;
+ JS_ASSERT_IF(ngslots != 0, globalFrameSize == STOBJ_NSLOTS(globalObj));
+ JS_ASSERT(*(uint64*)&global[globalFrameSize] == 0xdeadbeefdeadbeefLL);
+
+ /* write back native stack frame */
+ slots = FlushNativeStackFrame(cx, innermost->calldepth,
+ getTypeMap(innermost) + innermost->numGlobalSlots,
+ stack, NULL);
+ if (slots < 0)
+ return NULL;
+ JS_ASSERT(unsigned(slots) == innermost->numStackSlots);
+
+#ifdef DEBUG
+ // Verify that our state restoration worked
+ for (JSStackFrame* fp = cx->fp; fp; fp = fp->down) {
+ JS_ASSERT(!fp->callee || JSVAL_IS_OBJECT(fp->argv[-1]));
+ JS_ASSERT(!fp->callee || fp->thisp == JSVAL_TO_OBJECT(fp->argv[-1]));
+ }
+#endif
+
+ AUDIT(sideExitIntoInterpreter);
+
+ return innermost;
+}
+
+bool
+js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ /* Is the recorder currently active? */
+ if (tm->recorder) {
+ if (js_RecordLoopEdge(cx, tm->recorder, inlineCallCount))
+ return true;
+ /* recording was aborted, treat like a regular loop edge hit */
+ }
+ JS_ASSERT(!tm->recorder);
+
+
+ /* Check the recovery pool of doubles (this might trigger a GC). */
+ if (tm->recoveryDoublePoolPtr < (tm->recoveryDoublePool + MAX_NATIVE_STACK_SLOTS) &&
+ !js_ReplenishRecoveryPool(cx, tm)) {
+ return false; /* Out of memory, don't try to record now. */
+ }
+
+ /* Make sure the shape of the global object still matches (this might flush the JIT cache). */
+ JSObject* globalObj = JS_GetGlobalForObject(cx, cx->fp->scopeChain);
+ if (!js_CheckGlobalObjectShape(cx, tm, globalObj))
+ js_FlushJITCache(cx);
+
+ jsbytecode* pc = cx->fp->regs->pc;
+ Fragmento* fragmento = tm->fragmento;
+ Fragment* f;
+ f = fragmento->getLoop(pc);
+ if (!f)
+ f = fragmento->getAnchor(pc);
+
+ /* If we have no code in the anchor and no peers, we definitively won't be able to
+ activate any trees so increment the hit counter and start compiling if appropriate. */
+ if (!f->code() && !f->peer) {
+monitor_loop:
+ if (++f->hits() >= HOTLOOP) {
+ /* We can give RecordTree the root peer. If that peer is already taken, it will
+ walk the peer list and find us a free slot or allocate a new tree if needed. */
+ return js_RecordTree(cx, tm, f->first, NULL, NULL);
+ }
+ /* Threshold not reached yet. */
+ return false;
+ }
+
+ debug_only_v(printf("Looking for compat peer %d@%d, from %p (ip: %p, hits=%d)\n",
+ js_FramePCToLineNumber(cx, cx->fp),
+ FramePCOffset(cx->fp),
+ f, f->ip, f->hits());)
+ Fragment* match = js_FindVMCompatiblePeer(cx, f);
+ /* If we didn't find a tree that actually matched, keep monitoring the loop. */
+ if (!match)
+ goto monitor_loop;
+
+ VMSideExit* lr = NULL;
+ VMSideExit* innermostNestedGuard = NULL;
+
+ lr = js_ExecuteTree(cx, match, inlineCallCount, &innermostNestedGuard);
+ if (!lr)
+ return false;
+
+ /* If we exit on a branch, or on a tree call guard, try to grow the inner tree (in case
+ of a branch exit), or the tree nested around the tree we exited from (in case of the
+ tree call guard). */
+ switch (lr->exitType) {
+ case UNSTABLE_LOOP_EXIT:
+ return js_AttemptToStabilizeTree(cx, lr, NULL);
+ case BRANCH_EXIT:
+ return js_AttemptToExtendTree(cx, lr, NULL, NULL);
+ case LOOP_EXIT:
+ if (innermostNestedGuard)
+ return js_AttemptToExtendTree(cx, innermostNestedGuard, lr, NULL);
+ return false;
+ default:
+ /* No, this was an unusual exit (i.e. out of memory/GC), so just resume interpretation. */
+ return false;
+ }
+}
+
+bool
+js_MonitorRecording(TraceRecorder* tr)
+{
+ JSContext* cx = tr->cx;
+
+ if (tr->lirbuf->outOmem()) {
+ js_AbortRecording(cx, "no more LIR memory");
+ js_FlushJITCache(cx);
+ return false;
+ }
+
+ if (tr->walkedOutOfLoop())
+ return js_CloseLoop(cx);
+
+ // Clear one-shot state used to communicate between record_JSOP_CALL and mid- and post-
+ // opcode-case-guts record hooks (record_EnterFrame, record_FastNativeCallComplete).
+ tr->applyingArguments = false;
+ tr->pendingTraceableNative = NULL;
+
+ // In the future, handle dslots realloc by computing an offset from dslots instead.
+ if (tr->global_dslots != tr->globalObj->dslots) {
+ js_AbortRecording(cx, "globalObj->dslots reallocated");
+ return false;
+ }
+
+ // Process deepAbort() requests now.
+ if (tr->wasDeepAborted()) {
+ js_AbortRecording(cx, "deep abort requested");
+ return false;
+ }
+
+ jsbytecode* pc = cx->fp->regs->pc;
+
+ /* If we hit a break, end the loop and generate an always taken loop exit guard. For other
+ downward gotos (like if/else) continue recording. */
+ if (*pc == JSOP_GOTO || *pc == JSOP_GOTOX) {
+ jssrcnote* sn = js_GetSrcNote(cx->fp->script, pc);
+ if (sn && SN_TYPE(sn) == SRC_BREAK) {
+ AUDIT(breakLoopExits);
+ tr->endLoop(JS_TRACE_MONITOR(cx).fragmento);
+ js_DeleteRecorder(cx);
+ return false; /* done recording */
+ }
+ }
+
+ /* An explicit return from callDepth 0 should end the loop, not abort it. */
+ if (*pc == JSOP_RETURN && tr->callDepth == 0) {
+ AUDIT(returnLoopExits);
+ tr->endLoop(JS_TRACE_MONITOR(cx).fragmento);
+ js_DeleteRecorder(cx);
+ return false; /* done recording */
+ }
+
+ /* If it's not a break or a return from a loop, continue recording and follow the trace. */
+ return true;
+}
+
+/* If used on a loop trace, blacklists the root peer instead of the given fragment. */
+void
+js_BlacklistPC(Fragmento* frago, Fragment* frag)
+{
+ if (frag->kind == LoopTrace)
+ frag = frago->getLoop(frag->ip);
+ frag->blacklist();
+}
+
+void
+js_AbortRecording(JSContext* cx, const char* reason)
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ JS_ASSERT(tm->recorder != NULL);
+ AUDIT(recorderAborted);
+
+ /* Abort the trace and blacklist its starting point. */
+ JSStackFrame* fp = cx->fp;
+ if (fp) {
+ debug_only_v(printf("Abort recording (line %d, pc %d): %s.\n",
+ js_FramePCToLineNumber(cx, fp),
+ FramePCOffset(fp),
+ reason);)
+ }
+ Fragment* f = tm->recorder->getFragment();
+ if (!f) {
+ js_DeleteRecorder(cx);
+ return;
+ }
+ JS_ASSERT(!f->vmprivate);
+ js_BlacklistPC(tm->fragmento, f);
+ Fragment* outer = tm->recorder->getOuterToBlacklist();
+ /* Give outer two chances to stabilize before we start blacklisting. */
+ if (outer != NULL && outer->recordAttempts >= 2)
+ js_BlacklistPC(tm->fragmento, outer);
+ js_DeleteRecorder(cx);
+ /* If this is the primary trace and we didn't succeed compiling, trash the TreeInfo object. */
+ if (!f->code() && (f->root == f))
+ js_TrashTree(cx, f);
+}
+
+#if defined NANOJIT_IA32
+static bool
+js_CheckForSSE2()
+{
+ int features = 0;
+#if defined _MSC_VER
+ __asm
+ {
+ pushad
+ mov eax, 1
+ cpuid
+ mov features, edx
+ popad
+ }
+#elif defined __GNUC__
+ asm("xchg %%esi, %%ebx\n" /* we can't clobber ebx on gcc (PIC register) */
+ "mov $0x01, %%eax\n"
+ "cpuid\n"
+ "mov %%edx, %0\n"
+ "xchg %%esi, %%ebx\n"
+ : "=m" (features)
+ : /* We have no inputs */
+ : "%eax", "%esi", "%ecx", "%edx"
+ );
+#elif defined __SUNPRO_C || defined __SUNPRO_CC
+ asm("push %%ebx\n"
+ "mov $0x01, %%eax\n"
+ "cpuid\n"
+ "pop %%ebx\n"
+ : "=d" (features)
+ : /* We have no inputs */
+ : "%eax", "%ecx"
+ );
+#endif
+ return (features & (1<<26)) != 0;
+}
+#endif
+
+static void InitIMacroCode();
+
+extern void
+js_InitJIT(JSTraceMonitor *tm)
+{
+#if defined NANOJIT_IA32
+ if (!did_we_check_sse2) {
+ avmplus::AvmCore::cmov_available =
+ avmplus::AvmCore::sse2_available = js_CheckForSSE2();
+ did_we_check_sse2 = true;
+ }
+#endif
+ if (!tm->fragmento) {
+ JS_ASSERT(!tm->globalSlots && !tm->globalTypeMap && !tm->recoveryDoublePool);
+ Fragmento* fragmento = new (&gc) Fragmento(core, 24);
+ verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
+ tm->fragmento = fragmento;
+ tm->globalSlots = new (&gc) SlotList();
+ tm->globalTypeMap = new (&gc) TypeMap();
+ tm->recoveryDoublePoolPtr = tm->recoveryDoublePool = new jsval[MAX_NATIVE_STACK_SLOTS];
+ }
+ if (!tm->reFragmento) {
+ Fragmento* fragmento = new (&gc) Fragmento(core, 20);
+ verbose_only(fragmento->labels = new (&gc) LabelMap(core, NULL);)
+ tm->reFragmento = fragmento;
+ }
+ InitIMacroCode();
+#if !defined XP_WIN
+ debug_only(memset(&jitstats, 0, sizeof(jitstats)));
+#endif
+}
+
+extern void
+js_FinishJIT(JSTraceMonitor *tm)
+{
+#ifdef JS_JIT_SPEW
+ printf("recorder: started(%llu), aborted(%llu), completed(%llu), different header(%llu), "
+ "trees trashed(%llu), slot promoted(%llu), unstable loop variable(%llu), "
+ "breaks(%llu), returns(%llu), unstableInnerCalls(%llu)\n",
+ jitstats.recorderStarted, jitstats.recorderAborted, jitstats.traceCompleted,
+ jitstats.returnToDifferentLoopHeader, jitstats.treesTrashed, jitstats.slotPromoted,
+ jitstats.unstableLoopVariable, jitstats.breakLoopExits, jitstats.returnLoopExits,
+ jitstats.noCompatInnerTrees);
+ printf("monitor: triggered(%llu), exits(%llu), type mismatch(%llu), "
+ "global mismatch(%llu)\n", jitstats.traceTriggered, jitstats.sideExitIntoInterpreter,
+ jitstats.typeMapMismatchAtEntry, jitstats.globalShapeMismatchAtEntry);
+#endif
+ if (tm->fragmento != NULL) {
+ JS_ASSERT(tm->globalSlots && tm->globalTypeMap && tm->recoveryDoublePool);
+ verbose_only(delete tm->fragmento->labels;)
+ delete tm->fragmento;
+ tm->fragmento = NULL;
+ delete tm->globalSlots;
+ tm->globalSlots = NULL;
+ delete tm->globalTypeMap;
+ tm->globalTypeMap = NULL;
+ delete[] tm->recoveryDoublePool;
+ tm->recoveryDoublePool = tm->recoveryDoublePoolPtr = NULL;
+ }
+ if (tm->reFragmento != NULL) {
+ verbose_only(delete tm->reFragmento->labels;)
+ delete tm->reFragmento;
+ }
+}
+
+void
+TraceRecorder::pushAbortStack()
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ JS_ASSERT(tm->abortStack != this);
+
+ nextRecorderToAbort = tm->abortStack;
+ tm->abortStack = this;
+}
+
+void
+TraceRecorder::popAbortStack()
+{
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+
+ JS_ASSERT(tm->abortStack == this);
+
+ tm->abortStack = nextRecorderToAbort;
+ nextRecorderToAbort = NULL;
+}
+
+extern void
+js_FlushJITOracle(JSContext* cx)
+{
+ if (!TRACING_ENABLED(cx))
+ return;
+ oracle.clear();
+}
+
+extern void
+js_FlushJITCache(JSContext* cx)
+{
+ if (!TRACING_ENABLED(cx))
+ return;
+ debug_only_v(printf("Flushing cache.\n");)
+ JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);
+ if (tm->recorder)
+ js_AbortRecording(cx, "flush cache");
+ TraceRecorder* tr;
+ while ((tr = tm->abortStack) != NULL) {
+ tr->removeFragmentoReferences();
+ tr->deepAbort();
+ tr->popAbortStack();
+ }
+ Fragmento* fragmento = tm->fragmento;
+ if (fragmento) {
+ fragmento->clearFrags();
+#ifdef DEBUG
+ JS_ASSERT(fragmento->labels);
+ delete fragmento->labels;
+ fragmento->labels = new (&gc) LabelMap(core, NULL);
+#endif
+ }
+ if (cx->fp) {
+ tm->globalShape = OBJ_SHAPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain));
+ tm->globalSlots->clear();
+ tm->globalTypeMap->clear();
+ }
+}
+
+jsval&
+TraceRecorder::argval(unsigned n) const
+{
+ JS_ASSERT(n < cx->fp->fun->nargs);
+ return cx->fp->argv[n];
+}
+
+jsval&
+TraceRecorder::varval(unsigned n) const
+{
+ JS_ASSERT(n < cx->fp->script->nslots);
+ return cx->fp->slots[n];
+}
+
+jsval&
+TraceRecorder::stackval(int n) const
+{
+ jsval* sp = cx->fp->regs->sp;
+ return sp[n];
+}
+
+LIns*
+TraceRecorder::scopeChain() const
+{
+ return lir->insLoad(LIR_ldp,
+ lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp)),
+ offsetof(JSStackFrame, scopeChain));
+}
+
+static inline bool
+FrameInRange(JSStackFrame* fp, JSStackFrame *target, unsigned callDepth)
+{
+ while (fp != target) {
+ if (callDepth-- == 0)
+ return false;
+ if (!(fp = fp->down))
+ return false;
+ }
+ return true;
+}
+
+bool
+TraceRecorder::activeCallOrGlobalSlot(JSObject* obj, jsval*& vp)
+{
+ JS_ASSERT(obj != globalObj);
+
+ JSAtom* atom = atoms[GET_INDEX(cx->fp->regs->pc)];
+ JSObject* obj2;
+ JSProperty* prop;
+ if (js_FindProperty(cx, ATOM_TO_JSID(atom), &obj, &obj2, &prop) < 0 || !prop)
+ ABORT_TRACE("failed to find name in non-global scope chain");
+
+ if (obj == globalObj) {
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+ if (obj2 != obj || !SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj))) {
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ ABORT_TRACE("prototype or slotless globalObj property");
+ }
+
+ if (!lazilyImportGlobalSlot(sprop->slot))
+ ABORT_TRACE("lazy import of global slot failed");
+ vp = &STOBJ_GET_SLOT(obj, sprop->slot);
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ return true;
+ }
+
+ if (obj == obj2 && OBJ_GET_CLASS(cx, obj) == &js_CallClass) {
+ JSStackFrame* cfp = (JSStackFrame*) JS_GetPrivate(cx, obj);
+ if (cfp && FrameInRange(cx->fp, cfp, callDepth)) {
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+ uintN slot = sprop->shortid;
+
+ vp = NULL;
+ if (sprop->getter == js_GetCallArg) {
+ JS_ASSERT(slot < cfp->fun->nargs);
+ vp = &cfp->argv[slot];
+ } else if (sprop->getter == js_GetCallVar) {
+ JS_ASSERT(slot < cfp->script->nslots);
+ vp = &cfp->slots[slot];
+ }
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!vp)
+ ABORT_TRACE("dynamic property of Call object");
+ return true;
+ }
+ }
+
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ ABORT_TRACE("fp->scopeChain is not global or active call object");
+}
+
+LIns*
+TraceRecorder::arg(unsigned n)
+{
+ return get(&argval(n));
+}
+
+void
+TraceRecorder::arg(unsigned n, LIns* i)
+{
+ set(&argval(n), i);
+}
+
+LIns*
+TraceRecorder::var(unsigned n)
+{
+ return get(&varval(n));
+}
+
+void
+TraceRecorder::var(unsigned n, LIns* i)
+{
+ set(&varval(n), i);
+}
+
+LIns*
+TraceRecorder::stack(int n)
+{
+ return get(&stackval(n));
+}
+
+void
+TraceRecorder::stack(int n, LIns* i)
+{
+ set(&stackval(n), i, n >= 0);
+}
+
+LIns*
+TraceRecorder::alu(LOpcode v, jsdouble v0, jsdouble v1, LIns* s0, LIns* s1)
+{
+ if (v == LIR_fadd || v == LIR_fsub) {
+ jsdouble r;
+ if (v == LIR_fadd)
+ r = v0 + v1;
+ else
+ r = v0 - v1;
+ /*
+ * Calculate the result of the addition for the current values. If the
+ * value is not within the integer range, don't even try to demote
+ * here.
+ */
+ if (!JSDOUBLE_IS_NEGZERO(r) && (jsint(r) == r) && isPromoteInt(s0) && isPromoteInt(s1)) {
+ LIns* d0 = ::demote(lir, s0);
+ LIns* d1 = ::demote(lir, s1);
+ /*
+ * If the inputs are constant, generate an integer constant for
+ * this operation.
+ */
+ if (d0->isconst() && d1->isconst())
+ return lir->ins1(LIR_i2f, lir->insImm(jsint(r)));
+ /*
+ * Speculatively generate code that will perform the addition over
+ * the integer inputs as an integer addition/subtraction and exit
+ * if that fails.
+ */
+ v = (LOpcode)((int)v & ~LIR64);
+ LIns* result = lir->ins2(v, d0, d1);
+ if (!overflowSafe(d0) || !overflowSafe(d1)) {
+ lir->insGuard(LIR_xt, lir->ins1(LIR_ov, result),
+ snapshot(OVERFLOW_EXIT));
+ }
+ return lir->ins1(LIR_i2f, result);
+ }
+ /*
+ * The result doesn't fit into the integer domain, so either generate
+ * a floating point constant or a floating point operation.
+ */
+ if (s0->isconst() && s1->isconst()) {
+ jsdpun u;
+ u.d = r;
+ return lir->insImmq(u.u64);
+ }
+ return lir->ins2(v, s0, s1);
+ }
+ return lir->ins2(v, s0, s1);
+}
+
+LIns*
+TraceRecorder::f2i(LIns* f)
+{
+ return lir->insCall(&js_DoubleToInt32_ci, &f);
+}
+
+LIns*
+TraceRecorder::makeNumberInt32(LIns* f)
+{
+ JS_ASSERT(f->isQuad());
+ LIns* x;
+ if (!isPromote(f)) {
+ x = f2i(f);
+ guard(true, lir->ins2(LIR_feq, f, lir->ins1(LIR_i2f, x)), MISMATCH_EXIT);
+ } else {
+ x = ::demote(lir, f);
+ }
+ return x;
+}
+
+LIns*
+TraceRecorder::stringify(jsval& v)
+{
+ LIns* v_ins = get(&v);
+ if (JSVAL_IS_STRING(v))
+ return v_ins;
+
+ LIns* args[] = { v_ins, cx_ins };
+ const CallInfo* ci;
+ if (JSVAL_IS_NUMBER(v)) {
+ ci = &js_NumberToString_ci;
+ } else if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ ci = &js_BooleanOrUndefinedToString_ci;
+ } else {
+ /* We can't stringify objects here (use imacros instead), just return NULL. */
+ return NULL;
+ }
+ v_ins = lir->insCall(ci, args);
+ guard(false, lir->ins_eq0(v_ins), OOM_EXIT);
+ return v_ins;
+}
+
+bool
+TraceRecorder::call_imacro(jsbytecode* imacro)
+{
+ JSStackFrame* fp = cx->fp;
+ JSFrameRegs* regs = fp->regs;
+
+ if (!fp->imacpc) {
+ fp->imacpc = regs->pc;
+ fp->flags |= JSFRAME_IMACRO_START;
+ regs->pc = imacro;
+ atoms = COMMON_ATOMS_START(&cx->runtime->atomState);
+ }
+ return false;
+}
+
+bool
+TraceRecorder::ifop()
+{
+ jsval& v = stackval(-1);
+ LIns* v_ins = get(&v);
+ bool cond;
+ LIns* x;
+ /* no need to guard if condition is constant */
+ if (v_ins->isconst() || v_ins->isconstq())
+ return true;
+ if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ /* test for boolean is true, negate later if we are testing for false */
+ cond = JSVAL_TO_BOOLEAN(v) == 1;
+ x = lir->ins2i(LIR_eq, v_ins, 1);
+ } else if (JSVAL_IS_OBJECT(v)) {
+ cond = !JSVAL_IS_NULL(v);
+ x = v_ins;
+ } else if (isNumber(v)) {
+ jsdouble d = asNumber(v);
+ cond = !JSDOUBLE_IS_NaN(d) && d;
+ jsdpun u;
+ u.d = 0;
+ x = lir->ins2(LIR_and,
+ lir->ins2(LIR_feq, v_ins, v_ins),
+ lir->ins_eq0(lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64))));
+ } else if (JSVAL_IS_STRING(v)) {
+ cond = JSSTRING_LENGTH(JSVAL_TO_STRING(v)) != 0;
+ x = lir->ins2(LIR_piand,
+ lir->insLoad(LIR_ldp,
+ v_ins,
+ (int)offsetof(JSString, length)),
+ INS_CONSTPTR(JSSTRING_LENGTH_MASK));
+ } else {
+ JS_NOT_REACHED("ifop");
+ return false;
+ }
+ flipIf(cx->fp->regs->pc, cond);
+ bool expected = cond;
+ if (!x->isCond()) {
+ x = lir->ins_eq0(x);
+ expected = !expected;
+ }
+ guard(expected, x, BRANCH_EXIT);
+ return true;
+}
+
+bool
+TraceRecorder::switchop()
+{
+ jsval& v = stackval(-1);
+ LIns* v_ins = get(&v);
+ /* no need to guard if condition is constant */
+ if (v_ins->isconst() || v_ins->isconstq())
+ return true;
+ if (isNumber(v)) {
+ jsdouble d = asNumber(v);
+ jsdpun u;
+ u.d = d;
+ guard(true,
+ addName(lir->ins2(LIR_feq, v_ins, lir->insImmq(u.u64)),
+ "guard(switch on numeric)"),
+ BRANCH_EXIT);
+ } else if (JSVAL_IS_STRING(v)) {
+ LIns* args[] = { v_ins, INS_CONSTPTR(JSVAL_TO_STRING(v)) };
+ guard(true,
+ addName(lir->ins_eq0(lir->ins_eq0(lir->insCall(&js_EqualStrings_ci, args))),
+ "guard(switch on string)"),
+ BRANCH_EXIT);
+ } else if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ guard(true,
+ addName(lir->ins2(LIR_eq, v_ins, lir->insImm(JSVAL_TO_BOOLEAN(v))),
+ "guard(switch on boolean)"),
+ BRANCH_EXIT);
+ } else {
+ ABORT_TRACE("switch on object or null");
+ }
+ return true;
+}
+
+bool
+TraceRecorder::inc(jsval& v, jsint incr, bool pre)
+{
+ LIns* v_ins = get(&v);
+ if (!inc(v, v_ins, incr, pre))
+ return false;
+ set(&v, v_ins);
+ return true;
+}
+
+/*
+ * On exit, v_ins is the incremented unboxed value, and the appropriate
+ * value (pre- or post-increment as described by pre) is stacked.
+ */
+bool
+TraceRecorder::inc(jsval& v, LIns*& v_ins, jsint incr, bool pre)
+{
+ if (!isNumber(v))
+ ABORT_TRACE("can only inc numbers");
+
+ jsdpun u;
+ u.d = jsdouble(incr);
+
+ LIns* v_after = alu(LIR_fadd, asNumber(v), incr, v_ins, lir->insImmq(u.u64));
+
+ const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, pre ? v_after : v_ins);
+ v_ins = v_after;
+ return true;
+}
+
+bool
+TraceRecorder::incProp(jsint incr, bool pre)
+{
+ jsval& l = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(l))
+ ABORT_TRACE("incProp on primitive");
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ LIns* obj_ins = get(&l);
+
+ uint32 slot;
+ LIns* v_ins;
+ if (!prop(obj, obj_ins, slot, v_ins))
+ return false;
+
+ if (slot == SPROP_INVALID_SLOT)
+ ABORT_TRACE("incProp on invalid slot");
+
+ jsval& v = STOBJ_GET_SLOT(obj, slot);
+ if (!inc(v, v_ins, incr, pre))
+ return false;
+
+ if (!box_jsval(v, v_ins))
+ return false;
+
+ LIns* dslots_ins = NULL;
+ stobj_set_slot(obj_ins, slot, dslots_ins, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::incElem(jsint incr, bool pre)
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+ jsval* vp;
+ LIns* v_ins;
+ LIns* addr_ins;
+ if (!elem(l, r, vp, v_ins, addr_ins))
+ return false;
+ if (!addr_ins) // if we read a hole, abort
+ return false;
+ if (!inc(*vp, v_ins, incr, pre))
+ return false;
+ if (!box_jsval(*vp, v_ins))
+ return false;
+ lir->insStorei(v_ins, addr_ins, 0);
+ return true;
+}
+
+static bool
+evalCmp(LOpcode op, double result)
+{
+ bool cond;
+ switch (op) {
+ case LIR_feq:
+ cond = (result == 0);
+ break;
+ case LIR_flt:
+ cond = result < 0;
+ break;
+ case LIR_fgt:
+ cond = result > 0;
+ break;
+ case LIR_fle:
+ cond = result <= 0;
+ break;
+ case LIR_fge:
+ cond = result >= 0;
+ break;
+ default:
+ JS_NOT_REACHED("unexpected comparison op");
+ return false;
+ }
+ return cond;
+}
+
+static bool
+evalCmp(LOpcode op, double l, double r)
+{
+ return evalCmp(op, l - r);
+}
+
+static bool
+evalCmp(LOpcode op, JSString* l, JSString* r)
+{
+ if (op == LIR_feq)
+ return js_EqualStrings(l, r);
+ return evalCmp(op, js_CompareStrings(l, r));
+}
+
+static struct {
+ jsbytecode obj_any[13];
+ jsbytecode any_obj[11];
+ jsbytecode obj_obj[22];
+} binary_imacros = {
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_SWAP,
+ JSOP_IMACOP,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_IMACOP,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(valueOf),
+ JSOP_STRING, 0, COMMON_TYPE_ATOM_INDEX(JSTYPE_NUMBER),
+ JSOP_CALL, 0, 1,
+ JSOP_IMACOP,
+ JSOP_STOP
+ }
+};
+
+JS_STATIC_ASSERT(sizeof(binary_imacros) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::cmp(LOpcode op, int flags)
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+ LIns* x = NULL;
+ bool negate = !!(flags & CMP_NEGATE);
+ bool cond;
+ LIns* l_ins = get(&l);
+ LIns* r_ins = get(&r);
+ bool fp = false;
+
+ if (op != LIR_feq) {
+ if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.obj_obj);
+ return call_imacro(binary_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.any_obj);
+ }
+
+ // CMP_STRICT is set only for JSOP_STRICTEQ and JSOP_STRICTNE, which correspond to the
+ // === and !== operators. negate is true for !== and false for ===. The strict equality
+ // operators produce false if the types of the operands differ, i.e. if only one of
+ // them is a number.
+ if ((flags & CMP_STRICT) && getPromotedType(l) != getPromotedType(r)) {
+ x = INS_CONST(negate);
+ cond = negate;
+ } else if (JSVAL_IS_STRING(l) || JSVAL_IS_STRING(r)) {
+ // Comparing equality of a string against null always produces false.
+ if (op == LIR_feq &&
+ ((JSVAL_IS_NULL(l) && l_ins->isconst()) ||
+ (JSVAL_IS_NULL(r) && r_ins->isconst()))) {
+ x = INS_CONST(negate);
+ cond = negate;
+ } else {
+ if (!JSVAL_IS_STRING(l) || !JSVAL_IS_STRING(r))
+ ABORT_TRACE("unsupported type for cmp vs string");
+
+ LIns* args[] = { r_ins, l_ins };
+ if (op == LIR_feq)
+ l_ins = lir->ins_eq0(lir->insCall(&js_EqualStrings_ci, args));
+ else
+ l_ins = lir->insCall(&js_CompareStrings_ci, args);
+ r_ins = lir->insImm(0);
+ cond = evalCmp(op, JSVAL_TO_STRING(l), JSVAL_TO_STRING(r));
+ }
+ } else if (isNumber(l) || isNumber(r)) {
+ jsval tmp[2] = {l, r};
+ JSAutoTempValueRooter tvr(cx, 2, tmp);
+
+ fp = true;
+
+ // TODO: coerce non-numbers to numbers if it's not string-on-string above
+ jsdouble lnum;
+ jsdouble rnum;
+ LIns* args[] = { l_ins, cx_ins };
+ if (l == JSVAL_NULL && l_ins->isconst()) {
+ jsdpun u;
+ u.d = (op == LIR_feq) ? js_NaN : 0.0;
+ l_ins = lir->insImmq(u.u64);
+ } else if (JSVAL_IS_STRING(l)) {
+ l_ins = lir->insCall(&js_StringToNumber_ci, args);
+ } else if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
+ /*
+ * What I really want here is for undefined to be type-specialized
+ * differently from real booleans. Failing that, I want to be able
+ * to cmov on quads. Failing that, I want to have small forward
+ * branches. Failing that, I want to be able to ins_choose on quads
+ * without cmov. Failing that, eat flaming builtin!
+ */
+ l_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ } else if (!isNumber(l)) {
+ ABORT_TRACE("unsupported LHS type for cmp vs number");
+ }
+ lnum = js_ValueToNumber(cx, &tmp[0]);
+
+ args[0] = r_ins;
+ args[1] = cx_ins;
+ if (r == JSVAL_NULL && r_ins->isconst()) {
+ jsdpun u;
+ u.d = (op == LIR_feq) ? js_NaN : 0.0;
+ r_ins = lir->insImmq(u.u64);
+ } else if (JSVAL_IS_STRING(r)) {
+ r_ins = lir->insCall(&js_StringToNumber_ci, args);
+ } else if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
+ // See above for the sob story.
+ r_ins = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ } else if (!isNumber(r)) {
+ ABORT_TRACE("unsupported RHS type for cmp vs number");
+ }
+ rnum = js_ValueToNumber(cx, &tmp[1]);
+ cond = evalCmp(op, lnum, rnum);
+ } else if ((JSVAL_TAG(l) == JSVAL_BOOLEAN) && (JSVAL_TAG(r) == JSVAL_BOOLEAN)) {
+ // The well-known values of JSVAL_TRUE and JSVAL_FALSE make this very easy.
+ // In particular: JSVAL_TO_BOOLEAN(0) < JSVAL_TO_BOOLEAN(1) so all of these comparisons do
+ // the right thing.
+ cond = evalCmp(op, l, r);
+ // For ==, !=, ===, and !=== the result is magically correct even if undefined (2) is
+ // involved. For the relational operations we need some additional cmov magic to make
+ // the result always false (since undefined becomes NaN per ECMA and that doesn't
+ // compare to anything, even itself). The code for this is emitted a few lines down.
+ } else if (JSVAL_IS_OBJECT(l) && JSVAL_IS_OBJECT(r)) {
+ if (op != LIR_feq) {
+ JS_NOT_REACHED("we should have converted to numbers already");
+ return false;
+ }
+ cond = (l == r);
+ } else {
+ ABORT_TRACE("unsupported operand types for cmp");
+ }
+
+ /* If we didn't generate a constant result yet, then emit the comparison now. */
+ if (!x) {
+ /* If the result is not a number or it's not a quad, we must use an integer compare. */
+ if (!fp) {
+ JS_ASSERT(op >= LIR_feq && op <= LIR_fge);
+ op = LOpcode(op + (LIR_eq - LIR_feq));
+ }
+ x = lir->ins2(op, l_ins, r_ins);
+ if (negate) {
+ x = lir->ins_eq0(x);
+ cond = !cond;
+ }
+ // For boolean comparison we need a bit post-processing to make the result false if
+ // either side is undefined.
+ if (op != LIR_eq && (JSVAL_TAG(l) == JSVAL_BOOLEAN) && (JSVAL_TAG(r) == JSVAL_BOOLEAN)) {
+ x = lir->ins_choose(lir->ins2i(LIR_eq,
+ lir->ins2i(LIR_and,
+ lir->ins2(LIR_or, l_ins, r_ins),
+ JSVAL_TO_BOOLEAN(JSVAL_VOID)),
+ JSVAL_TO_BOOLEAN(JSVAL_VOID)),
+ lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_FALSE)),
+ x);
+ x = lir->ins_eq0(lir->ins_eq0(x));
+ if ((l == JSVAL_VOID) || (r == JSVAL_VOID))
+ cond = false;
+ }
+ }
+
+ /* Don't guard if the same path is always taken. */
+ if (!x->isconst()) {
+ if (flags & CMP_CASE) {
+ guard(cond, x, BRANCH_EXIT);
+ return true;
+ }
+
+ /* The interpreter fuses comparisons and the following branch,
+ so we have to do that here as well. */
+ if (flags & CMP_TRY_BRANCH_AFTER_COND) {
+ fuseIf(cx->fp->regs->pc + 1, cond, x);
+ }
+ } else if (flags & CMP_CASE) {
+ return true;
+ }
+
+ /* We update the stack after the guard. This is safe since
+ the guard bails out at the comparison and the interpreter
+ will therefore re-execute the comparison. This way the
+ value of the condition doesn't have to be calculated and
+ saved on the stack in most cases. */
+ set(&l, x);
+ return true;
+}
+
+bool
+TraceRecorder::unary(LOpcode op)
+{
+ jsval& v = stackval(-1);
+ bool intop = !(op & LIR64);
+ if (isNumber(v)) {
+ LIns* a = get(&v);
+ if (intop)
+ a = f2i(a);
+ a = lir->ins1(op, a);
+ if (intop)
+ a = lir->ins1(LIR_i2f, a);
+ set(&v, a);
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::binary(LOpcode op)
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.obj_obj);
+ return call_imacro(binary_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.any_obj);
+
+ bool intop = !(op & LIR64);
+ LIns* a = get(&l);
+ LIns* b = get(&r);
+
+ bool leftIsNumber = isNumber(l);
+ jsdouble lnum = leftIsNumber ? asNumber(l) : 0;
+
+ bool rightIsNumber = isNumber(r);
+ jsdouble rnum = rightIsNumber ? asNumber(r) : 0;
+
+ if ((op >= LIR_sub && op <= LIR_ush) || // sub, mul, (callh), or, xor, (not,) lsh, rsh, ush
+ (op >= LIR_fsub && op <= LIR_fdiv)) { // fsub, fmul, fdiv
+ LIns* args[2];
+ if (JSVAL_IS_STRING(l)) {
+ args[0] = a;
+ args[1] = cx_ins;
+ a = lir->insCall(&js_StringToNumber_ci, args);
+ lnum = js_StringToNumber(cx, JSVAL_TO_STRING(l));
+ leftIsNumber = true;
+ }
+ if (JSVAL_IS_STRING(r)) {
+ args[0] = b;
+ args[1] = cx_ins;
+ b = lir->insCall(&js_StringToNumber_ci, args);
+ rnum = js_StringToNumber(cx, JSVAL_TO_STRING(r));
+ rightIsNumber = true;
+ }
+ }
+ if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
+ LIns* args[] = { a, cx_ins };
+ a = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ lnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_BOOLEAN(l));
+ leftIsNumber = true;
+ }
+ if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
+ LIns* args[] = { b, cx_ins };
+ b = lir->insCall(&js_BooleanOrUndefinedToNumber_ci, args);
+ rnum = js_BooleanOrUndefinedToNumber(cx, JSVAL_TO_BOOLEAN(r));
+ rightIsNumber = true;
+ }
+ if (leftIsNumber && rightIsNumber) {
+ if (intop) {
+ LIns *args[] = { a };
+ a = lir->insCall(op == LIR_ush ? &js_DoubleToUint32_ci : &js_DoubleToInt32_ci, args);
+ b = f2i(b);
+ }
+ a = alu(op, lnum, rnum, a, b);
+ if (intop)
+ a = lir->ins1(op == LIR_ush ? LIR_u2f : LIR_i2f, a);
+ set(&l, a);
+ return true;
+ }
+ return false;
+}
+
+JS_STATIC_ASSERT(offsetof(JSObjectOps, newObjectMap) == 0);
+
+bool
+TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins, LIns*& ops_ins, size_t op_offset)
+{
+ ops_ins = addName(lir->insLoad(LIR_ldp, map_ins, offsetof(JSObjectMap, ops)), "ops");
+ LIns* n = lir->insLoad(LIR_ldp, ops_ins, op_offset);
+
+#define OP(ops) (*(JSObjectOp*) ((char*)(ops) + op_offset))
+
+ if (OP(map->ops) == OP(&js_ObjectOps)) {
+ guard(true, addName(lir->ins2(LIR_eq, n, INS_CONSTPTR(OP(&js_ObjectOps))),
+ "guard(native-map)"),
+ MISMATCH_EXIT);
+ return true;
+ }
+
+#undef OP
+ ABORT_TRACE("non-native map");
+}
+
+bool
+TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2, jsuword& pcval)
+{
+ jsbytecode* pc = cx->fp->regs->pc;
+ JS_ASSERT(*pc != JSOP_INITPROP && *pc != JSOP_SETNAME && *pc != JSOP_SETPROP);
+
+ // Mimic the interpreter's special case for dense arrays by skipping up one
+ // hop along the proto chain when accessing a named (not indexed) property,
+ // typically to find Array.prototype methods.
+ JSObject* aobj = obj;
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ aobj = OBJ_GET_PROTO(cx, obj);
+ obj_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
+ }
+
+ LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
+ LIns* ops_ins;
+
+ // Interpreter calls to PROPERTY_CACHE_TEST guard on native object ops
+ // (newObjectMap == js_ObjectOps.newObjectMap) which is required to use
+ // native objects (those whose maps are scopes), or even more narrow
+ // conditions required because the cache miss case will call a particular
+ // object-op (js_GetProperty, js_SetProperty).
+ //
+ // We parameterize using offsetof and guard on match against the hook at
+ // the given offset in js_ObjectOps. TraceRecorder::record_JSOP_SETPROP
+ // guards the js_SetProperty case.
+ uint32 format = js_CodeSpec[*pc].format;
+ uint32 mode = JOF_MODE(format);
+
+ // No need to guard native-ness of global object.
+ JS_ASSERT(OBJ_IS_NATIVE(globalObj));
+ if (aobj != globalObj) {
+ size_t op_offset = 0;
+ if (mode == JOF_PROP || mode == JOF_VARPROP) {
+ JS_ASSERT(!(format & JOF_SET));
+ op_offset = offsetof(JSObjectOps, getProperty);
+ } else {
+ JS_ASSERT(mode == JOF_NAME);
+ }
+
+ if (!map_is_native(aobj->map, map_ins, ops_ins, op_offset))
+ return false;
+ }
+
+ JSAtom* atom;
+ JSPropCacheEntry* entry;
+ PROPERTY_CACHE_TEST(cx, pc, aobj, obj2, entry, atom);
+ if (atom) {
+ // Miss: pre-fill the cache for the interpreter, as well as for our needs.
+ // FIXME: 452357 - correctly propagate exceptions into the interpreter from
+ // js_FindPropertyHelper, js_LookupPropertyWithFlags, and elsewhere.
+ jsid id = ATOM_TO_JSID(atom);
+ JSProperty* prop;
+ if (JOF_OPMODE(*pc) == JOF_NAME) {
+ JS_ASSERT(aobj == obj);
+ if (js_FindPropertyHelper(cx, id, &obj, &obj2, &prop, &entry) < 0)
+ ABORT_TRACE("failed to find name");
+ } else {
+ int protoIndex = js_LookupPropertyWithFlags(cx, aobj, id,
+ cx->resolveFlags,
+ &obj2, &prop);
+ if (protoIndex < 0)
+ ABORT_TRACE("failed to lookup property");
+
+ if (prop) {
+ js_FillPropertyCache(cx, aobj, OBJ_SHAPE(aobj), 0, protoIndex, obj2,
+ (JSScopeProperty*) prop, &entry);
+ }
+ }
+
+ if (!prop) {
+ // Propagate obj from js_FindPropertyHelper to record_JSOP_BINDNAME
+ // via our obj2 out-parameter. If we are recording JSOP_SETNAME and
+ // the global it's assigning does not yet exist, create it.
+ obj2 = obj;
+
+ // Use PCVAL_NULL to return "no such property" to our caller.
+ pcval = PCVAL_NULL;
+ ABORT_TRACE("failed to find property");
+ }
+
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+ if (!entry)
+ ABORT_TRACE("failed to fill property cache");
+ }
+
+#ifdef JS_THREADSAFE
+ // There's a potential race in any JS_THREADSAFE embedding that's nuts
+ // enough to share mutable objects on the scope or proto chain, but we
+ // don't care about such insane embeddings. Anyway, the (scope, proto)
+ // entry->vcap coordinates must reach obj2 from aobj at this point.
+ JS_ASSERT(cx->requestDepth);
+#endif
+
+ // Emit guard(s), common code for both hit and miss cases.
+ // Check for first-level cache hit and guard on kshape if possible.
+ // Otherwise guard on key object exact match.
+ if (PCVCAP_TAG(entry->vcap) <= 1) {
+ if (aobj != globalObj) {
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
+ "shape");
+ guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)"),
+ MISMATCH_EXIT);
+ }
+ } else {
+#ifdef DEBUG
+ JSOp op = JSOp(*pc);
+ ptrdiff_t pcoff = (op == JSOP_GETARGPROP) ? ARGNO_LEN :
+ (op == JSOP_GETLOCALPROP) ? SLOTNO_LEN : 0;
+ jsatomid index = js_GetIndexFromBytecode(cx, cx->fp->script, pc, pcoff);
+ JS_ASSERT(entry->kpc == (jsbytecode*) atoms[index]);
+ JS_ASSERT(entry->kshape == jsuword(aobj));
+#endif
+ if (aobj != globalObj) {
+ guard(true, addName(lir->ins2i(LIR_eq, obj_ins, entry->kshape), "guard(kobj)"),
+ MISMATCH_EXIT);
+ }
+ }
+
+ // For any hit that goes up the scope and/or proto chains, we will need to
+ // guard on the shape of the object containing the property.
+ if (PCVCAP_TAG(entry->vcap) >= 1) {
+ jsuword vcap = entry->vcap;
+ uint32 vshape = PCVCAP_SHAPE(vcap);
+ JS_ASSERT(OBJ_SHAPE(obj2) == vshape);
+
+ LIns* obj2_ins;
+ if (PCVCAP_TAG(entry->vcap) == 1) {
+ // Duplicate the special case in PROPERTY_CACHE_TEST.
+ obj2_ins = stobj_get_fslot(obj_ins, JSSLOT_PROTO);
+ guard(false, lir->ins_eq0(obj2_ins), MISMATCH_EXIT);
+ } else {
+ obj2_ins = INS_CONSTPTR(obj2);
+ }
+ map_ins = lir->insLoad(LIR_ldp, obj2_ins, (int)offsetof(JSObject, map));
+ if (!map_is_native(obj2->map, map_ins, ops_ins))
+ return false;
+
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
+ "shape");
+ guard(true,
+ addName(lir->ins2i(LIR_eq, shape_ins, vshape), "guard(vshape)"),
+ MISMATCH_EXIT);
+ }
+
+ pcval = entry->vword;
+ return true;
+}
+
+bool
+TraceRecorder::test_property_cache_direct_slot(JSObject* obj, LIns* obj_ins, uint32& slot)
+{
+ JSObject* obj2;
+ jsuword pcval;
+
+ /*
+ * Property cache ensures that we are dealing with an existing property,
+ * and guards the shape for us.
+ */
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ /* No such property means invalid slot, which callers must check for first. */
+ if (PCVAL_IS_NULL(pcval)) {
+ slot = SPROP_INVALID_SLOT;
+ return true;
+ }
+
+ /* Insist on obj being the directly addressed object. */
+ if (obj2 != obj)
+ ABORT_TRACE("test_property_cache_direct_slot hit prototype chain");
+
+ /* Don't trace getter or setter calls, our caller wants a direct slot. */
+ if (PCVAL_IS_SPROP(pcval)) {
+ JSScopeProperty* sprop = PCVAL_TO_SPROP(pcval);
+
+ uint32 setflags = (js_CodeSpec[*cx->fp->regs->pc].format & (JOF_SET | JOF_INCDEC));
+ if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
+ ABORT_TRACE("non-stub setter");
+ if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop))
+ ABORT_TRACE("non-stub getter");
+ if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)))
+ ABORT_TRACE("no valid slot");
+ slot = sprop->slot;
+ } else {
+ if (!PCVAL_IS_SLOT(pcval))
+ ABORT_TRACE("PCE is not a slot");
+ slot = PCVAL_TO_SLOT(pcval);
+ }
+ return true;
+}
+
+void
+TraceRecorder::stobj_set_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins, LIns* v_ins)
+{
+ if (slot < JS_INITIAL_NSLOTS) {
+ addName(lir->insStorei(v_ins, obj_ins,
+ offsetof(JSObject, fslots) + slot * sizeof(jsval)),
+ "set_slot(fslots)");
+ } else {
+ if (!dslots_ins)
+ dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
+ addName(lir->insStorei(v_ins, dslots_ins,
+ (slot - JS_INITIAL_NSLOTS) * sizeof(jsval)),
+ "set_slot(dslots");
+ }
+}
+
+LIns*
+TraceRecorder::stobj_get_fslot(LIns* obj_ins, unsigned slot)
+{
+ JS_ASSERT(slot < JS_INITIAL_NSLOTS);
+ return lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, fslots) + slot * sizeof(jsval));
+}
+
+LIns*
+TraceRecorder::stobj_get_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins)
+{
+ if (slot < JS_INITIAL_NSLOTS)
+ return stobj_get_fslot(obj_ins, slot);
+
+ if (!dslots_ins)
+ dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
+ return lir->insLoad(LIR_ldp, dslots_ins, (slot - JS_INITIAL_NSLOTS) * sizeof(jsval));
+}
+
+bool
+TraceRecorder::native_set(LIns* obj_ins, JSScopeProperty* sprop, LIns*& dslots_ins, LIns* v_ins)
+{
+ if (SPROP_HAS_STUB_SETTER(sprop) && sprop->slot != SPROP_INVALID_SLOT) {
+ stobj_set_slot(obj_ins, sprop->slot, dslots_ins, v_ins);
+ return true;
+ }
+ ABORT_TRACE("unallocated or non-stub sprop");
+}
+
+bool
+TraceRecorder::native_get(LIns* obj_ins, LIns* pobj_ins, JSScopeProperty* sprop,
+ LIns*& dslots_ins, LIns*& v_ins)
+{
+ if (!SPROP_HAS_STUB_GETTER(sprop))
+ return false;
+
+ if (sprop->slot != SPROP_INVALID_SLOT)
+ v_ins = stobj_get_slot(pobj_ins, sprop->slot, dslots_ins);
+ else
+ v_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ return true;
+}
+
+// So box_jsval can emit no LIR_or at all to tag an object jsval.
+JS_STATIC_ASSERT(JSVAL_OBJECT == 0);
+
+bool
+TraceRecorder::box_jsval(jsval v, LIns*& v_ins)
+{
+ if (isNumber(v)) {
+ LIns* args[] = { v_ins, cx_ins };
+ v_ins = lir->insCall(&js_BoxDouble_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)),
+ OOM_EXIT);
+ return true;
+ }
+ switch (JSVAL_TAG(v)) {
+ case JSVAL_BOOLEAN:
+ v_ins = lir->ins2i(LIR_pior, lir->ins2i(LIR_pilsh, v_ins, JSVAL_TAGBITS), JSVAL_BOOLEAN);
+ return true;
+ case JSVAL_OBJECT:
+ return true;
+ case JSVAL_STRING:
+ v_ins = lir->ins2(LIR_pior, v_ins, INS_CONST(JSVAL_STRING));
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::unbox_jsval(jsval v, LIns*& v_ins)
+{
+ if (isNumber(v)) {
+ // JSVAL_IS_NUMBER(v)
+ guard(false,
+ lir->ins_eq0(lir->ins2(LIR_pior,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_INT)),
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins,
+ INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_DOUBLE))),
+ MISMATCH_EXIT);
+ LIns* args[] = { v_ins };
+ v_ins = lir->insCall(&js_UnboxDouble_ci, args);
+ return true;
+ }
+ switch (JSVAL_TAG(v)) {
+ case JSVAL_BOOLEAN:
+ guard(true,
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_BOOLEAN),
+ MISMATCH_EXIT);
+ v_ins = lir->ins2i(LIR_ush, v_ins, JSVAL_TAGBITS);
+ return true;
+ case JSVAL_OBJECT:
+ guard(true,
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_OBJECT),
+ MISMATCH_EXIT);
+ return true;
+ case JSVAL_STRING:
+ guard(true,
+ lir->ins2i(LIR_eq,
+ lir->ins2(LIR_piand, v_ins, INS_CONST(JSVAL_TAGMASK)),
+ JSVAL_STRING),
+ MISMATCH_EXIT);
+ v_ins = lir->ins2(LIR_piand, v_ins, INS_CONST(~JSVAL_TAGMASK));
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::getThis(LIns*& this_ins)
+{
+ if (cx->fp->callee) { /* in a function */
+ if (JSVAL_IS_NULL(cx->fp->argv[-1]))
+ return false;
+ this_ins = get(&cx->fp->argv[-1]);
+ guard(false, lir->ins_eq0(this_ins), MISMATCH_EXIT);
+ } else { /* in global code */
+ this_ins = scopeChain();
+ }
+ return true;
+}
+
+bool
+TraceRecorder::guardClass(JSObject* obj, LIns* obj_ins, JSClass* clasp, ExitType exitType)
+{
+ bool cond = STOBJ_GET_CLASS(obj) == clasp;
+
+ LIns* class_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, classword));
+ class_ins = lir->ins2(LIR_piand, class_ins, lir->insImm(~3));
+
+ char namebuf[32];
+ JS_snprintf(namebuf, sizeof namebuf, "guard(class is %s)", clasp->name);
+ guard(cond, addName(lir->ins2(LIR_eq, class_ins, INS_CONSTPTR(clasp)), namebuf), exitType);
+ return cond;
+}
+
+bool
+TraceRecorder::guardDenseArray(JSObject* obj, LIns* obj_ins, ExitType exitType)
+{
+ return guardClass(obj, obj_ins, &js_ArrayClass, exitType);
+}
+
+bool
+TraceRecorder::guardDenseArrayIndex(JSObject* obj, jsint idx, LIns* obj_ins,
+ LIns* dslots_ins, LIns* idx_ins, ExitType exitType)
+{
+ jsuint length = ARRAY_DENSE_LENGTH(obj);
+
+ bool cond = (jsuint(idx) < jsuint(obj->fslots[JSSLOT_ARRAY_LENGTH]) && jsuint(idx) < length);
+ if (cond) {
+ /* Guard array length */
+ LIns* exit = guard(true,
+ lir->ins2(LIR_ult, idx_ins, stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)),
+ exitType)->oprnd2();
+ /* dslots must not be NULL */
+ guard(false,
+ lir->ins_eq0(dslots_ins),
+ exit);
+ /* Guard array capacity */
+ guard(true,
+ lir->ins2(LIR_ult,
+ idx_ins,
+ lir->insLoad(LIR_ldp, dslots_ins, 0 - (int)sizeof(jsval))),
+ exit);
+ } else {
+ /* If not idx < length, stay on trace (and read value as undefined). */
+ LIns* br1 = lir->insBranch(LIR_jf,
+ lir->ins2(LIR_ult,
+ idx_ins,
+ stobj_get_fslot(obj_ins, JSSLOT_ARRAY_LENGTH)),
+ NULL);
+ /* If dslots is NULL, stay on trace (and read value as undefined). */
+ LIns* br2 = lir->insBranch(LIR_jt, lir->ins_eq0(dslots_ins), NULL);
+ /* If not idx < capacity, stay on trace (and read value as undefined). */
+ LIns* br3 = lir->insBranch(LIR_jf,
+ lir->ins2(LIR_ult,
+ idx_ins,
+ lir->insLoad(LIR_ldp, dslots_ins, 0 - (int)sizeof(jsval))),
+ NULL);
+ lir->insGuard(LIR_x, lir->insImm(1), snapshot(exitType));
+ LIns* label = lir->ins0(LIR_label);
+ br1->target(label);
+ br2->target(label);
+ br3->target(label);
+ }
+ return cond;
+}
+
+/*
+ * Guard that a computed property access via an element op (JSOP_GETELEM, etc.)
+ * does not find an alias to a global variable, or a property without a slot,
+ * or a slot-ful property with a getter or setter (depending on op_offset in
+ * JSObjectOps). Finally, beware resolve hooks mutating objects. Oh, and watch
+ * out for bears too ;-).
+ *
+ * One win here is that we do not need to generate a guard that obj_ins does
+ * not result in the global object on trace, because we guard on shape and rule
+ * out obj's shape being the global object's shape at recording time. This is
+ * safe because the global shape cannot change on trace.
+ */
+bool
+TraceRecorder::guardElemOp(JSObject* obj, LIns* obj_ins, jsid id, size_t op_offset, jsval* vp)
+{
+ LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
+ LIns* ops_ins;
+ if (!map_is_native(obj->map, map_ins, ops_ins, op_offset))
+ return false;
+
+ uint32 shape = OBJ_SHAPE(obj);
+ if (JSID_IS_ATOM(id) && shape == traceMonitor->globalShape)
+ ABORT_TRACE("elem op probably aliases global");
+
+ JSObject* pobj;
+ JSProperty* prop;
+ if (!js_LookupProperty(cx, obj, id, &pobj, &prop))
+ return false;
+
+ if (vp)
+ *vp = JSVAL_VOID;
+ if (prop) {
+ bool traceable_slot = true;
+ if (pobj == obj) {
+ JSScopeProperty* sprop = (JSScopeProperty*) prop;
+ traceable_slot = ((op_offset == offsetof(JSObjectOps, getProperty))
+ ? SPROP_HAS_STUB_GETTER(sprop)
+ : SPROP_HAS_STUB_SETTER(sprop)) &&
+ SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj));
+ if (vp && traceable_slot)
+ *vp = LOCKED_OBJ_GET_SLOT(obj, sprop->slot);
+ }
+
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ if (pobj != obj)
+ ABORT_TRACE("elem op hit prototype property, can't shape-guard");
+ if (!traceable_slot)
+ ABORT_TRACE("elem op hit direct and slotless getter or setter");
+ }
+
+ // If we got this far, we're almost safe -- but we must check for a rogue resolve hook.
+ if (OBJ_SHAPE(obj) != shape)
+ ABORT_TRACE("resolve hook mutated elem op base object");
+
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape");
+ guard(true, addName(lir->ins2i(LIR_eq, shape_ins, shape), "guard(shape)"), MISMATCH_EXIT);
+ return true;
+}
+
+void
+TraceRecorder::clearFrameSlotsFromCache()
+{
+ /* Clear out all slots of this frame in the nativeFrameTracker. Different locations on the
+ VM stack might map to different locations on the native stack depending on the
+ number of arguments (i.e.) of the next call, so we have to make sure we map
+ those in to the cache with the right offsets. */
+ JSStackFrame* fp = cx->fp;
+ jsval* vp;
+ jsval* vpstop;
+ if (fp->callee) {
+ vp = &fp->argv[-2];
+ vpstop = &fp->argv[fp->fun->nargs];
+ while (vp < vpstop)
+ nativeFrameTracker.set(vp++, (LIns*)0);
+ }
+ vp = &fp->slots[0];
+ vpstop = &fp->slots[fp->script->nslots];
+ while (vp < vpstop)
+ nativeFrameTracker.set(vp++, (LIns*)0);
+}
+
+bool
+TraceRecorder::record_EnterFrame()
+{
+ JSStackFrame* fp = cx->fp;
+
+ if (++callDepth >= MAX_CALLDEPTH)
+ ABORT_TRACE("exceeded maximum call depth");
+ // FIXME: Allow and attempt to inline a single level of recursion until we compile
+ // recursive calls as independent trees (459301).
+ if (fp->script == fp->down->script && fp->down->down && fp->down->down->script == fp->script)
+ ABORT_TRACE("recursive call");
+
+ debug_only_v(printf("EnterFrame %s, callDepth=%d\n",
+ js_AtomToPrintableString(cx, cx->fp->fun->atom),
+ callDepth);)
+ LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+
+ jsval* vp = &fp->argv[fp->argc];
+ jsval* vpstop = vp + ptrdiff_t(fp->fun->nargs) - ptrdiff_t(fp->argc);
+ if (applyingArguments) {
+ applyingArguments = false;
+ while (vp < vpstop) {
+ JS_ASSERT(vp >= fp->down->regs->sp);
+ nativeFrameTracker.set(vp, (LIns*)0);
+ LIns* arg_ins = get(&fp->down->argv[fp->argc + (vp - vpstop)]);
+ set(vp++, arg_ins, true);
+ }
+ } else {
+ while (vp < vpstop) {
+ if (vp >= fp->down->regs->sp)
+ nativeFrameTracker.set(vp, (LIns*)0);
+ set(vp++, void_ins, true);
+ }
+ }
+
+ vp = &fp->slots[0];
+ vpstop = vp + fp->script->nfixed;
+ while (vp < vpstop)
+ set(vp++, void_ins, true);
+ return true;
+}
+
+bool
+TraceRecorder::record_LeaveFrame()
+{
+ debug_only_v(
+ if (cx->fp->fun)
+ printf("LeaveFrame (back to %s), callDepth=%d\n",
+ js_AtomToPrintableString(cx, cx->fp->fun->atom),
+ callDepth);
+ );
+ if (callDepth-- <= 0)
+ ABORT_TRACE("returned out of a loop we started tracing");
+
+ // LeaveFrame gets called after the interpreter popped the frame and
+ // stored rval, so cx->fp not cx->fp->down, and -1 not 0.
+ atoms = cx->fp->script->atomMap.vector;
+ set(&stackval(-1), rval_ins, true);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INTERRUPT()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_PUSH()
+{
+ stack(0, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_POPV()
+{
+ jsval& rval = stackval(-1);
+ LIns *rval_ins = get(&rval);
+ if (!box_jsval(rval, rval_ins))
+ return false;
+
+ // Store it in cx->fp->rval. NB: Tricky dependencies. cx->fp is the right
+ // frame because POPV appears only in global and eval code and we don't
+ // trace JSOP_EVAL or leaving the frame where tracing started.
+ LIns *fp_ins = lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp));
+ lir->insStorei(rval_ins, fp_ins, offsetof(JSStackFrame, rval));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ENTERWITH()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LEAVEWITH()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_RETURN()
+{
+ jsval& rval = stackval(-1);
+ JSStackFrame *fp = cx->fp;
+ if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && JSVAL_IS_PRIMITIVE(rval)) {
+ JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]);
+ rval_ins = get(&fp->argv[-1]);
+ } else {
+ rval_ins = get(&rval);
+ }
+ debug_only_v(printf("returning from %s\n", js_AtomToPrintableString(cx, cx->fp->fun->atom));)
+ clearFrameSlotsFromCache();
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GOTO()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_IFEQ()
+{
+ trackCfgMerges(cx->fp->regs->pc);
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_IFNE()
+{
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_ARGUMENTS()
+{
+#if 1
+ ABORT_TRACE("can't trace arguments yet");
+#else
+ LIns* args[] = { cx_ins };
+ LIns* a_ins = lir->insCall(&js_Arguments_ci, args);
+ guard(false, lir->ins_eq0(a_ins), OOM_EXIT);
+ stack(0, a_ins);
+ return true;
+#endif
+}
+
+bool
+TraceRecorder::record_JSOP_DUP()
+{
+ stack(0, get(&stackval(-1)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DUP2()
+{
+ stack(0, get(&stackval(-2)));
+ stack(1, get(&stackval(-1)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SWAP()
+{
+ jsval& l = stackval(-2);
+ jsval& r = stackval(-1);
+ LIns* l_ins = get(&l);
+ LIns* r_ins = get(&r);
+ set(&r, l_ins);
+ set(&l, r_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETCONST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_BITOR()
+{
+ return binary(LIR_or);
+}
+
+bool
+TraceRecorder::record_JSOP_BITXOR()
+{
+ return binary(LIR_xor);
+}
+
+bool
+TraceRecorder::record_JSOP_BITAND()
+{
+ return binary(LIR_and);
+}
+
+bool
+TraceRecorder::record_JSOP_EQ()
+{
+ return cmp(LIR_feq, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_NE()
+{
+ return cmp(LIR_feq, CMP_NEGATE | CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_LT()
+{
+ return cmp(LIR_flt, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_LE()
+{
+ return cmp(LIR_fle, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_GT()
+{
+ return cmp(LIR_fgt, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_GE()
+{
+ return cmp(LIR_fge, CMP_TRY_BRANCH_AFTER_COND);
+}
+
+bool
+TraceRecorder::record_JSOP_LSH()
+{
+ return binary(LIR_lsh);
+}
+
+bool
+TraceRecorder::record_JSOP_RSH()
+{
+ return binary(LIR_rsh);
+}
+
+bool
+TraceRecorder::record_JSOP_URSH()
+{
+ return binary(LIR_ush);
+}
+
+static struct {
+ jsbytecode obj_any[10];
+ jsbytecode any_obj[8];
+ jsbytecode obj_obj[16];
+} add_imacros = {
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_SWAP,
+ JSOP_ADD,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_ADD,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_SWAP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(toString),
+ JSOP_CALL, 0, 0,
+ JSOP_ADD,
+ JSOP_STOP
+ }
+};
+
+JS_STATIC_ASSERT(sizeof(add_imacros) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::record_JSOP_ADD()
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ if (JSVAL_IS_OBJECT(l) && hasToStringMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasToStringMethod(r))
+ return call_imacro(add_imacros.obj_obj);
+ return call_imacro(add_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasToStringMethod(r))
+ return call_imacro(add_imacros.any_obj);
+
+ if (JSVAL_IS_STRING(l) || JSVAL_IS_STRING(r)) {
+ LIns* args[] = { stringify(r), stringify(l), cx_ins };
+ if (!args[0] || !args[1])
+ ABORT_TRACE("can't stringify objects");
+ LIns* concat = lir->insCall(&js_ConcatStrings_ci, args);
+ guard(false, lir->ins_eq0(concat), OOM_EXIT);
+ set(&l, concat);
+ return true;
+ }
+
+ return binary(LIR_fadd);
+}
+
+bool
+TraceRecorder::record_JSOP_SUB()
+{
+ return binary(LIR_fsub);
+}
+
+bool
+TraceRecorder::record_JSOP_MUL()
+{
+ return binary(LIR_fmul);
+}
+
+bool
+TraceRecorder::record_JSOP_DIV()
+{
+ return binary(LIR_fdiv);
+}
+
+bool
+TraceRecorder::record_JSOP_MOD()
+{
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ if (JSVAL_IS_OBJECT(l) && hasValueOfMethod(l)) {
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.obj_obj);
+ return call_imacro(binary_imacros.obj_any);
+ }
+ if (JSVAL_IS_OBJECT(r) && hasValueOfMethod(r))
+ return call_imacro(binary_imacros.any_obj);
+
+ if (isNumber(l) && isNumber(r)) {
+ LIns* l_ins = get(&l);
+ LIns* r_ins = get(&r);
+ LIns* x;
+ /* We can't demote this in a filter since we need the actual values of l and r. */
+ if (isPromote(l_ins) && isPromote(r_ins) && asNumber(l) >= 0 && asNumber(r) > 0) {
+ LIns* args[] = { ::demote(lir, r_ins), ::demote(lir, l_ins) };
+ x = lir->insCall(&js_imod_ci, args);
+ guard(false, lir->ins2(LIR_eq, x, lir->insImm(-1)), BRANCH_EXIT);
+ x = lir->ins1(LIR_i2f, x);
+ } else {
+ LIns* args[] = { r_ins, l_ins };
+ x = lir->insCall(&js_dmod_ci, args);
+ }
+ set(&l, x);
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_NOT()
+{
+ jsval& v = stackval(-1);
+ if (JSVAL_TAG(v) == JSVAL_BOOLEAN) {
+ set(&v, lir->ins_eq0(lir->ins2i(LIR_eq, get(&v), 1)));
+ return true;
+ }
+ if (isNumber(v)) {
+ LIns* v_ins = get(&v);
+ set(&v, lir->ins2(LIR_or, lir->ins2(LIR_feq, v_ins, lir->insImmq(0)),
+ lir->ins_eq0(lir->ins2(LIR_feq, v_ins, v_ins))));
+ return true;
+ }
+ if (JSVAL_IS_OBJECT(v)) {
+ set(&v, lir->ins_eq0(get(&v)));
+ return true;
+ }
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ set(&v, lir->ins_eq0(lir->ins2(LIR_piand,
+ lir->insLoad(LIR_ldp, get(&v), (int)offsetof(JSString, length)),
+ INS_CONSTPTR(JSSTRING_LENGTH_MASK))));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_BITNOT()
+{
+ return unary(LIR_not);
+}
+
+bool
+TraceRecorder::record_JSOP_NEG()
+{
+ jsval& v = stackval(-1);
+ if (isNumber(v)) {
+ LIns* a = get(&v);
+
+ /* If we're a promoted integer, we have to watch out for 0s since -0 is a double.
+ Only follow this path if we're not an integer that's 0 and we're not a double
+ that's zero.
+ */
+ if (isPromoteInt(a) &&
+ (!JSVAL_IS_INT(v) || JSVAL_TO_INT(v) != 0) &&
+ (!JSVAL_IS_DOUBLE(v) || !JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v)))) {
+ a = lir->ins1(LIR_neg, ::demote(lir, a));
+ lir->insGuard(LIR_xt, lir->ins1(LIR_ov, a), snapshot(OVERFLOW_EXIT));
+ lir->insGuard(LIR_xt, lir->ins2(LIR_eq, a, lir->insImm(0)), snapshot(OVERFLOW_EXIT));
+ a = lir->ins1(LIR_i2f, a);
+ } else {
+ a = lir->ins1(LIR_fneg, a);
+ }
+
+ set(&v, a);
+ return true;
+ }
+ return false;
+}
+
+JSBool
+js_Array(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval);
+
+JSBool
+js_Object(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool
+js_Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+
+JSBool
+js_fun_apply(JSContext* cx, uintN argc, jsval* vp);
+
+bool
+TraceRecorder::functionCall(bool constructing)
+{
+ JSStackFrame* fp = cx->fp;
+ jsbytecode *pc = fp->regs->pc;
+ uintN argc = GET_ARGC(pc);
+
+ jsval& fval = stackval(0 - (2 + argc));
+ JS_ASSERT(&fval >= StackBase(fp));
+
+ if (!VALUE_IS_FUNCTION(cx, fval))
+ ABORT_TRACE("callee is not a function");
+
+ jsval& tval = stackval(0 - (argc + 1));
+ LIns* this_ins = get(&tval);
+
+ if (this_ins->isconstp() && !this_ins->constvalp() && !guardShapelessCallee(fval))
+ return false;
+
+ /*
+ * Require that the callee be a function object, to avoid guarding on its
+ * class here. We know if the callee and this were pushed by JSOP_CALLNAME
+ * or JSOP_CALLPROP that callee is a *particular* function, since these hit
+ * the property cache and guard on the object (this) in which the callee
+ * was found. So it's sufficient to test here that the particular function
+ * is interpreted, not guard on that condition.
+ *
+ * Bytecode sequences that push shapeless callees must guard on the callee
+ * class being Function and the function being interpreted.
+ */
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(fval));
+
+ if (FUN_INTERPRETED(fun)) {
+ if (constructing) {
+ LIns* args[] = { get(&fval), cx_ins };
+ LIns* tv_ins = lir->insCall(&js_FastNewObject_ci, args);
+ guard(false, lir->ins_eq0(tv_ins), OOM_EXIT);
+ set(&tval, tv_ins);
+ }
+ return interpretedFunctionCall(fval, fun, argc, constructing);
+ }
+
+ LIns* arg1_ins = NULL;
+ jsval arg1 = JSVAL_VOID;
+ jsval thisval = tval;
+ if (!constructing && FUN_FAST_NATIVE(fun) == js_fun_apply) {
+ if (argc != 2)
+ ABORT_TRACE("can't trace Function.prototype.apply with other than 2 args");
+
+ if (!guardShapelessCallee(tval))
+ return false;
+ JSObject* tfunobj = JSVAL_TO_OBJECT(tval);
+ JSFunction* tfun = GET_FUNCTION_PRIVATE(cx, tfunobj);
+
+ jsval& oval = stackval(-2);
+ if (JSVAL_IS_PRIMITIVE(oval))
+ ABORT_TRACE("can't trace Function.prototype.apply with primitive 1st arg");
+
+ jsval& aval = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(aval))
+ ABORT_TRACE("can't trace Function.prototype.apply with primitive 2nd arg");
+ JSObject* aobj = JSVAL_TO_OBJECT(aval);
+
+ LIns* aval_ins = get(&aval);
+ if (!aval_ins->isCall())
+ ABORT_TRACE("can't trace Function.prototype.apply on non-builtin-call 2nd arg");
+
+ if (aval_ins->callInfo() == &js_Arguments_ci) {
+ JS_ASSERT(OBJ_GET_CLASS(cx, aobj) == &js_ArgumentsClass);
+ JS_ASSERT(OBJ_GET_PRIVATE(cx, aobj) == fp);
+ if (!FUN_INTERPRETED(tfun))
+ ABORT_TRACE("can't trace Function.prototype.apply(native_function, arguments)");
+
+ // We can only fasttrack applys where the argument array we pass in has the
+ // same length (fp->argc) as the number of arguments the function expects (tfun->nargs).
+ argc = fp->argc;
+ if (tfun->nargs != argc || fp->fun->nargs != argc)
+ ABORT_TRACE("can't trace Function.prototype.apply(scripted_function, arguments)");
+
+ jsval* sp = fp->regs->sp - 4;
+ set(sp, get(&tval));
+ *sp++ = tval;
+ set(sp, get(&oval));
+ *sp++ = oval;
+ jsval* newsp = sp + argc;
+ if (newsp > fp->slots + fp->script->nslots) {
+ JSArena* a = cx->stackPool.current;
+ if (jsuword(newsp) > a->limit)
+ ABORT_TRACE("can't grow stack for Function.prototype.apply");
+ if (jsuword(newsp) > a->avail)
+ a->avail = jsuword(newsp);
+ }
+
+ jsval* argv = fp->argv;
+ for (uintN i = 0; i < JS_MIN(argc, 2); i++) {
+ set(&sp[i], get(&argv[i]));
+ sp[i] = argv[i];
+ }
+ applyingArguments = true;
+ return interpretedFunctionCall(tval, tfun, argc, false);
+ }
+
+ if (aval_ins->callInfo() != &js_Array_1str_ci)
+ ABORT_TRACE("can't trace Function.prototype.apply on other than [str] 2nd arg");
+
+ JS_ASSERT(OBJ_IS_ARRAY(cx, aobj));
+ JS_ASSERT(aobj->fslots[JSSLOT_ARRAY_LENGTH] == 1);
+ JS_ASSERT(JSVAL_IS_STRING(aobj->dslots[0]));
+
+ if (FUN_INTERPRETED(tfun))
+ ABORT_TRACE("can't trace Function.prototype.apply for scripted functions");
+
+ if (!(tfun->flags & JSFUN_TRACEABLE))
+ ABORT_TRACE("Function.prototype.apply on untraceable native");
+
+ thisval = oval;
+ this_ins = get(&oval);
+ arg1_ins = callArgN(aval_ins, 2);
+ arg1 = aobj->dslots[0];
+ fun = tfun;
+ argc = 1;
+ }
+
+ if (!constructing && !(fun->flags & JSFUN_TRACEABLE))
+ ABORT_TRACE("untraceable native");
+
+ static JSTraceableNative knownNatives[] = {
+ { (JSFastNative)js_Array, &js_FastNewArray_ci, "pC", "", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Array, &js_Array_1int_ci, "pC", "i", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Array, &js_Array_2obj_ci, "pC", "oo", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Array, &js_Array_3num_ci, "pC", "ddd", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Object, &js_FastNewObject_ci, "fC", "", FAIL_NULL | JSTN_MORE },
+ { (JSFastNative)js_Date, &js_FastNewDate_ci, "pC", "", FAIL_NULL },
+ };
+
+ LIns* args[5];
+ JSTraceableNative* known = constructing ? knownNatives : FUN_TRCINFO(fun);
+ do {
+ if (constructing && (JSFastNative)fun->u.n.native != known->native)
+ continue;
+
+ uintN knownargc = strlen(known->argtypes);
+ if (argc != knownargc)
+ continue;
+
+ intN prefixc = strlen(known->prefix);
+ JS_ASSERT(prefixc <= 3);
+ LIns** argp = &args[argc + prefixc - 1];
+ char argtype;
+
+#if defined _DEBUG
+ memset(args, 0xCD, sizeof(args));
+#endif
+
+ uintN i;
+ for (i = prefixc; i--; ) {
+ argtype = known->prefix[i];
+ if (argtype == 'C') {
+ *argp = cx_ins;
+ } else if (argtype == 'T') { /* this, as an object */
+ if (!JSVAL_IS_OBJECT(thisval))
+ goto next_specialization;
+ *argp = this_ins;
+ } else if (argtype == 'S') { /* this, as a string */
+ if (!JSVAL_IS_STRING(thisval))
+ goto next_specialization;
+ *argp = this_ins;
+ } else if (argtype == 'f') {
+ *argp = INS_CONSTPTR(JSVAL_TO_OBJECT(fval));
+ } else if (argtype == 'p') {
+ JSObject* ctor = JSVAL_TO_OBJECT(fval);
+ jsval pval;
+ if (!OBJ_GET_PROPERTY(cx, ctor,
+ ATOM_TO_JSID(cx->runtime->atomState
+ .classPrototypeAtom),
+ &pval)) {
+ ABORT_TRACE("error getting prototype from constructor");
+ }
+ if (!JSVAL_IS_OBJECT(pval))
+ ABORT_TRACE("got primitive prototype from constructor");
+ *argp = INS_CONSTPTR(JSVAL_TO_OBJECT(pval));
+ } else if (argtype == 'R') {
+ *argp = INS_CONSTPTR(cx->runtime);
+ } else if (argtype == 'P') {
+ *argp = INS_CONSTPTR(pc);
+ } else if (argtype == 'D') { /* this, as a number */
+ if (!isNumber(thisval))
+ goto next_specialization;
+ *argp = this_ins;
+ } else {
+ JS_NOT_REACHED("unknown prefix arg type");
+ }
+ argp--;
+ }
+
+ for (i = knownargc; i--; ) {
+ jsval& arg = (!constructing && i == 0 && arg1_ins) ? arg1 : stackval(0 - (i + 1));
+ *argp = (!constructing && i == 0 && arg1_ins) ? arg1_ins : get(&arg);
+
+ argtype = known->argtypes[i];
+ if (argtype == 'd' || argtype == 'i') {
+ if (!isNumber(arg))
+ goto next_specialization;
+ if (argtype == 'i')
+ *argp = f2i(*argp);
+ } else if (argtype == 'o') {
+ if (!JSVAL_IS_OBJECT(arg))
+ goto next_specialization;
+ } else if (argtype == 's') {
+ if (!JSVAL_IS_STRING(arg))
+ goto next_specialization;
+ } else if (argtype == 'r') {
+ if (!VALUE_IS_REGEXP(cx, arg))
+ goto next_specialization;
+ } else if (argtype == 'f') {
+ if (!VALUE_IS_FUNCTION(cx, arg))
+ goto next_specialization;
+ } else if (argtype == 'v') {
+ if (!box_jsval(arg, *argp))
+ return false;
+ } else {
+ goto next_specialization;
+ }
+ argp--;
+ }
+
+ /*
+ * If we got this far, and we have a charCodeAt, check that charCodeAt
+ * isn't going to return a NaN.
+ */
+ if (!constructing && known->builtin == &js_String_p_charCodeAt_ci) {
+ JSString* str = JSVAL_TO_STRING(thisval);
+ jsval& arg = arg1_ins ? arg1 : stackval(-1);
+
+ JS_ASSERT(JSVAL_IS_STRING(thisval));
+ JS_ASSERT(isNumber(arg));
+
+ if (JSVAL_IS_INT(arg)) {
+ if (size_t(JSVAL_TO_INT(arg)) >= JSSTRING_LENGTH(str))
+ ABORT_TRACE("invalid charCodeAt index");
+ } else {
+ double d = js_DoubleToInteger(*JSVAL_TO_DOUBLE(arg));
+ if (d < 0 || JSSTRING_LENGTH(str) <= d)
+ ABORT_TRACE("invalid charCodeAt index");
+ }
+ }
+ goto success;
+
+next_specialization:;
+ } while ((known++)->flags & JSTN_MORE);
+
+ if (!constructing)
+ ABORT_TRACE("unknown native");
+ if (!(fun->flags & JSFUN_TRACEABLE) && FUN_CLASP(fun))
+ ABORT_TRACE("can't trace native constructor");
+ ABORT_TRACE("can't trace unknown constructor");
+
+success:
+#if defined _DEBUG
+ JS_ASSERT(args[0] != (LIns *)0xcdcdcdcd);
+#endif
+
+ LIns* res_ins = lir->insCall(known->builtin, args);
+ if (!constructing)
+ rval_ins = res_ins;
+ switch (JSTN_ERRTYPE(known)) {
+ case FAIL_NULL:
+ guard(false, lir->ins_eq0(res_ins), OOM_EXIT);
+ break;
+ case FAIL_NEG:
+ {
+ res_ins = lir->ins1(LIR_i2f, res_ins);
+ jsdpun u;
+ u.d = 0.0;
+ guard(false, lir->ins2(LIR_flt, res_ins, lir->insImmq(u.u64)), OOM_EXIT);
+ break;
+ }
+ case FAIL_VOID:
+ guard(false, lir->ins2i(LIR_eq, res_ins, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
+ break;
+ default:;
+ }
+ set(&fval, res_ins);
+
+ if (!constructing) {
+ /*
+ * The return value will be processed by FastNativeCallComplete since
+ * we have to know the actual return value type for calls that return
+ * jsval (like Array_p_pop).
+ */
+ pendingTraceableNative = known;
+ }
+
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NEW()
+{
+ return functionCall(true);
+}
+
+bool
+TraceRecorder::record_JSOP_DELNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DELPROP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DELELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TYPEOF()
+{
+ jsval& r = stackval(-1);
+ LIns* type;
+ if (JSVAL_IS_STRING(r)) {
+ type = INS_CONSTPTR(ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_STRING]));
+ } else if (isNumber(r)) {
+ type = INS_CONSTPTR(ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER]));
+ } else {
+ LIns* args[] = { get(&r), cx_ins };
+ if (JSVAL_TAG(r) == JSVAL_BOOLEAN) {
+ // We specialize identically for boolean and undefined. We must not have a hole here.
+ // Pass the unboxed type here, since TypeOfBoolean knows how to handle it.
+ JS_ASSERT(JSVAL_TO_BOOLEAN(r) <= 2);
+ type = lir->insCall(&js_TypeOfBoolean_ci, args);
+ } else {
+ JS_ASSERT(JSVAL_IS_OBJECT(r));
+ type = lir->insCall(&js_TypeOfObject_ci, args);
+ }
+ }
+ set(&r, type);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_VOID()
+{
+ stack(-1, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INCNAME()
+{
+ return incName(1);
+}
+
+bool
+TraceRecorder::record_JSOP_INCPROP()
+{
+ return incProp(1);
+}
+
+bool
+TraceRecorder::record_JSOP_INCELEM()
+{
+ return incElem(1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECNAME()
+{
+ return incName(-1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECPROP()
+{
+ return incProp(-1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECELEM()
+{
+ return incElem(-1);
+}
+
+bool
+TraceRecorder::incName(jsint incr, bool pre)
+{
+ jsval* vp;
+ if (!name(vp))
+ return false;
+ LIns* v_ins = get(vp);
+ if (!inc(*vp, v_ins, incr, pre))
+ return false;
+ set(vp, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NAMEINC()
+{
+ return incName(1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_PROPINC()
+{
+ return incProp(1, false);
+}
+
+// XXX consolidate with record_JSOP_GETELEM code...
+bool
+TraceRecorder::record_JSOP_ELEMINC()
+{
+ return incElem(1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_NAMEDEC()
+{
+ return incName(-1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_PROPDEC()
+{
+ return incProp(-1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_ELEMDEC()
+{
+ return incElem(-1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_GETPROP()
+{
+ return getProp(stackval(-1));
+}
+
+bool
+TraceRecorder::record_JSOP_SETPROP()
+{
+ jsval& l = stackval(-2);
+ if (JSVAL_IS_PRIMITIVE(l))
+ ABORT_TRACE("primitive this for SETPROP");
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (obj->map->ops->setProperty != js_SetProperty)
+ ABORT_TRACE("non-native JSObjectOps::setProperty");
+ return true;
+}
+
+bool
+TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop)
+{
+ if (sprop->setter == js_watch_set)
+ ABORT_TRACE("watchpoint detected");
+
+ jsbytecode* pc = cx->fp->regs->pc;
+ jsval& r = stackval(-1);
+ jsval& l = stackval(-2);
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(l));
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ LIns* obj_ins = get(&l);
+
+ if (obj == globalObj) {
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)));
+ uint32 slot = sprop->slot;
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ LIns* r_ins = get(&r);
+ set(&STOBJ_GET_SLOT(obj, slot), r_ins);
+
+ JS_ASSERT(*pc != JSOP_INITPROP);
+ if (pc[JSOP_SETPROP_LENGTH] != JSOP_POP)
+ set(&l, r_ins);
+ return true;
+ }
+
+ // The global object's shape is guarded at trace entry, all others need a guard here.
+ LIns* map_ins = lir->insLoad(LIR_ldp, obj_ins, (int)offsetof(JSObject, map));
+ LIns* ops_ins;
+ if (!map_is_native(obj->map, map_ins, ops_ins, offsetof(JSObjectOps, setProperty)))
+ return false;
+
+ LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape");
+ guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(shape)"),
+ MISMATCH_EXIT);
+
+ if (entry->kshape != PCVCAP_SHAPE(entry->vcap)) {
+ LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
+ LIns* ok_ins = lir->insCall(&js_AddProperty_ci, args);
+ guard(false, lir->ins_eq0(ok_ins), OOM_EXIT);
+ }
+
+ LIns* dslots_ins = NULL;
+ LIns* v_ins = get(&r);
+ LIns* boxed_ins = v_ins;
+ if (!box_jsval(r, boxed_ins))
+ return false;
+ if (!native_set(obj_ins, sprop, dslots_ins, boxed_ins))
+ return false;
+
+ if (*pc != JSOP_INITPROP && pc[JSOP_SETPROP_LENGTH] != JSOP_POP)
+ set(&l, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_SetPropMiss(JSPropCacheEntry* entry)
+{
+ if (entry->kpc != cx->fp->regs->pc || !PCVAL_IS_SPROP(entry->vword))
+ ABORT_TRACE("can't trace uncacheable property set");
+
+ JSScopeProperty* sprop = PCVAL_TO_SPROP(entry->vword);
+
+#ifdef DEBUG
+ jsval& l = stackval(-2);
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ JSScope* scope = OBJ_SCOPE(obj);
+ JS_ASSERT(scope->object == obj);
+ JS_ASSERT(scope->shape == PCVCAP_SHAPE(entry->vcap));
+ JS_ASSERT(SCOPE_HAS_PROPERTY(scope, sprop));
+#endif
+
+ return record_SetPropHit(entry, sprop);
+}
+
+bool
+TraceRecorder::record_JSOP_GETELEM()
+{
+ jsval& idx = stackval(-1);
+ jsval& lval = stackval(-2);
+
+ LIns* obj_ins = get(&lval);
+ LIns* idx_ins = get(&idx);
+
+ if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(idx)) {
+ int i = JSVAL_TO_INT(idx);
+ if ((size_t)i >= JSSTRING_LENGTH(JSVAL_TO_STRING(lval)))
+ ABORT_TRACE("Invalid string index in JSOP_GETELEM");
+ idx_ins = makeNumberInt32(idx_ins);
+ LIns* args[] = { idx_ins, obj_ins, cx_ins };
+ LIns* unitstr_ins = lir->insCall(&js_String_getelem_ci, args);
+ guard(false, lir->ins_eq0(unitstr_ins), MISMATCH_EXIT);
+ set(&lval, unitstr_ins);
+ return true;
+ }
+
+ if (JSVAL_IS_PRIMITIVE(lval))
+ ABORT_TRACE("JSOP_GETLEM on a primitive");
+
+ JSObject* obj = JSVAL_TO_OBJECT(lval);
+ jsval id;
+ jsval v;
+ LIns* v_ins;
+
+ /* Property access using a string name. */
+ if (JSVAL_IS_STRING(idx)) {
+ if (!js_ValueToStringId(cx, idx, &id))
+ return false;
+ // Store the interned string to the stack to save the interpreter from redoing this work.
+ idx = ID_TO_VALUE(id);
+ jsuint index;
+ if (js_IdIsIndex(idx, &index) && guardDenseArray(obj, obj_ins, BRANCH_EXIT)) {
+ v = (index >= ARRAY_DENSE_LENGTH(obj)) ? JSVAL_HOLE : obj->dslots[index];
+ if (v == JSVAL_HOLE)
+ ABORT_TRACE("can't see through hole in dense array");
+ } else {
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, getProperty), &v))
+ return false;
+ }
+ LIns* args[] = { idx_ins, obj_ins, cx_ins };
+ v_ins = lir->insCall(&js_Any_getprop_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), MISMATCH_EXIT);
+ if (!unbox_jsval(v, v_ins))
+ ABORT_TRACE("JSOP_GETELEM");
+ set(&lval, v_ins);
+ return true;
+ }
+
+ /* At this point we expect a whole number or we bail. */
+ if (!JSVAL_IS_INT(idx))
+ ABORT_TRACE("non-string, non-int JSOP_GETELEM index");
+ if (JSVAL_TO_INT(idx) < 0)
+ ABORT_TRACE("negative JSOP_GETELEM index");
+
+ /* Accessing an object using integer index but not a dense array. */
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ idx_ins = makeNumberInt32(idx_ins);
+ LIns* args[] = { idx_ins, obj_ins, cx_ins };
+ if (!js_IndexToId(cx, JSVAL_TO_INT(idx), &id))
+ return false;
+ idx = ID_TO_VALUE(id);
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, getProperty), &v))
+ return false;
+ LIns* v_ins = lir->insCall(&js_Any_getelem_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), MISMATCH_EXIT);
+ if (!unbox_jsval(v, v_ins))
+ ABORT_TRACE("JSOP_GETELEM");
+ set(&lval, v_ins);
+ return true;
+ }
+
+ jsval* vp;
+ LIns* addr_ins;
+ if (!elem(lval, idx, vp, v_ins, addr_ins))
+ return false;
+ set(&lval, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETELEM()
+{
+ jsval& v = stackval(-1);
+ jsval& idx = stackval(-2);
+ jsval& lval = stackval(-3);
+
+ /* no guards for type checks, trace specialized this already */
+ if (JSVAL_IS_PRIMITIVE(lval))
+ ABORT_TRACE("left JSOP_SETELEM operand is not an object");
+
+ JSObject* obj = JSVAL_TO_OBJECT(lval);
+ LIns* obj_ins = get(&lval);
+ LIns* idx_ins = get(&idx);
+ LIns* v_ins = get(&v);
+ jsid id;
+
+ LIns* boxed_v_ins = v_ins;
+ if (!box_jsval(v, boxed_v_ins))
+ ABORT_TRACE("boxing JSOP_SETELEM value");
+
+ if (JSVAL_IS_STRING(idx)) {
+ if (!js_ValueToStringId(cx, idx, &id))
+ return false;
+ // Store the interned string to the stack to save the interpreter from redoing this work.
+ idx = ID_TO_VALUE(id);
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, setProperty), NULL))
+ return false;
+ LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins };
+ LIns* ok_ins = lir->insCall(&js_Any_setprop_ci, args);
+ guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
+ } else if (JSVAL_IS_INT(idx)) {
+ if (JSVAL_TO_INT(idx) < 0)
+ ABORT_TRACE("negative JSOP_SETELEM index");
+ idx_ins = makeNumberInt32(idx_ins);
+ LIns* args[] = { boxed_v_ins, idx_ins, obj_ins, cx_ins };
+ LIns* res_ins;
+ if (guardDenseArray(obj, obj_ins, BRANCH_EXIT)) {
+ res_ins = lir->insCall(&js_Array_dense_setelem_ci, args);
+ } else {
+ if (!js_IndexToId(cx, JSVAL_TO_INT(idx), &id))
+ return false;
+ idx = ID_TO_VALUE(id);
+ if (!guardElemOp(obj, obj_ins, id, offsetof(JSObjectOps, setProperty), NULL))
+ return false;
+ res_ins = lir->insCall(&js_Any_setelem_ci, args);
+ }
+ guard(false, lir->ins_eq0(res_ins), MISMATCH_EXIT);
+ } else {
+ ABORT_TRACE("non-string, non-int JSOP_SETELEM index");
+ }
+
+ jsbytecode* pc = cx->fp->regs->pc;
+ if (*pc == JSOP_SETELEM && pc[JSOP_SETELEM_LENGTH] != JSOP_POP)
+ set(&lval, v_ins);
+
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLNAME()
+{
+ JSObject* obj = cx->fp->scopeChain;
+ if (obj != globalObj) {
+ jsval* vp;
+ if (!activeCallOrGlobalSlot(obj, vp))
+ return false;
+ stack(0, get(vp));
+ stack(1, INS_CONSTPTR(globalObj));
+ return true;
+ }
+
+ LIns* obj_ins = scopeChain();
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ if (PCVAL_IS_NULL(pcval) || !PCVAL_IS_OBJECT(pcval))
+ ABORT_TRACE("callee is not an object");
+ JS_ASSERT(HAS_FUNCTION_CLASS(PCVAL_TO_OBJECT(pcval)));
+
+ stack(0, INS_CONSTPTR(PCVAL_TO_OBJECT(pcval)));
+ stack(1, obj_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GETUPVAR()
+{
+ ABORT_TRACE("GETUPVAR");
+}
+
+bool
+TraceRecorder::record_JSOP_CALLUPVAR()
+{
+ ABORT_TRACE("CALLUPVAR");
+}
+
+bool
+TraceRecorder::guardShapelessCallee(jsval& callee)
+{
+ guard(true,
+ addName(lir->ins2(LIR_eq, get(&callee), INS_CONSTPTR(JSVAL_TO_OBJECT(callee))),
+ "guard(shapeless callee)"),
+ MISMATCH_EXIT);
+ return true;
+}
+
+bool
+TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, bool constructing)
+{
+ if (JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(fval)) != globalObj)
+ ABORT_TRACE("JSOP_CALL or JSOP_NEW crosses global scopes");
+
+ JSStackFrame* fp = cx->fp;
+
+ // TODO: track the copying via the tracker...
+ if (argc < fun->nargs &&
+ jsuword(fp->regs->sp + (fun->nargs - argc)) > cx->stackPool.current->limit) {
+ ABORT_TRACE("can't trace calls with too few args requiring argv move");
+ }
+
+ // Generate a type map for the outgoing frame and stash it in the LIR
+ unsigned stackSlots = js_NativeStackSlots(cx, 0/*callDepth*/);
+ LIns* data = lir_buf_writer->skip(stackSlots * sizeof(uint8));
+ uint8* typemap = (uint8 *)data->payload();
+ uint8* m = typemap;
+ /* Determine the type of a store by looking at the current type of the actual value the
+ interpreter is using. For numbers we have to check what kind of store we used last
+ (integer or double) to figure out what the side exit show reflect in its typemap. */
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0/*callDepth*/,
+ *m++ = determineSlotType(vp);
+ );
+
+ if (argc >= 0x8000)
+ ABORT_TRACE("too many arguments");
+
+ FrameInfo fi = {
+ JSVAL_TO_OBJECT(fval),
+ ENCODE_IP_ADJ(fp, fp->regs->pc),
+ typemap,
+ { { fp->regs->sp - fp->slots, argc | (constructing ? 0x8000 : 0) } }
+ };
+
+ unsigned callDepth = getCallDepth();
+ if (callDepth >= treeInfo->maxCallDepth)
+ treeInfo->maxCallDepth = callDepth + 1;
+
+ lir->insStorei(INS_CONSTPTR(fi.callee), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, callee));
+ lir->insStorei(INS_CONSTPTR(fi.ip_adj), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, ip_adj));
+ lir->insStorei(INS_CONSTPTR(fi.typemap), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, typemap));
+ lir->insStorei(INS_CONST(fi.word), lirbuf->rp,
+ callDepth * sizeof(FrameInfo) + offsetof(FrameInfo, word));
+
+ atoms = fun->u.i.script->atomMap.vector;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALL()
+{
+ return functionCall(false);
+}
+
+bool
+TraceRecorder::record_JSOP_APPLY()
+{
+ return functionCall(false);
+}
+
+bool
+TraceRecorder::record_FastNativeCallComplete()
+{
+ JS_ASSERT(pendingTraceableNative);
+
+ /* At this point the generated code has already called the native function
+ and we can no longer fail back to the original pc location (JSOP_CALL)
+ because that would cause the interpreter to re-execute the native
+ function, which might have side effects.
+
+ Instead, snapshot(), which is invoked from unbox_jsval(), will see that
+ we are currently parked on a traceable native's JSOP_CALL instruction,
+ and it will advance the pc to restore by the length of the current
+ opcode, and indicate in the type map that the element on top of the
+ stack is a boxed value which doesn't need to be boxed if the type guard
+ generated by unbox_jsval() fails. */
+ JS_ASSERT(*cx->fp->regs->pc == JSOP_CALL ||
+ *cx->fp->regs->pc == JSOP_APPLY);
+
+ jsval& v = stackval(-1);
+ LIns* v_ins = get(&v);
+
+ bool ok = true;
+ switch (JSTN_ERRTYPE(pendingTraceableNative)) {
+ case FAIL_JSVAL:
+ ok = unbox_jsval(v, v_ins);
+ if (ok)
+ set(&v, v_ins);
+ break;
+ case FAIL_NEG:
+ /* Already added i2f in functionCall. */
+ JS_ASSERT(JSVAL_IS_NUMBER(v));
+ break;
+ default:
+ /* Convert the result to double if the builtin returns int32. */
+ if (JSVAL_IS_NUMBER(v) &&
+ (pendingTraceableNative->builtin->_argtypes & 3) == nanojit::ARGSIZE_LO) {
+ set(&v, lir->ins1(LIR_i2f, v_ins));
+ }
+ }
+
+ // We'll null pendingTraceableNative in js_MonitorRecording, on the next op cycle.
+ // There must be a next op since the stack is non-empty.
+ return ok;
+}
+
+bool
+TraceRecorder::name(jsval*& vp)
+{
+ JSObject* obj = cx->fp->scopeChain;
+ if (obj != globalObj)
+ return activeCallOrGlobalSlot(obj, vp);
+
+ /* Can't use prop here, because we don't want unboxing from global slots. */
+ LIns* obj_ins = scopeChain();
+ uint32 slot;
+ if (!test_property_cache_direct_slot(obj, obj_ins, slot))
+ return false;
+
+ if (slot == SPROP_INVALID_SLOT)
+ ABORT_TRACE("name op can't find named property");
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ vp = &STOBJ_GET_SLOT(obj, slot);
+ return true;
+}
+
+bool
+TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32& slot, LIns*& v_ins)
+{
+ /*
+ * Can't specialize to assert obj != global, must guard to avoid aliasing
+ * stale homes of stacked global variables.
+ */
+ if (obj == globalObj)
+ ABORT_TRACE("prop op aliases global");
+ guard(false, lir->ins2(LIR_eq, obj_ins, INS_CONSTPTR(globalObj)), MISMATCH_EXIT);
+
+ /*
+ * Property cache ensures that we are dealing with an existing property,
+ * and guards the shape for us.
+ */
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ /* Check for non-existent property reference, which results in undefined. */
+ const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
+ if (PCVAL_IS_NULL(pcval)) {
+ v_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, v_ins);
+ slot = SPROP_INVALID_SLOT;
+ return true;
+ }
+
+ /* Insist if setting on obj being the directly addressed object. */
+ uint32 setflags = (cs.format & (JOF_SET | JOF_INCDEC));
+ LIns* dslots_ins = NULL;
+ if (obj2 != obj) {
+ if (setflags)
+ ABORT_TRACE("JOF_SET opcode hit prototype chain");
+
+ /*
+ * We're getting a proto-property. Walk up the prototype chain emitting
+ * proto slot loads, updating obj as we go, leaving obj set to obj2 with
+ * obj_ins the last proto-load.
+ */
+ while (obj != obj2) {
+ obj_ins = stobj_get_slot(obj_ins, JSSLOT_PROTO, dslots_ins);
+ obj = STOBJ_GET_PROTO(obj);
+ }
+ }
+
+ /* Don't trace getter or setter calls, our caller wants a direct slot. */
+ if (PCVAL_IS_SPROP(pcval)) {
+ JSScopeProperty* sprop = PCVAL_TO_SPROP(pcval);
+
+ if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
+ ABORT_TRACE("non-stub setter");
+ if (setflags != JOF_SET && !SPROP_HAS_STUB_GETTER(sprop)) {
+ // FIXME 450335: generalize this away from regexp built-in getters.
+ if (setflags == 0 &&
+ sprop->getter == js_RegExpClass.getProperty &&
+ sprop->shortid < 0) {
+ if (sprop->shortid == REGEXP_LAST_INDEX)
+ ABORT_TRACE("can't trace regexp.lastIndex yet");
+ LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
+ v_ins = lir->insCall(&js_CallGetter_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
+ if (!unbox_jsval((sprop->shortid == REGEXP_SOURCE) ? JSVAL_STRING : JSVAL_BOOLEAN,
+ v_ins)) {
+ ABORT_TRACE("unboxing");
+ }
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, v_ins);
+ return true;
+ }
+ ABORT_TRACE("non-stub getter");
+ }
+ if (!SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)))
+ ABORT_TRACE("no valid slot");
+ slot = sprop->slot;
+ } else {
+ if (!PCVAL_IS_SLOT(pcval))
+ ABORT_TRACE("PCE is not a slot");
+ slot = PCVAL_TO_SLOT(pcval);
+ }
+
+ v_ins = stobj_get_slot(obj_ins, slot, dslots_ins);
+ if (!unbox_jsval(STOBJ_GET_SLOT(obj, slot), v_ins))
+ ABORT_TRACE("unboxing");
+ return true;
+}
+
+bool
+TraceRecorder::elem(jsval& oval, jsval& idx, jsval*& vp, LIns*& v_ins, LIns*& addr_ins)
+{
+ /* no guards for type checks, trace specialized this already */
+ if (JSVAL_IS_PRIMITIVE(oval) || !JSVAL_IS_INT(idx))
+ return false;
+
+ JSObject* obj = JSVAL_TO_OBJECT(oval);
+ LIns* obj_ins = get(&oval);
+
+ /* make sure the object is actually a dense array */
+ if (!guardDenseArray(obj, obj_ins))
+ return false;
+
+ /* check that the index is within bounds */
+ jsint i = JSVAL_TO_INT(idx);
+ LIns* idx_ins = makeNumberInt32(get(&idx));
+
+ LIns* dslots_ins = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
+ if (!guardDenseArrayIndex(obj, i, obj_ins, dslots_ins, idx_ins, BRANCH_EXIT)) {
+ LIns* rt_ins = lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, runtime));
+ guard(true,
+ lir->ins_eq0(lir->insLoad(LIR_ldp, rt_ins,
+ offsetof(JSRuntime, anyArrayProtoHasElement))),
+ MISMATCH_EXIT);
+ // Return undefined and indicate that we didn't actually read this (addr_ins).
+ v_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ addr_ins = NULL;
+ return true;
+ }
+
+ // We can't "see through" a hole to a possible Array.prototype property, so
+ // we abort here and guard below (after unboxing).
+ vp = &obj->dslots[i];
+ if (*vp == JSVAL_HOLE)
+ ABORT_TRACE("can't see through hole in dense array");
+
+ addr_ins = lir->ins2(LIR_piadd, dslots_ins,
+ lir->ins2i(LIR_pilsh, idx_ins, (sizeof(jsval) == 4) ? 2 : 3));
+
+ /* Load the value and guard on its type to unbox it. */
+ v_ins = lir->insLoad(LIR_ldp, addr_ins, 0);
+ if (!unbox_jsval(*vp, v_ins))
+ return false;
+
+ if (JSVAL_TAG(*vp) == JSVAL_BOOLEAN) {
+ // Optimize to guard for a hole only after untagging, so we know that
+ // we have a boolean, to avoid an extra guard for non-boolean values.
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE))),
+ MISMATCH_EXIT);
+ }
+ return true;
+}
+
+bool
+TraceRecorder::getProp(JSObject* obj, LIns* obj_ins)
+{
+ uint32 slot;
+ LIns* v_ins;
+ if (!prop(obj, obj_ins, slot, v_ins))
+ return false;
+
+ const JSCodeSpec& cs = js_CodeSpec[*cx->fp->regs->pc];
+ JS_ASSERT(cs.ndefs == 1);
+ stack(-cs.nuses, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::getProp(jsval& v)
+{
+ if (JSVAL_IS_PRIMITIVE(v))
+ ABORT_TRACE("primitive lhs");
+
+ return getProp(JSVAL_TO_OBJECT(v), get(&v));
+}
+
+bool
+TraceRecorder::record_JSOP_NAME()
+{
+ jsval* vp;
+ if (!name(vp))
+ return false;
+ stack(0, get(vp));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DOUBLE()
+{
+ jsval v = jsval(atoms[GET_INDEX(cx->fp->regs->pc)]);
+ jsdpun u;
+ u.d = *JSVAL_TO_DOUBLE(v);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_STRING()
+{
+ JSAtom* atom = atoms[GET_INDEX(cx->fp->regs->pc)];
+ JS_ASSERT(ATOM_IS_STRING(atom));
+ stack(0, INS_CONSTPTR(ATOM_TO_STRING(atom)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ZERO()
+{
+ jsdpun u;
+ u.d = 0.0;
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ONE()
+{
+ jsdpun u;
+ u.d = 1.0;
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NULL()
+{
+ stack(0, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_THIS()
+{
+ LIns* this_ins;
+ if (!getThis(this_ins))
+ return false;
+ stack(0, this_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_FALSE()
+{
+ stack(0, lir->insImm(0));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_TRUE()
+{
+ stack(0, lir->insImm(1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_OR()
+{
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_AND()
+{
+ return ifop();
+}
+
+bool
+TraceRecorder::record_JSOP_TABLESWITCH()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_LOOKUPSWITCH()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_STRICTEQ()
+{
+ return cmp(LIR_feq, CMP_STRICT);
+}
+
+bool
+TraceRecorder::record_JSOP_STRICTNE()
+{
+ return cmp(LIR_feq, CMP_STRICT | CMP_NEGATE);
+}
+
+bool
+TraceRecorder::record_JSOP_OBJECT()
+{
+ JSStackFrame* fp = cx->fp;
+ JSScript* script = fp->script;
+ unsigned index = atoms - script->atomMap.vector + GET_INDEX(fp->regs->pc);
+
+ JSObject* obj;
+ JS_GET_SCRIPT_OBJECT(script, index, obj);
+ stack(0, INS_CONSTPTR(obj));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_POP()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_POS()
+{
+ jsval& r = stackval(-1);
+ return isNumber(r);
+}
+
+bool
+TraceRecorder::record_JSOP_TRAP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETARG()
+{
+ stack(0, arg(GET_ARGNO(cx->fp->regs->pc)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETARG()
+{
+ arg(GET_ARGNO(cx->fp->regs->pc), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GETLOCAL()
+{
+ stack(0, var(GET_SLOTNO(cx->fp->regs->pc)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETLOCAL()
+{
+ var(GET_SLOTNO(cx->fp->regs->pc), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_UINT16()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_UINT16(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NEWINIT()
+{
+ JSProtoKey key = JSProtoKey(GET_INT8(cx->fp->regs->pc));
+ JSObject* obj;
+ const CallInfo *ci;
+ if (key == JSProto_Array) {
+ if (!js_GetClassPrototype(cx, globalObj, INT_TO_JSID(key), &obj))
+ return false;
+ ci = &js_FastNewArray_ci;
+ } else {
+ jsval v_obj;
+ if (!js_FindClassObject(cx, globalObj, INT_TO_JSID(key), &v_obj))
+ return false;
+ if (JSVAL_IS_PRIMITIVE(v_obj))
+ ABORT_TRACE("primitive Object value");
+ obj = JSVAL_TO_OBJECT(v_obj);
+ ci = &js_FastNewObject_ci;
+ }
+ LIns* args[] = { INS_CONSTPTR(obj), cx_ins };
+ LIns* v_ins = lir->insCall(ci, args);
+ guard(false, lir->ins_eq0(v_ins), OOM_EXIT);
+ stack(0, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ENDINIT()
+{
+ jsval& v = stackval(-1);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ JSObject* obj = JSVAL_TO_OBJECT(v);
+ if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
+ // Until we get JSOP_NEWARRAY working, we do our optimizing here...
+ if (obj->fslots[JSSLOT_ARRAY_LENGTH] == 1 &&
+ obj->dslots && JSVAL_IS_STRING(obj->dslots[0])) {
+ LIns* v_ins = get(&v);
+ JS_ASSERT(v_ins->isCall() && v_ins->callInfo() == &js_FastNewArray_ci);
+ LIns* args[] = { stack(1), callArgN(v_ins, 1), cx_ins };
+ v_ins = lir->insCall(&js_Array_1str_ci, args);
+ set(&v, v_ins);
+ }
+ }
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INITPROP()
+{
+ // All the action is in record_SetPropHit.
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INITELEM()
+{
+ return record_JSOP_SETELEM();
+}
+
+bool
+TraceRecorder::record_JSOP_DEFSHARP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_USESHARP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_INCARG()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), 1);
+}
+
+bool
+TraceRecorder::record_JSOP_INCLOCAL()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), 1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECARG()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), -1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECLOCAL()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), -1);
+}
+
+bool
+TraceRecorder::record_JSOP_ARGINC()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), 1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_LOCALINC()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), 1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_ARGDEC()
+{
+ return inc(argval(GET_ARGNO(cx->fp->regs->pc)), -1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_LOCALDEC()
+{
+ return inc(varval(GET_SLOTNO(cx->fp->regs->pc)), -1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_IMACOP()
+{
+ JS_ASSERT(cx->fp->imacpc);
+ return true;
+}
+
+static struct {
+ jsbytecode for_in[10];
+ jsbytecode for_each[10];
+} iter_imacros = {
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
+ JSOP_INT8, JSITER_ENUMERATE,
+ JSOP_CALL, 0, 1,
+ JSOP_PUSH,
+ JSOP_STOP
+ },
+
+ {
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(iterator),
+ JSOP_INT8, JSITER_ENUMERATE | JSITER_FOREACH,
+ JSOP_CALL, 0, 1,
+ JSOP_PUSH,
+ JSOP_STOP
+ }
+};
+
+JS_STATIC_ASSERT(sizeof(iter_imacros) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::record_JSOP_ITER()
+{
+ jsval& v = stackval(-1);
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ jsuint flags = cx->fp->regs->pc[1];
+
+ if (!hasIteratorMethod(v)) {
+ LIns* args[] = { get(&v), INS_CONST(flags), cx_ins };
+ LIns* v_ins = lir->insCall(&js_FastValueToIterator_ci, args);
+ guard(false, lir->ins_eq0(v_ins), MISMATCH_EXIT);
+ set(&v, v_ins);
+
+ LIns* void_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ stack(0, void_ins);
+ return true;
+ }
+
+ if (flags == JSITER_ENUMERATE)
+ return call_imacro(iter_imacros.for_in);
+ if (flags == (JSITER_ENUMERATE | JSITER_FOREACH))
+ return call_imacro(iter_imacros.for_each);
+ ABORT_TRACE("unimplemented JSITER_* flags");
+ }
+
+ ABORT_TRACE("for-in on a primitive value");
+}
+
+static JSTraceableNative js_FastCallIteratorNext_tn = {
+ NULL, // JSFastNative native;
+ &js_FastCallIteratorNext_ci, // const nanojit::CallInfo *builtin;
+ "C", // const char *prefix;
+ "o", // const char *argtypes;
+ FAIL_JSVAL // uintN flags;
+};
+
+static jsbytecode nextiter_imacro[] = {
+ JSOP_POP,
+ JSOP_DUP,
+ JSOP_CALLPROP, 0, COMMON_ATOM_INDEX(next),
+ JSOP_CALL, 0, 0,
+ JSOP_TRUE,
+ JSOP_STOP
+};
+
+JS_STATIC_ASSERT(sizeof(nextiter_imacro) < IMACRO_PC_ADJ_LIMIT);
+
+bool
+TraceRecorder::record_JSOP_NEXTITER()
+{
+ jsval& iterobj_val = stackval(-2);
+ if (!JSVAL_IS_PRIMITIVE(iterobj_val)) {
+ LIns* iterobj_ins = get(&iterobj_val);
+
+ if (guardClass(JSVAL_TO_OBJECT(iterobj_val), iterobj_ins, &js_IteratorClass, BRANCH_EXIT)) {
+ LIns* args[] = { iterobj_ins, cx_ins };
+ LIns* v_ins = lir->insCall(&js_FastCallIteratorNext_ci, args);
+ guard(false, lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_ERROR_COOKIE)), OOM_EXIT);
+
+ LIns* flag_ins = lir->ins_eq0(lir->ins2(LIR_eq, v_ins, INS_CONST(JSVAL_HOLE)));
+ stack(-1, v_ins);
+ stack(0, flag_ins);
+
+ pendingTraceableNative = &js_FastCallIteratorNext_tn;
+ return true;
+ }
+
+ // Custom iterator, possibly a generator.
+ return call_imacro(nextiter_imacro);
+ }
+
+ ABORT_TRACE("for-in on a primitive value");
+}
+
+bool
+TraceRecorder::record_IteratorNextComplete()
+{
+ JS_ASSERT(*cx->fp->regs->pc == JSOP_NEXTITER);
+ JS_ASSERT(pendingTraceableNative == &js_FastCallIteratorNext_tn);
+
+ jsval& v = stackval(-2);
+ LIns* v_ins = get(&v);
+ if (unbox_jsval(v, v_ins)) {
+ set(&v, v_ins);
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENDITER()
+{
+ LIns* args[] = { stack(-2), cx_ins };
+ LIns* ok_ins = lir->insCall(&js_CloseIterator_ci, args);
+ guard(false, lir->ins_eq0(ok_ins), MISMATCH_EXIT);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_FORNAME()
+{
+ jsval* vp;
+ if (name(vp)) {
+ set(vp, stack(-1));
+ return true;
+ }
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_FORPROP()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_FORELEM()
+{
+ return record_JSOP_DUP();
+}
+
+bool
+TraceRecorder::record_JSOP_FORARG()
+{
+ return record_JSOP_SETARG();
+}
+
+bool
+TraceRecorder::record_JSOP_FORLOCAL()
+{
+ return record_JSOP_SETLOCAL();
+}
+
+bool
+TraceRecorder::record_JSOP_POPN()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_BINDNAME()
+{
+ JSObject* obj = cx->fp->scopeChain;
+ if (obj != globalObj)
+ ABORT_TRACE("JSOP_BINDNAME crosses global scopes");
+
+ LIns* obj_ins = scopeChain();
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+ if (obj2 != obj)
+ ABORT_TRACE("JSOP_BINDNAME found a non-direct property on the global object");
+
+ stack(0, obj_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETNAME()
+{
+ jsval& l = stackval(-2);
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(l));
+
+ /*
+ * Trace cases that are global code or in lightweight functions scoped by
+ * the global object only.
+ */
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (obj != cx->fp->scopeChain || obj != globalObj)
+ ABORT_TRACE("JSOP_SETNAME left operand is not the global object");
+
+ // The rest of the work is in record_SetPropHit.
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_THROW()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_IN()
+{
+ jsval& rval = stackval(-1);
+ jsval& lval = stackval(-2);
+
+ if (JSVAL_IS_PRIMITIVE(rval))
+ ABORT_TRACE("JSOP_IN on non-object right operand");
+ JSObject* obj = JSVAL_TO_OBJECT(rval);
+ LIns* obj_ins = get(&rval);
+
+ jsid id;
+ LIns* x;
+ if (JSVAL_IS_INT(lval)) {
+ id = INT_JSVAL_TO_JSID(lval);
+ LIns* args[] = { makeNumberInt32(get(&lval)), obj_ins, cx_ins };
+ x = lir->insCall(&js_HasNamedPropertyInt32_ci, args);
+ } else if (JSVAL_IS_STRING(lval)) {
+ if (!js_ValueToStringId(cx, lval, &id))
+ ABORT_TRACE("left operand of JSOP_IN didn't convert to a string-id");
+ LIns* args[] = { get(&lval), obj_ins, cx_ins };
+ x = lir->insCall(&js_HasNamedProperty_ci, args);
+ } else {
+ ABORT_TRACE("string or integer expected");
+ }
+
+ guard(false, lir->ins2i(LIR_eq, x, JSVAL_TO_BOOLEAN(JSVAL_VOID)), OOM_EXIT);
+ x = lir->ins2i(LIR_eq, x, 1);
+
+ JSObject* obj2;
+ JSProperty* prop;
+ if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))
+ ABORT_TRACE("OBJ_LOOKUP_PROPERTY failed in JSOP_IN");
+ bool cond = prop != NULL;
+ if (prop)
+ OBJ_DROP_PROPERTY(cx, obj2, prop);
+
+ /* The interpreter fuses comparisons and the following branch,
+ so we have to do that here as well. */
+ fuseIf(cx->fp->regs->pc + 1, cond, x);
+
+ /* We update the stack after the guard. This is safe since
+ the guard bails out at the comparison and the interpreter
+ will therefore re-execute the comparison. This way the
+ value of the condition doesn't have to be calculated and
+ saved on the stack in most cases. */
+ set(&lval, x);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INSTANCEOF()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEBUGGER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GOSUB()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_RETSUB()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_EXCEPTION()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LINENO()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CONDSWITCH()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CASE()
+{
+ return cmp(LIR_feq, CMP_CASE);
+}
+
+bool
+TraceRecorder::record_JSOP_DEFAULT()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_EVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENUMELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFFUN()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFCONST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFVAR()
+{
+ return false;
+}
+
+/*
+ * XXX could hoist out to jsinterp.h and share with jsinterp.cpp, but
+ * XXX jsopcode.cpp has different definitions of same-named macros.
+ */
+#define GET_FULL_INDEX(PCOFF) \
+ (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))
+
+#define LOAD_FUNCTION(PCOFF) \
+ JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)
+
+bool
+TraceRecorder::record_JSOP_ANONFUNOBJ()
+{
+ JSFunction* fun;
+ JSFrameRegs& regs = *cx->fp->regs;
+ JSScript* script = cx->fp->script;
+ LOAD_FUNCTION(0); // needs script, regs, fun
+
+ JSObject* obj = FUN_OBJECT(fun);
+ if (OBJ_GET_PARENT(cx, obj) != cx->fp->scopeChain)
+ ABORT_TRACE("can't trace with activation object on scopeChain");
+
+ stack(0, INS_CONSTPTR(obj));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NAMEDFUNOBJ()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETLOCALPOP()
+{
+ var(GET_SLOTNO(cx->fp->regs->pc), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETCALL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TRY()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_FINALLY()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NOP()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_ARGSUB()
+{
+ JSStackFrame* fp = cx->fp;
+ if (!(fp->fun->flags & JSFUN_HEAVYWEIGHT)) {
+ uintN slot = GET_ARGNO(fp->regs->pc);
+ if (slot < fp->fun->nargs && slot < fp->argc && !fp->argsobj) {
+ stack(0, get(&cx->fp->argv[slot]));
+ return true;
+ }
+ }
+ ABORT_TRACE("can't trace JSOP_ARGSUB hard case");
+}
+
+bool
+TraceRecorder::record_JSOP_ARGCNT()
+{
+ if (!(cx->fp->fun->flags & JSFUN_HEAVYWEIGHT)) {
+ jsdpun u;
+ u.d = cx->fp->argc;
+ stack(0, lir->insImmq(u.u64));
+ return true;
+ }
+ ABORT_TRACE("can't trace heavyweight JSOP_ARGCNT");
+}
+
+bool
+TraceRecorder::record_DefLocalFunSetSlot(uint32 slot, JSObject* obj)
+{
+ var(slot, INS_CONSTPTR(obj));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DEFLOCALFUN()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GOTOX()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_IFEQX()
+{
+ trackCfgMerges(cx->fp->regs->pc);
+ return record_JSOP_IFEQ();
+}
+
+bool
+TraceRecorder::record_JSOP_IFNEX()
+{
+ return record_JSOP_IFNE();
+}
+
+bool
+TraceRecorder::record_JSOP_ORX()
+{
+ return record_JSOP_OR();
+}
+
+bool
+TraceRecorder::record_JSOP_ANDX()
+{
+ return record_JSOP_AND();
+}
+
+bool
+TraceRecorder::record_JSOP_GOSUBX()
+{
+ return record_JSOP_GOSUB();
+}
+
+bool
+TraceRecorder::record_JSOP_CASEX()
+{
+ return cmp(LIR_feq, CMP_CASE);
+}
+
+bool
+TraceRecorder::record_JSOP_DEFAULTX()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_TABLESWITCHX()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_LOOKUPSWITCHX()
+{
+ return switchop();
+}
+
+bool
+TraceRecorder::record_JSOP_BACKPATCH()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_BACKPATCH_POP()
+{
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_THROWING()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETRVAL()
+{
+ // If we implement this, we need to update JSOP_STOP.
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_RETRVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_NAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ stack(0, get(&STOBJ_GET_SLOT(globalObj, slot)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_SETGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_NAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ set(&STOBJ_GET_SLOT(globalObj, slot), stack(-1));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INCGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), 1);
+}
+
+bool
+TraceRecorder::record_JSOP_DECGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), -1);
+}
+
+bool
+TraceRecorder::record_JSOP_GVARINC()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), 1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_GVARDEC()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_INCNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ return inc(STOBJ_GET_SLOT(globalObj, slot), -1, false);
+}
+
+bool
+TraceRecorder::record_JSOP_REGEXP()
+{
+ return false;
+}
+
+// begin JS_HAS_XML_SUPPORT
+
+bool
+TraceRecorder::record_JSOP_DEFXMLNS()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ANYNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_QNAMEPART()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_QNAMECONST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_QNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOATTRNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOATTRVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ADDATTRNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ADDATTRVAL()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_BINDXMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_SETXMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_DESCENDANTS()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_FILTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENDFILTER()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOXML()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TOXMLLIST()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLTAGEXPR()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLELTEXPR()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLOBJECT()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLCDATA()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLCOMMENT()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_XMLPI()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETFUNNS()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_STARTXML()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_STARTXMLEXPR()
+{
+ return false;
+}
+
+// end JS_HAS_XML_SUPPORT
+
+bool
+TraceRecorder::record_JSOP_CALLPROP()
+{
+ jsval& l = stackval(-1);
+ JSObject* obj;
+ LIns* obj_ins;
+ LIns* this_ins;
+ if (!JSVAL_IS_PRIMITIVE(l)) {
+ obj = JSVAL_TO_OBJECT(l);
+ obj_ins = get(&l);
+ this_ins = obj_ins; // |this| for subsequent call
+ if (JSVAL_IS_NULL(l))
+ ABORT_TRACE("callprop on null");
+ if (!this_ins->isconstp())
+ guard(false, lir->ins_eq0(this_ins), MISMATCH_EXIT);
+ } else {
+ jsint i;
+ debug_only(const char* protoname = NULL;)
+ if (JSVAL_IS_STRING(l)) {
+ i = JSProto_String;
+ debug_only(protoname = "String.prototype";)
+ } else if (JSVAL_IS_NUMBER(l)) {
+ i = JSProto_Number;
+ debug_only(protoname = "Number.prototype";)
+ } else if (JSVAL_TAG(l) == JSVAL_BOOLEAN) {
+ if (l == JSVAL_VOID)
+ ABORT_TRACE("callprop on void");
+ guard(false, lir->ins2i(LIR_eq, get(&l), JSVAL_TO_BOOLEAN(JSVAL_VOID)), MISMATCH_EXIT);
+ i = JSProto_Boolean;
+ debug_only(protoname = "Boolean.prototype";)
+ } else {
+ JS_ASSERT(JSVAL_IS_NULL(l) || JSVAL_IS_VOID(l));
+ ABORT_TRACE("callprop on null or void");
+ }
+
+ if (!js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj))
+ ABORT_TRACE("GetClassPrototype failed!");
+
+ obj_ins = INS_CONSTPTR(obj);
+ debug_only(obj_ins = addName(obj_ins, protoname);)
+ this_ins = get(&l); // use primitive as |this|
+ }
+
+ JSObject* obj2;
+ jsuword pcval;
+ if (!test_property_cache(obj, obj_ins, obj2, pcval))
+ return false;
+
+ if (PCVAL_IS_NULL(pcval) || !PCVAL_IS_OBJECT(pcval))
+ ABORT_TRACE("callee is not an object");
+ JS_ASSERT(HAS_FUNCTION_CLASS(PCVAL_TO_OBJECT(pcval)));
+
+ if (JSVAL_IS_PRIMITIVE(l)) {
+ JSFunction* fun = GET_FUNCTION_PRIVATE(cx, PCVAL_TO_OBJECT(pcval));
+ if (!PRIMITIVE_THIS_TEST(fun, l))
+ ABORT_TRACE("callee does not accept primitive |this|");
+ }
+
+ stack(0, this_ins);
+ stack(-1, INS_CONSTPTR(PCVAL_TO_OBJECT(pcval)));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_DELDESC()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_UINT24()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_UINT24(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE()
+{
+ atoms += GET_INDEXBASE(cx->fp->regs->pc);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_RESETBASE()
+{
+ atoms = cx->fp->script->atomMap.vector;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_RESETBASE0()
+{
+ atoms = cx->fp->script->atomMap.vector;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_STOP()
+{
+ JSStackFrame *fp = cx->fp;
+
+ if (fp->imacpc) {
+ // End of imacro, so return true to the interpreter immediately. The
+ // interpreter's JSOP_STOP case will return from the imacro, back to
+ // the pc after the calling op, still in the same JSStackFrame.
+ atoms = fp->script->atomMap.vector;
+ return true;
+ }
+
+ /*
+ * We know falling off the end of a constructor returns the new object that
+ * was passed in via fp->argv[-1], while falling off the end of a function
+ * returns undefined.
+ *
+ * NB: we do not support script rval (eval, API users who want the result
+ * of the last expression-statement, debugger API calls).
+ */
+ if (fp->flags & JSFRAME_CONSTRUCTING) {
+ JS_ASSERT(OBJECT_TO_JSVAL(fp->thisp) == fp->argv[-1]);
+ rval_ins = get(&fp->argv[-1]);
+ } else {
+ rval_ins = INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_VOID));
+ }
+ clearFrameSlotsFromCache();
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_GETXPROP()
+{
+ jsval& l = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(l))
+ ABORT_TRACE("primitive-this for GETXPROP?");
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (obj != cx->fp->scopeChain || obj != globalObj)
+ return false;
+
+ jsval* vp;
+ if (!name(vp))
+ return false;
+ stack(-1, get(vp));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLXMLNAME()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_TYPEOFEXPR()
+{
+ return record_JSOP_TYPEOF();
+}
+
+bool
+TraceRecorder::record_JSOP_ENTERBLOCK()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LEAVEBLOCK()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GENERATOR()
+{
+ return false;
+#if 0
+ JSStackFrame* fp = cx->fp;
+ if (fp->callobj || fp->argsobj || fp->varobj)
+ ABORT_TRACE("can't trace hard-case generator");
+
+ // Generate a type map for the outgoing frame and stash it in the LIR
+ unsigned stackSlots = js_NativeStackSlots(cx, 0/*callDepth*/);
+ LIns* data = lir_buf_writer->skip(stackSlots * sizeof(uint8));
+ uint8* typemap = (uint8 *)data->payload();
+ uint8* m = typemap;
+ /* Determine the type of a store by looking at the current type of the actual value the
+ interpreter is using. For numbers we have to check what kind of store we used last
+ (integer or double) to figure out what the side exit show reflect in its typemap. */
+ FORALL_SLOTS_IN_PENDING_FRAMES(cx, 0/*callDepth*/,
+ *m++ = determineSlotType(vp);
+ );
+ FlushNativeStackFrame(cx, 0, typemap, state.???, NULL);
+
+ LIns* args[] = { INS_CONST(fp->argc), INS_CONSTPTR(fp->callee), cx_ins };
+ LIns* g_ins = lir->insCall(&js_FastNewGenerator_ci, args);
+ guard(false, lir->ins_eq0(g_ins), OOM_EXIT);
+ return true;
+#endif
+}
+
+bool
+TraceRecorder::record_JSOP_YIELD()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ARRAYPUSH()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_ENUMCONSTELEM()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_LEAVEBLOCKEXPR()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_GETTHISPROP()
+{
+ LIns* this_ins;
+
+ /* its safe to just use cx->fp->thisp here because getThis() returns false if thisp
+ is not available */
+ return getThis(this_ins) && getProp(cx->fp->thisp, this_ins);
+}
+
+bool
+TraceRecorder::record_JSOP_GETARGPROP()
+{
+ return getProp(argval(GET_ARGNO(cx->fp->regs->pc)));
+}
+
+bool
+TraceRecorder::record_JSOP_GETLOCALPROP()
+{
+ return getProp(varval(GET_SLOTNO(cx->fp->regs->pc)));
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE1()
+{
+ atoms += 1 << 16;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE2()
+{
+ atoms += 2 << 16;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INDEXBASE3()
+{
+ atoms += 3 << 16;
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLGVAR()
+{
+ jsval slotval = cx->fp->slots[GET_SLOTNO(cx->fp->regs->pc)];
+ if (JSVAL_IS_NULL(slotval))
+ return true; // We will see JSOP_CALLNAME from the interpreter's jump, so no-op here.
+
+ uint32 slot = JSVAL_TO_INT(slotval);
+
+ if (!lazilyImportGlobalSlot(slot))
+ ABORT_TRACE("lazy import of global slot failed");
+
+ jsval& v = STOBJ_GET_SLOT(cx->fp->scopeChain, slot);
+ stack(0, get(&v));
+ stack(1, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLLOCAL()
+{
+ uintN slot = GET_SLOTNO(cx->fp->regs->pc);
+ stack(0, var(slot));
+ stack(1, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_CALLARG()
+{
+ uintN slot = GET_ARGNO(cx->fp->regs->pc);
+ stack(0, arg(slot));
+ stack(1, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NULLTHIS()
+{
+ stack(0, INS_CONSTPTR(NULL));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INT8()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_INT8(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_INT32()
+{
+ jsdpun u;
+ u.d = (jsdouble)GET_INT32(cx->fp->regs->pc);
+ stack(0, lir->insImmq(u.u64));
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_LENGTH()
+{
+ jsval& l = stackval(-1);
+ if (JSVAL_IS_PRIMITIVE(l)) {
+ if (!JSVAL_IS_STRING(l))
+ ABORT_TRACE("non-string primitives unsupported");
+ LIns* str_ins = get(&l);
+ LIns* len_ins = lir->insLoad(LIR_ldp, str_ins, (int)offsetof(JSString, length));
+
+ LIns* masked_len_ins = lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRING_LENGTH_MASK));
+
+ LIns *choose_len_ins =
+ lir->ins_choose(lir->ins_eq0(lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRFLAG_DEPENDENT))),
+ masked_len_ins,
+ lir->ins_choose(lir->ins_eq0(lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRFLAG_PREFIX))),
+ lir->ins2(LIR_piand,
+ len_ins,
+ INS_CONSTPTR(JSSTRDEP_LENGTH_MASK)),
+ masked_len_ins));
+
+ set(&l, lir->ins1(LIR_i2f, choose_len_ins));
+ return true;
+ }
+
+ JSObject* obj = JSVAL_TO_OBJECT(l);
+ if (!OBJ_IS_DENSE_ARRAY(cx, obj))
+ ABORT_TRACE("only dense arrays supported");
+ if (!guardDenseArray(obj, get(&l)))
+ ABORT_TRACE("OBJ_IS_DENSE_ARRAY but not?!?");
+ LIns* v_ins = lir->ins1(LIR_i2f, stobj_get_fslot(get(&l), JSSLOT_ARRAY_LENGTH));
+ set(&l, v_ins);
+ return true;
+}
+
+bool
+TraceRecorder::record_JSOP_NEWARRAY()
+{
+ return false;
+}
+
+bool
+TraceRecorder::record_JSOP_HOLE()
+{
+ stack(0, INS_CONST(JSVAL_TO_BOOLEAN(JSVAL_HOLE)));
+ return true;
+}
+
+#ifdef JS_JIT_SPEW
+/* Prints information about entry typemaps and unstable exits for all peers at a PC */
+void
+js_DumpPeerStability(Fragmento* frago, const void* ip)
+{
+ Fragment* f;
+ TreeInfo* ti;
+ bool looped = false;
+ unsigned length = 0;
+
+ for (f = frago->getLoop(ip); f != NULL; f = f->peer) {
+ if (!f->vmprivate)
+ continue;
+ printf("fragment %p:\nENTRY: ", f);
+ ti = (TreeInfo*)f->vmprivate;
+ if (looped)
+ JS_ASSERT(ti->stackTypeMap.length() == length);
+ for (unsigned i = 0; i < ti->stackTypeMap.length(); i++)
+ printf("%d ", ti->stackTypeMap.data()[i]);
+ printf("\n");
+ UnstableExit* uexit = ti->unstableExits;
+ while (uexit != NULL) {
+ printf("EXIT: ");
+ uint8* m = getTypeMap(uexit->exit) + uexit->exit->numGlobalSlots;
+ for (unsigned i = 0; i < uexit->exit->numStackSlots; i++)
+ printf("%d ", m[i]);
+ printf("\n");
+ uexit = uexit->next;
+ }
+ length = ti->stackTypeMap.length();
+ looped = true;
+ }
+}
+#endif
+
+/*
+ * 17 potentially-converting binary operators:
+ * | ^ & == != < <= > >= << >> >>> + - * / %
+ */
+JS_STATIC_ASSERT((uintN)(JSOP_MOD - JSOP_BITOR) == 16);
+
+/*
+ * Use an old <ctype.h> trick: bias imacro_code[op] by -1 to allow zero high
+ * FrameInfo.ip_adj byte to mean "not in an imacro".
+ */
+static void
+InitIMacroCode()
+{
+ if (imacro_code[JSOP_NEXTITER]) {
+ JS_ASSERT(imacro_code[JSOP_NEXTITER] == nextiter_imacro - 1);
+ return;
+ }
+
+ for (uintN op = JSOP_BITOR; op <= JSOP_MOD; op++)
+ imacro_code[op] = (jsbytecode*)&binary_imacros - 1;
+
+ // NB: above loop mis-set JSOP_ADD's entry, so order here is crucial.
+ imacro_code[JSOP_ADD] = (jsbytecode*)&add_imacros - 1;
+
+ imacro_code[JSOP_ITER] = (jsbytecode*)&iter_imacros - 1;
+ imacro_code[JSOP_NEXTITER] = nextiter_imacro - 1;
+}
+
+#define UNUSED(n) bool TraceRecorder::record_JSOP_UNUSED##n() { return false; }
+
+UNUSED(131)
+UNUSED(201)
+UNUSED(202)
+UNUSED(203)
+UNUSED(204)
+UNUSED(205)
+UNUSED(206)
+UNUSED(207)
+UNUSED(208)
+UNUSED(209)
+UNUSED(219)
+UNUSED(226)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jstracer.h b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.h
new file mode 100644
index 0000000..9295acb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jstracer.h
@@ -0,0 +1,552 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
+ * May 28, 2008.
+ *
+ * The Initial Developer of the Original Code is
+ * Brendan Eich <brendan@mozilla.org>
+ *
+ * Contributor(s):
+ * Andreas Gal <gal@mozilla.com>
+ * Mike Shaver <shaver@mozilla.org>
+ * David Anderson <danderson@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jstracer_h___
+#define jstracer_h___
+
+#ifdef JS_TRACER
+
+#include "jscntxt.h"
+#include "jsstddef.h"
+#include "jstypes.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsinterp.h"
+#include "jsbuiltins.h"
+
+#if defined(DEBUG) && !defined(JS_JIT_SPEW)
+#define JS_JIT_SPEW
+#endif
+
+template <typename T>
+class Queue : public avmplus::GCObject {
+ T* _data;
+ unsigned _len;
+ unsigned _max;
+
+ void ensure(unsigned size) {
+ while (_max < size)
+ _max <<= 1;
+ _data = (T*)realloc(_data, _max * sizeof(T));
+ }
+public:
+ Queue(unsigned max = 16) {
+ this->_max = max;
+ this->_len = 0;
+ this->_data = (T*)malloc(max * sizeof(T));
+ }
+
+ ~Queue() {
+ free(_data);
+ }
+
+ bool contains(T a) {
+ for (unsigned n = 0; n < _len; ++n)
+ if (_data[n] == a)
+ return true;
+ return false;
+ }
+
+ void add(T a) {
+ ensure(_len + 1);
+ JS_ASSERT(_len <= _max);
+ _data[_len++] = a;
+ }
+
+ void add(T* chunk, unsigned size) {
+ ensure(_len + size);
+ JS_ASSERT(_len <= _max);
+ memcpy(&_data[_len], chunk, size * sizeof(T));
+ _len += size;
+ }
+
+ void addUnique(T a) {
+ if (!contains(a))
+ add(a);
+ }
+
+ void setLength(unsigned len) {
+ ensure(len + 1);
+ _len = len;
+ }
+
+ void clear() {
+ _len = 0;
+ }
+
+ unsigned length() const {
+ return _len;
+ }
+
+ T* data() const {
+ return _data;
+ }
+};
+
+/*
+ * Tracker is used to keep track of values being manipulated by the interpreter
+ * during trace recording.
+ */
+class Tracker {
+ struct Page {
+ struct Page* next;
+ jsuword base;
+ nanojit::LIns* map[1];
+ };
+ struct Page* pagelist;
+
+ jsuword getPageBase(const void* v) const;
+ struct Page* findPage(const void* v) const;
+ struct Page* addPage(const void* v);
+public:
+ Tracker();
+ ~Tracker();
+
+ bool has(const void* v) const;
+ nanojit::LIns* get(const void* v) const;
+ void set(const void* v, nanojit::LIns* ins);
+ void clear();
+};
+
+/*
+ * The oracle keeps track of slots that should not be demoted to int because we know them
+ * to overflow or they result in type-unstable traces. We are using a simple hash table.
+ * Collisions lead to loss of optimization (demotable slots are not demoted) but have no
+ * correctness implications.
+ */
+#define ORACLE_SIZE 4096
+
+class Oracle {
+ avmplus::BitSet _dontDemote;
+public:
+ void markGlobalSlotUndemotable(JSScript* script, unsigned slot);
+ bool isGlobalSlotUndemotable(JSScript* script, unsigned slot) const;
+ void markStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot);
+ bool isStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot) const;
+ void clear();
+};
+
+typedef Queue<uint16> SlotList;
+
+class TypeMap : public Queue<uint8> {
+public:
+ void captureGlobalTypes(JSContext* cx, SlotList& slots);
+ void captureStackTypes(JSContext* cx, unsigned callDepth);
+ bool matches(TypeMap& other) const;
+};
+
+enum ExitType {
+ BRANCH_EXIT,
+ LOOP_EXIT,
+ NESTED_EXIT,
+ MISMATCH_EXIT,
+ OOM_EXIT,
+ OVERFLOW_EXIT,
+ UNSTABLE_LOOP_EXIT,
+ TIMEOUT_EXIT
+};
+
+struct VMSideExit : public nanojit::SideExit
+{
+ intptr_t ip_adj;
+ intptr_t sp_adj;
+ intptr_t rp_adj;
+ int32_t calldepth;
+ uint32 numGlobalSlots;
+ uint32 numStackSlots;
+ uint32 numStackSlotsBelowCurrentFrame;
+ ExitType exitType;
+};
+
+static inline uint8* getTypeMap(nanojit::SideExit* exit)
+{
+ return (uint8*)(((VMSideExit*)exit) + 1);
+}
+
+struct InterpState
+{
+ void* sp; /* native stack pointer, stack[0] is spbase[0] */
+ void* rp; /* call stack pointer */
+ void* gp; /* global frame pointer */
+ JSContext *cx; /* current VM context handle */
+ void* eos; /* first unusable word after the native stack */
+ void* eor; /* first unusable word after the call stack */
+ VMSideExit* lastTreeExitGuard; /* guard we exited on during a tree call */
+ VMSideExit* lastTreeCallGuard; /* guard we want to grow from if the tree
+ call exit guard mismatched */
+ void* rpAtLastTreeCall; /* value of rp at innermost tree call guard */
+};
+
+struct UnstableExit
+{
+ nanojit::Fragment* fragment;
+ VMSideExit* exit;
+ UnstableExit* next;
+};
+
+class TreeInfo MMGC_SUBCLASS_DECL {
+ nanojit::Fragment* fragment;
+public:
+ JSScript* script;
+ unsigned maxNativeStackSlots;
+ ptrdiff_t nativeStackBase;
+ unsigned maxCallDepth;
+ TypeMap stackTypeMap;
+ Queue<nanojit::Fragment*> dependentTrees;
+ unsigned branchCount;
+ Queue<VMSideExit*> sideExits;
+ UnstableExit* unstableExits;
+
+ TreeInfo(nanojit::Fragment* _fragment) : unstableExits(NULL) {
+ fragment = _fragment;
+ }
+ ~TreeInfo();
+};
+
+struct FrameInfo {
+ JSObject* callee; // callee function object
+ intptr_t ip_adj; // callee script-based pc index and imacro pc
+ uint8* typemap; // typemap for the stack frame
+ union {
+ struct {
+ uint16 spdist; // distance from fp->slots to fp->regs->sp at JSOP_CALL
+ uint16 argc; // actual argument count, may be < fun->nargs
+ } s;
+ uint32 word; // for spdist/argc LIR store in record_JSOP_CALL
+ };
+};
+
+class TraceRecorder : public avmplus::GCObject {
+ JSContext* cx;
+ JSTraceMonitor* traceMonitor;
+ JSObject* globalObj;
+ Tracker tracker;
+ Tracker nativeFrameTracker;
+ char* entryTypeMap;
+ unsigned callDepth;
+ JSAtom** atoms;
+ VMSideExit* anchor;
+ nanojit::Fragment* fragment;
+ TreeInfo* treeInfo;
+ nanojit::LirBuffer* lirbuf;
+ nanojit::LirWriter* lir;
+ nanojit::LirBufWriter* lir_buf_writer;
+ nanojit::LirWriter* verbose_filter;
+ nanojit::LirWriter* cse_filter;
+ nanojit::LirWriter* expr_filter;
+ nanojit::LirWriter* func_filter;
+#ifdef NJ_SOFTFLOAT
+ nanojit::LirWriter* float_filter;
+#endif
+ nanojit::LIns* cx_ins;
+ nanojit::LIns* gp_ins;
+ nanojit::LIns* eos_ins;
+ nanojit::LIns* eor_ins;
+ nanojit::LIns* rval_ins;
+ nanojit::LIns* inner_sp_ins;
+ bool deepAborted;
+ bool applyingArguments;
+ bool trashTree;
+ nanojit::Fragment* whichTreeToTrash;
+ Queue<jsbytecode*> cfgMerges;
+ jsval* global_dslots;
+ JSTraceableNative* pendingTraceableNative;
+ bool terminate;
+ intptr_t terminate_ip_adj;
+ nanojit::Fragment* outerToBlacklist;
+ nanojit::Fragment* promotedPeer;
+ TraceRecorder* nextRecorderToAbort;
+ bool wasRootFragment;
+
+ bool isGlobal(jsval* p) const;
+ ptrdiff_t nativeGlobalOffset(jsval* p) const;
+ ptrdiff_t nativeStackOffset(jsval* p) const;
+ void import(nanojit::LIns* base, ptrdiff_t offset, jsval* p, uint8& t,
+ const char *prefix, uintN index, JSStackFrame *fp);
+ void import(TreeInfo* treeInfo, nanojit::LIns* sp, unsigned ngslots, unsigned callDepth,
+ uint8* globalTypeMap, uint8* stackTypeMap);
+ void trackNativeStackUse(unsigned slots);
+
+ bool lazilyImportGlobalSlot(unsigned slot);
+
+ nanojit::LIns* guard(bool expected, nanojit::LIns* cond, ExitType exitType);
+ nanojit::LIns* guard(bool expected, nanojit::LIns* cond, nanojit::LIns* exit);
+ nanojit::LIns* addName(nanojit::LIns* ins, const char* name);
+
+ nanojit::LIns* get(jsval* p) const;
+ nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset);
+ void set(jsval* p, nanojit::LIns* l, bool initializing = false);
+
+ bool checkType(jsval& v, uint8 t, jsval*& stage_val, nanojit::LIns*& stage_ins,
+ unsigned& stage_count);
+ bool deduceTypeStability(nanojit::Fragment* root_peer, nanojit::Fragment** stable_peer,
+ unsigned* demotes);
+
+ jsval& argval(unsigned n) const;
+ jsval& varval(unsigned n) const;
+ jsval& stackval(int n) const;
+
+ nanojit::LIns* scopeChain() const;
+ bool activeCallOrGlobalSlot(JSObject* obj, jsval*& vp);
+
+ nanojit::LIns* arg(unsigned n);
+ void arg(unsigned n, nanojit::LIns* i);
+ nanojit::LIns* var(unsigned n);
+ void var(unsigned n, nanojit::LIns* i);
+ nanojit::LIns* stack(int n);
+ void stack(int n, nanojit::LIns* i);
+
+ nanojit::LIns* alu(nanojit::LOpcode op, jsdouble v0, jsdouble v1,
+ nanojit::LIns* s0, nanojit::LIns* s1);
+ nanojit::LIns* f2i(nanojit::LIns* f);
+ nanojit::LIns* makeNumberInt32(nanojit::LIns* f);
+ nanojit::LIns* stringify(jsval& v);
+
+ bool call_imacro(jsbytecode* imacro);
+
+ bool ifop();
+ bool switchop();
+ bool inc(jsval& v, jsint incr, bool pre = true);
+ bool inc(jsval& v, nanojit::LIns*& v_ins, jsint incr, bool pre = true);
+ bool incProp(jsint incr, bool pre = true);
+ bool incElem(jsint incr, bool pre = true);
+ bool incName(jsint incr, bool pre = true);
+
+ enum { CMP_NEGATE = 1, CMP_TRY_BRANCH_AFTER_COND = 2, CMP_CASE = 4, CMP_STRICT = 8 };
+ bool cmp(nanojit::LOpcode op, int flags = 0);
+
+ bool unary(nanojit::LOpcode op);
+ bool binary(nanojit::LOpcode op);
+
+ bool ibinary(nanojit::LOpcode op);
+ bool iunary(nanojit::LOpcode op);
+ bool bbinary(nanojit::LOpcode op);
+ void demote(jsval& v, jsdouble result);
+
+ bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins, nanojit::LIns*& ops_ins,
+ size_t op_offset = 0);
+ bool test_property_cache(JSObject* obj, nanojit::LIns* obj_ins, JSObject*& obj2,
+ jsuword& pcval);
+ bool test_property_cache_direct_slot(JSObject* obj, nanojit::LIns* obj_ins, uint32& slot);
+ void stobj_set_slot(nanojit::LIns* obj_ins, unsigned slot,
+ nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
+ nanojit::LIns* stobj_get_fslot(nanojit::LIns* obj_ins, unsigned slot);
+ nanojit::LIns* stobj_get_slot(nanojit::LIns* obj_ins, unsigned slot,
+ nanojit::LIns*& dslots_ins);
+ bool native_set(nanojit::LIns* obj_ins, JSScopeProperty* sprop,
+ nanojit::LIns*& dslots_ins, nanojit::LIns* v_ins);
+ bool native_get(nanojit::LIns* obj_ins, nanojit::LIns* pobj_ins, JSScopeProperty* sprop,
+ nanojit::LIns*& dslots_ins, nanojit::LIns*& v_ins);
+
+ bool name(jsval*& vp);
+ bool prop(JSObject* obj, nanojit::LIns* obj_ins, uint32& slot, nanojit::LIns*& v_ins);
+ bool elem(jsval& oval, jsval& idx, jsval*& vp, nanojit::LIns*& v_ins, nanojit::LIns*& addr_ins);
+
+ bool getProp(JSObject* obj, nanojit::LIns* obj_ins);
+ bool getProp(jsval& v);
+ bool getThis(nanojit::LIns*& this_ins);
+
+ bool box_jsval(jsval v, nanojit::LIns*& v_ins);
+ bool unbox_jsval(jsval v, nanojit::LIns*& v_ins);
+ bool guardClass(JSObject* obj, nanojit::LIns* obj_ins, JSClass* clasp,
+ ExitType exitType = MISMATCH_EXIT);
+ bool guardDenseArray(JSObject* obj, nanojit::LIns* obj_ins,
+ ExitType exitType = MISMATCH_EXIT);
+ bool guardDenseArrayIndex(JSObject* obj, jsint idx, nanojit::LIns* obj_ins,
+ nanojit::LIns* dslots_ins, nanojit::LIns* idx_ins,
+ ExitType exitType);
+ bool guardElemOp(JSObject* obj, nanojit::LIns* obj_ins, jsid id, size_t op_offset, jsval* vp);
+ void clearFrameSlotsFromCache();
+ bool guardShapelessCallee(jsval& callee);
+ bool interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc, bool constructing);
+ bool functionCall(bool constructing);
+
+ void trackCfgMerges(jsbytecode* pc);
+ void flipIf(jsbytecode* pc, bool& cond);
+ void fuseIf(jsbytecode* pc, bool cond, nanojit::LIns* x);
+
+ bool hasMethod(JSObject* obj, jsid id);
+ bool hasToStringMethod(JSObject* obj);
+ bool hasToStringMethod(jsval v) {
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ return hasToStringMethod(JSVAL_TO_OBJECT(v));
+ }
+ bool hasValueOfMethod(JSObject* obj);
+ bool hasValueOfMethod(jsval v) {
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ return hasValueOfMethod(JSVAL_TO_OBJECT(v));
+ }
+ bool hasIteratorMethod(JSObject* obj);
+ bool hasIteratorMethod(jsval v) {
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ return hasIteratorMethod(JSVAL_TO_OBJECT(v));
+ }
+
+public:
+ friend bool js_MonitorRecording(TraceRecorder* tr);
+
+ TraceRecorder(JSContext* cx, VMSideExit*, nanojit::Fragment*, TreeInfo*,
+ unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
+ VMSideExit* expectedInnerExit, nanojit::Fragment* outerToBlacklist);
+ ~TraceRecorder();
+
+ uint8 determineSlotType(jsval* vp) const;
+ nanojit::LIns* snapshot(ExitType exitType);
+ nanojit::Fragment* getFragment() const { return fragment; }
+ bool isLoopHeader(JSContext* cx) const;
+ void compile(nanojit::Fragmento* fragmento);
+ bool closeLoop(nanojit::Fragmento* fragmento, bool& demote, unsigned *demotes);
+ void endLoop(nanojit::Fragmento* fragmento);
+ void joinEdgesToEntry(nanojit::Fragmento* fragmento, nanojit::Fragment* peer_root);
+ void blacklist() { fragment->blacklist(); }
+ bool adjustCallerTypes(nanojit::Fragment* f, unsigned* demote_slots, bool& trash);
+ nanojit::Fragment* findNestedCompatiblePeer(nanojit::Fragment* f, nanojit::Fragment** empty);
+ void prepareTreeCall(nanojit::Fragment* inner);
+ void emitTreeCall(nanojit::Fragment* inner, VMSideExit* exit);
+ unsigned getCallDepth() const;
+ void pushAbortStack();
+ void popAbortStack();
+ void removeFragmentoReferences();
+
+ bool record_EnterFrame();
+ bool record_LeaveFrame();
+ bool record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop);
+ bool record_SetPropMiss(JSPropCacheEntry* entry);
+ bool record_DefLocalFunSetSlot(uint32 slot, JSObject* obj);
+ bool record_FastNativeCallComplete();
+ bool record_IteratorNextComplete();
+
+ nanojit::Fragment* getOuterToBlacklist() { return outerToBlacklist; }
+ void deepAbort() { deepAborted = true; }
+ bool wasDeepAborted() { return deepAborted; }
+ bool walkedOutOfLoop() { return terminate; }
+ void setPromotedPeer(nanojit::Fragment* peer) { promotedPeer = peer; }
+ TreeInfo* getTreeInfo() { return treeInfo; }
+
+#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
+ bool record_##op();
+# include "jsopcode.tbl"
+#undef OPDEF
+};
+
+#define TRACING_ENABLED(cx) JS_HAS_OPTION(cx, JSOPTION_JIT)
+#define TRACE_RECORDER(cx) (JS_TRACE_MONITOR(cx).recorder)
+#define SET_TRACE_RECORDER(cx,tr) (JS_TRACE_MONITOR(cx).recorder = (tr))
+
+#define JSOP_IS_BINARY(op) ((uintN)((op) - JSOP_BITOR) <= (uintN)(JSOP_MOD - JSOP_BITOR))
+
+/*
+ * See jsinterp.cpp for the ENABLE_TRACER definition. Also note how comparing x
+ * to JSOP_* constants specializes trace-recording code at compile time either
+ * to include imacro support, or exclude it altogether for this particular x.
+ *
+ * We save macro-generated code size also via bool TraceRecorder::record_JSOP_*
+ * return type, instead of a three-state: OK, ABORTED, IMACRO_STARTED. But the
+ * price of this is the JSFRAME_IMACRO_START frame flag. We need one more bit
+ * to detect that TraceRecorder::call_imacro was invoked by the record_JSOP_*
+ * method invoked by TRACE_ARGS_.
+ */
+#define RECORD_ARGS(x,args) \
+ JS_BEGIN_MACRO \
+ if (!js_MonitorRecording(TRACE_RECORDER(cx))) { \
+ ENABLE_TRACER(0); \
+ } else { \
+ TRACE_ARGS_(x, args, \
+ if ((fp->flags & JSFRAME_IMACRO_START) && \
+ (x == JSOP_ITER || x == JSOP_NEXTITER || \
+ JSOP_IS_BINARY(x))) { \
+ fp->flags &= ~JSFRAME_IMACRO_START; \
+ atoms = COMMON_ATOMS_START(&rt->atomState); \
+ op = JSOp(*regs.pc); \
+ DO_OP(); \
+ } \
+ ); \
+ } \
+ JS_END_MACRO
+
+#define TRACE_ARGS_(x,args,onfalse) \
+ JS_BEGIN_MACRO \
+ TraceRecorder* tr_ = TRACE_RECORDER(cx); \
+ if (tr_ && !tr_->record_##x args) { \
+ onfalse \
+ js_AbortRecording(cx, #x); \
+ ENABLE_TRACER(0); \
+ } \
+ JS_END_MACRO
+
+#define TRACE_ARGS(x,args) TRACE_ARGS_(x, args, )
+
+#define RECORD(x) RECORD_ARGS(x, ())
+#define TRACE_0(x) TRACE_ARGS(x, ())
+#define TRACE_1(x,a) TRACE_ARGS(x, (a))
+#define TRACE_2(x,a,b) TRACE_ARGS(x, (a, b))
+
+extern bool
+js_MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount);
+
+extern bool
+js_MonitorRecording(TraceRecorder *tr);
+
+extern void
+js_AbortRecording(JSContext* cx, const char* reason);
+
+extern void
+js_InitJIT(JSTraceMonitor *tm);
+
+extern void
+js_FinishJIT(JSTraceMonitor *tm);
+
+extern void
+js_FlushJITCache(JSContext* cx);
+
+extern void
+js_FlushJITOracle(JSContext* cx);
+
+#else /* !JS_TRACER */
+
+#define RECORD(x) ((void)0)
+#define TRACE_0(x) ((void)0)
+#define TRACE_1(x,a) ((void)0)
+#define TRACE_2(x,a,b) ((void)0)
+
+#endif /* !JS_TRACER */
+
+#endif /* jstracer_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jstypes.h b/tools/node_modules/expresso/deps/jscoverage/js/jstypes.h
new file mode 100644
index 0000000..bf09bfe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jstypes.h
@@ -0,0 +1,490 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+** File: jstypes.h
+** Description: Definitions of NSPR's basic types
+**
+** Prototypes and macros used to make up for deficiencies in ANSI environments
+** that we have found.
+**
+** Since we do not wrap <stdlib.h> and all the other standard headers, authors
+** of portable code will not know in general that they need these definitions.
+** Instead of requiring these authors to find the dependent uses in their code
+** and take the following steps only in those C files, we take steps once here
+** for all C files.
+**/
+
+#ifndef jstypes_h___
+#define jstypes_h___
+
+#include <stddef.h>
+
+/***********************************************************************
+** MACROS: JS_EXTERN_API
+** JS_EXPORT_API
+** DESCRIPTION:
+** These are only for externally visible routines and globals. For
+** internal routines, just use "extern" for type checking and that
+** will not export internal cross-file or forward-declared symbols.
+** Define a macro for declaring procedures return types. We use this to
+** deal with windoze specific type hackery for DLL definitions. Use
+** JS_EXTERN_API when the prototype for the method is declared. Use
+** JS_EXPORT_API for the implementation of the method.
+**
+** Example:
+** in dowhim.h
+** JS_EXTERN_API( void ) DoWhatIMean( void );
+** in dowhim.c
+** JS_EXPORT_API( void ) DoWhatIMean( void ) { return; }
+**
+**
+***********************************************************************/
+#ifdef WIN32
+
+/* These also work for __MWERKS__ */
+# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_API(__type) __declspec(dllexport) __type
+# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
+
+#elif defined(XP_OS2) && defined(__declspec)
+
+# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_API(__type) __declspec(dllexport) __type
+# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
+# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
+
+#else /* Unix */
+
+# ifdef HAVE_VISIBILITY_ATTRIBUTE
+# define JS_EXTERNAL_VIS __attribute__((visibility ("default")))
+# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# define JS_EXTERNAL_VIS __global
+# else
+# define JS_EXTERNAL_VIS
+# endif
+
+# define JS_EXTERN_API(__type) extern JS_EXTERNAL_VIS __type
+# define JS_EXPORT_API(__type) JS_EXTERNAL_VIS __type
+# define JS_EXTERN_DATA(__type) extern JS_EXTERNAL_VIS __type
+# define JS_EXPORT_DATA(__type) JS_EXTERNAL_VIS __type
+
+#endif
+
+#ifdef _WIN32
+# if defined(__MWERKS__) || defined(__GNUC__)
+# define JS_IMPORT_API(__x) __x
+# else
+# define JS_IMPORT_API(__x) __declspec(dllimport) __x
+# endif
+#elif defined(XP_OS2) && defined(__declspec)
+# define JS_IMPORT_API(__x) __declspec(dllimport) __x
+#else
+# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
+#endif
+
+#if defined(_WIN32) && !defined(__MWERKS__)
+# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
+#elif defined(XP_OS2) && defined(__declspec)
+# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
+#else
+# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x)
+#endif
+
+/*
+ * The linkage of JS API functions differs depending on whether the file is
+ * used within the JS library or not. Any source file within the JS
+ * interpreter should define EXPORT_JS_API whereas any client of the library
+ * should not. STATIC_JS_API is used to build JS as a static library.
+ */
+#if defined(STATIC_JS_API)
+
+# define JS_PUBLIC_API(t) t
+# define JS_PUBLIC_DATA(t) t
+
+#elif defined(EXPORT_JS_API)
+
+# define JS_PUBLIC_API(t) JS_EXPORT_API(t)
+# define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
+
+#else
+
+# define JS_PUBLIC_API(t) JS_IMPORT_API(t)
+# define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
+
+#endif
+
+#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
+#define JS_FRIEND_DATA(t) JS_PUBLIC_DATA(t)
+
+#if defined(_MSC_VER) && defined(_M_IX86)
+#define JS_FASTCALL __fastcall
+#elif defined(__GNUC__) && defined(__i386__) && \
+ ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+#define JS_FASTCALL __attribute__((fastcall))
+#else
+#define JS_FASTCALL
+#define JS_NO_FASTCALL
+#endif
+
+#ifndef JS_INLINE
+# if defined __cplusplus
+# define JS_INLINE inline
+# elif defined _MSC_VER
+# define JS_INLINE __inline
+# elif defined __GNUC__
+# define JS_INLINE __inline__
+# else
+# define JS_INLINE inline
+# endif
+#endif
+
+#ifndef JS_ALWAYS_INLINE
+# if defined DEBUG
+# define JS_ALWAYS_INLINE JS_INLINE
+# elif defined _MSC_VER
+# define JS_ALWAYS_INLINE __forceinline
+# elif defined __GNUC__
+# define JS_ALWAYS_INLINE __attribute__((always_inline))
+# else
+# define JS_ALWAYS_INLINE JS_INLINE
+# endif
+#endif
+
+/***********************************************************************
+** MACROS: JS_BEGIN_MACRO
+** JS_END_MACRO
+** DESCRIPTION:
+** Macro body brackets so that macros with compound statement definitions
+** behave syntactically more like functions when called.
+***********************************************************************/
+#define JS_BEGIN_MACRO do {
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+# define JS_END_MACRO \
+ } __pragma(warning(push)) __pragma(warning(disable:4127)) \
+ while (0) __pragma(warning(pop))
+#else
+# define JS_END_MACRO } while (0)
+#endif
+
+/***********************************************************************
+** MACROS: JS_BEGIN_EXTERN_C
+** JS_END_EXTERN_C
+** DESCRIPTION:
+** Macro shorthands for conditional C++ extern block delimiters.
+***********************************************************************/
+#ifdef __cplusplus
+
+# define JS_BEGIN_EXTERN_C extern "C" {
+# define JS_END_EXTERN_C }
+
+#else
+
+# define JS_BEGIN_EXTERN_C
+# define JS_END_EXTERN_C
+
+#endif
+
+/***********************************************************************
+** MACROS: JS_BIT
+** JS_BITMASK
+** DESCRIPTION:
+** Bit masking macros. XXX n must be <= 31 to be portable
+***********************************************************************/
+#define JS_BIT(n) ((JSUint32)1 << (n))
+#define JS_BITMASK(n) (JS_BIT(n) - 1)
+
+/***********************************************************************
+** MACROS: JS_PTR_TO_INT32
+** JS_PTR_TO_UINT32
+** JS_INT32_TO_PTR
+** JS_UINT32_TO_PTR
+** DESCRIPTION:
+** Integer to pointer and pointer to integer conversion macros.
+***********************************************************************/
+#define JS_PTR_TO_INT32(x) ((jsint)((char *)(x) - (char *)0))
+#define JS_PTR_TO_UINT32(x) ((jsuint)((char *)(x) - (char *)0))
+#define JS_INT32_TO_PTR(x) ((void *)((char *)0 + (jsint)(x)))
+#define JS_UINT32_TO_PTR(x) ((void *)((char *)0 + (jsuint)(x)))
+
+/***********************************************************************
+** MACROS: JS_HOWMANY
+** JS_ROUNDUP
+** JS_MIN
+** JS_MAX
+** DESCRIPTION:
+** Commonly used macros for operations on compatible types.
+***********************************************************************/
+#define JS_HOWMANY(x,y) (((x)+(y)-1)/(y))
+#define JS_ROUNDUP(x,y) (JS_HOWMANY(x,y)*(y))
+#define JS_MIN(x,y) ((x)<(y)?(x):(y))
+#define JS_MAX(x,y) ((x)>(y)?(x):(y))
+
+#if (defined(XP_WIN) && !defined(CROSS_COMPILE)) || defined (WINCE)
+# include "jscpucfg.h" /* Use standard Mac or Windows configuration */
+#elif defined(XP_UNIX) || defined(XP_BEOS) || defined(XP_OS2) || defined(CROSS_COMPILE)
+# include "jsautocfg.h" /* Use auto-detected configuration */
+#else
+# error "Must define one of XP_BEOS, XP_OS2, XP_WIN or XP_UNIX"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+/************************************************************************
+** TYPES: JSUint8
+** JSInt8
+** DESCRIPTION:
+** The int8 types are known to be 8 bits each. There is no type that
+** is equivalent to a plain "char".
+************************************************************************/
+#if JS_BYTES_PER_BYTE == 1
+typedef unsigned char JSUint8;
+typedef signed char JSInt8;
+#else
+# error No suitable type for JSInt8/JSUint8
+#endif
+
+/************************************************************************
+** TYPES: JSUint16
+** JSInt16
+** DESCRIPTION:
+** The int16 types are known to be 16 bits each.
+************************************************************************/
+#if JS_BYTES_PER_SHORT == 2
+typedef unsigned short JSUint16;
+typedef short JSInt16;
+#else
+# error No suitable type for JSInt16/JSUint16
+#endif
+
+/************************************************************************
+** TYPES: JSUint32
+** JSInt32
+** DESCRIPTION:
+** The int32 types are known to be 32 bits each.
+************************************************************************/
+#if JS_BYTES_PER_INT == 4
+typedef unsigned int JSUint32;
+typedef int JSInt32;
+# define JS_INT32(x) x
+# define JS_UINT32(x) x ## U
+#elif JS_BYTES_PER_LONG == 4
+typedef unsigned long JSUint32;
+typedef long JSInt32;
+# define JS_INT32(x) x ## L
+# define JS_UINT32(x) x ## UL
+#else
+# error No suitable type for JSInt32/JSUint32
+#endif
+
+/************************************************************************
+** TYPES: JSUint64
+** JSInt64
+** DESCRIPTION:
+** The int64 types are known to be 64 bits each. Care must be used when
+** declaring variables of type JSUint64 or JSInt64. Different hardware
+** architectures and even different compilers have varying support for
+** 64 bit values. The only guaranteed portability requires the use of
+** the JSLL_ macros (see jslong.h).
+************************************************************************/
+#ifdef JS_HAVE_LONG_LONG
+
+# if JS_BYTES_PER_LONG == 8
+typedef long JSInt64;
+typedef unsigned long JSUint64;
+# elif defined(WIN16)
+typedef __int64 JSInt64;
+typedef unsigned __int64 JSUint64;
+# elif defined(WIN32) && !defined(__GNUC__)
+typedef __int64 JSInt64;
+typedef unsigned __int64 JSUint64;
+# else
+typedef long long JSInt64;
+typedef unsigned long long JSUint64;
+# endif /* JS_BYTES_PER_LONG == 8 */
+
+#else /* !JS_HAVE_LONG_LONG */
+
+typedef struct {
+# ifdef IS_LITTLE_ENDIAN
+ JSUint32 lo, hi;
+# else
+ JSUint32 hi, lo;
+#endif
+} JSInt64;
+typedef JSInt64 JSUint64;
+
+#endif /* !JS_HAVE_LONG_LONG */
+
+/************************************************************************
+** TYPES: JSUintn
+** JSIntn
+** DESCRIPTION:
+** The JSIntn types are most appropriate for automatic variables. They are
+** guaranteed to be at least 16 bits, though various architectures may
+** define them to be wider (e.g., 32 or even 64 bits). These types are
+** never valid for fields of a structure.
+************************************************************************/
+#if JS_BYTES_PER_INT >= 2
+typedef int JSIntn;
+typedef unsigned int JSUintn;
+#else
+# error 'sizeof(int)' not sufficient for platform use
+#endif
+
+/************************************************************************
+** TYPES: JSFloat64
+** DESCRIPTION:
+** NSPR's floating point type is always 64 bits.
+************************************************************************/
+typedef double JSFloat64;
+
+/************************************************************************
+** TYPES: JSSize
+** DESCRIPTION:
+** A type for representing the size of objects.
+************************************************************************/
+typedef size_t JSSize;
+
+/************************************************************************
+** TYPES: JSPtrDiff
+** DESCRIPTION:
+** A type for pointer difference. Variables of this type are suitable
+** for storing a pointer or pointer sutraction.
+************************************************************************/
+typedef ptrdiff_t JSPtrdiff;
+
+/************************************************************************
+** TYPES: JSUptrdiff
+** DESCRIPTION:
+** A type for pointer difference. Variables of this type are suitable
+** for storing a pointer or pointer sutraction.
+************************************************************************/
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+typedef JSUint64 JSUptrdiff;
+#else
+typedef unsigned long JSUptrdiff;
+#endif
+
+/************************************************************************
+** TYPES: JSBool
+** DESCRIPTION:
+** Use JSBool for variables and parameter types. Use JS_FALSE and JS_TRUE
+** for clarity of target type in assignments and actual arguments. Use
+** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
+** just as you would C int-valued conditions.
+************************************************************************/
+typedef JSIntn JSBool;
+#define JS_TRUE (JSIntn)1
+#define JS_FALSE (JSIntn)0
+
+/************************************************************************
+** TYPES: JSPackedBool
+** DESCRIPTION:
+** Use JSPackedBool within structs where bitfields are not desireable
+** but minimum and consistent overhead matters.
+************************************************************************/
+typedef JSUint8 JSPackedBool;
+
+/*
+** A JSWord is an integer that is the same size as a void*
+*/
+#if JS_BYTES_PER_WORD == 8 && JS_BYTES_PER_LONG != 8
+typedef JSInt64 JSWord;
+typedef JSUint64 JSUword;
+#else
+typedef long JSWord;
+typedef unsigned long JSUword;
+#endif
+
+#include "jsotypes.h"
+
+/***********************************************************************
+** MACROS: JS_LIKELY
+** JS_UNLIKELY
+** DESCRIPTION:
+** These macros allow you to give a hint to the compiler about branch
+** probability so that it can better optimize. Use them like this:
+**
+** if (JS_LIKELY(v == 1)) {
+** ... expected code path ...
+** }
+**
+** if (JS_UNLIKELY(v == 0)) {
+** ... non-expected code path ...
+** }
+**
+***********************************************************************/
+#if defined(__GNUC__) && (__GNUC__ > 2)
+
+# define JS_LIKELY(x) (__builtin_expect((x), 1))
+# define JS_UNLIKELY(x) (__builtin_expect((x), 0))
+
+#else
+
+# define JS_LIKELY(x) (x)
+# define JS_UNLIKELY(x) (x)
+
+#endif
+
+/***********************************************************************
+** MACROS: JS_ARRAY_LENGTH
+** JS_ARRAY_END
+** DESCRIPTION:
+** Macros to get the number of elements and the pointer to one past the
+** last element of a C array. Use them like this:
+**
+** jschar buf[10], *s;
+** JSString *str;
+** ...
+** for (s = buf; s != JS_ARRAY_END(buf); ++s) *s = ...;
+** ...
+** str = JS_NewStringCopyN(cx, buf, JS_ARRAY_LENGTH(buf));
+** ...
+**
+***********************************************************************/
+
+#define JS_ARRAY_LENGTH(array) (sizeof (array) / sizeof (array)[0])
+#define JS_ARRAY_END(array) ((array) + JS_ARRAY_LENGTH(array))
+
+JS_END_EXTERN_C
+
+#endif /* jstypes_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp
new file mode 100644
index 0000000..5d7eb88
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.cpp
@@ -0,0 +1,345 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR assertion checker.
+ */
+#include "jsstddef.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jsutil.h"
+
+#ifdef WIN32
+# include <windows.h>
+#endif
+
+JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln)
+{
+ fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
+#if defined(WIN32)
+ DebugBreak();
+ exit(3);
+#elif defined(XP_OS2) || (defined(__GNUC__) && defined(__i386))
+ asm("int $3");
+#endif
+ abort();
+}
+
+#ifdef JS_BASIC_STATS
+
+#include <math.h>
+#include <string.h>
+#include "jscompat.h"
+#include "jsbit.h"
+
+/*
+ * Histogram bins count occurrences of values <= the bin label, as follows:
+ *
+ * linear: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or more
+ * 2**x: 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or more
+ * 10**x: 0, 1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more
+ *
+ * We wish to count occurrences of 0 and 1 values separately, always.
+ */
+static uint32
+BinToVal(uintN logscale, uintN bin)
+{
+ JS_ASSERT(bin <= 10);
+ if (bin <= 1 || logscale == 0)
+ return bin;
+ --bin;
+ if (logscale == 2)
+ return JS_BIT(bin);
+ JS_ASSERT(logscale == 10);
+ return (uint32) pow(10.0, (double) bin);
+}
+
+static uintN
+ValToBin(uintN logscale, uint32 val)
+{
+ uintN bin;
+
+ if (val <= 1)
+ return val;
+ bin = (logscale == 10)
+ ? (uintN) ceil(log10((double) val))
+ : (logscale == 2)
+ ? (uintN) JS_CeilingLog2(val)
+ : val;
+ return JS_MIN(bin, 10);
+}
+
+void
+JS_BasicStatsAccum(JSBasicStats *bs, uint32 val)
+{
+ uintN oldscale, newscale, bin;
+ double mean;
+
+ ++bs->num;
+ if (bs->max < val)
+ bs->max = val;
+ bs->sum += val;
+ bs->sqsum += (double)val * val;
+
+ oldscale = bs->logscale;
+ if (oldscale != 10) {
+ mean = bs->sum / bs->num;
+ if (bs->max > 16 && mean > 8) {
+ newscale = (bs->max > 1e6 && mean > 1000) ? 10 : 2;
+ if (newscale != oldscale) {
+ uint32 newhist[11], newbin;
+
+ memset(newhist, 0, sizeof newhist);
+ for (bin = 0; bin <= 10; bin++) {
+ newbin = ValToBin(newscale, BinToVal(oldscale, bin));
+ newhist[newbin] += bs->hist[bin];
+ }
+ memcpy(bs->hist, newhist, sizeof bs->hist);
+ bs->logscale = newscale;
+ }
+ }
+ }
+
+ bin = ValToBin(bs->logscale, val);
+ ++bs->hist[bin];
+}
+
+double
+JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma)
+{
+ double var;
+
+ if (num == 0 || sum == 0) {
+ *sigma = 0;
+ return 0;
+ }
+
+ var = num * sqsum - sum * sum;
+ if (var < 0 || num == 1)
+ var = 0;
+ else
+ var /= (double)num * (num - 1);
+
+ /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */
+ *sigma = (var != 0) ? sqrt(var) : 0;
+ return sum / num;
+}
+
+void
+JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp)
+{
+ double mean, sigma;
+
+ mean = JS_MeanAndStdDevBS(bs, &sigma);
+ fprintf(fp, "\nmean %s %g, std. deviation %g, max %lu\n",
+ title, mean, sigma, (unsigned long) bs->max);
+ JS_DumpHistogram(bs, fp);
+}
+
+void
+JS_DumpHistogram(JSBasicStats *bs, FILE *fp)
+{
+ uintN bin;
+ uint32 cnt, max, prev, val, i;
+ double sum, mean;
+
+ for (bin = 0, max = 0, sum = 0; bin <= 10; bin++) {
+ cnt = bs->hist[bin];
+ if (max < cnt)
+ max = cnt;
+ sum += cnt;
+ }
+ mean = sum / cnt;
+ for (bin = 0, prev = 0; bin <= 10; bin++, prev = val) {
+ val = BinToVal(bs->logscale, bin);
+ cnt = bs->hist[bin];
+ if (prev + 1 >= val)
+ fprintf(fp, " [%6u]", val);
+ else
+ fprintf(fp, "[%6u, %6u]", prev + 1, val);
+ fprintf(fp, "%s %8u ", (bin == 10) ? "+" : ":", cnt);
+ if (cnt != 0) {
+ if (max > 1e6 && mean > 1e3)
+ cnt = (uint32) ceil(log10((double) cnt));
+ else if (max > 16 && mean > 8)
+ cnt = JS_CeilingLog2(cnt);
+ for (i = 0; i < cnt; i++)
+ putc('*', fp);
+ }
+ putc('\n', fp);
+ }
+}
+
+#endif /* JS_BASIC_STATS */
+
+#if defined DEBUG_notme && defined XP_UNIX
+
+#define __USE_GNU 1
+#include <dlfcn.h>
+#include <string.h>
+#include "jshash.h"
+#include "jsprf.h"
+
+JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL};
+
+static JSCallsite *
+CallTree(void **bp)
+{
+ void **bpup, **bpdown, *pc;
+ JSCallsite *parent, *site, **csp;
+ Dl_info info;
+ int ok, offset;
+ const char *symbol;
+ char *method;
+
+ /* Reverse the stack frame list to avoid recursion. */
+ bpup = NULL;
+ for (;;) {
+ bpdown = (void**) bp[0];
+ bp[0] = (void*) bpup;
+ if ((void**) bpdown[0] < bpdown)
+ break;
+ bpup = bp;
+ bp = bpdown;
+ }
+
+ /* Reverse the stack again, finding and building a path in the tree. */
+ parent = &js_calltree_root;
+ do {
+ bpup = (void**) bp[0];
+ bp[0] = (void*) bpdown;
+ pc = bp[1];
+
+ csp = &parent->kids;
+ while ((site = *csp) != NULL) {
+ if (site->pc == (uint32)pc) {
+ /* Put the most recently used site at the front of siblings. */
+ *csp = site->siblings;
+ site->siblings = parent->kids;
+ parent->kids = site;
+
+ /* Site already built -- go up the stack. */
+ goto upward;
+ }
+ csp = &site->siblings;
+ }
+
+ /* Check for recursion: see if pc is on our ancestor line. */
+ for (site = parent; site; site = site->parent) {
+ if (site->pc == (uint32)pc)
+ goto upward;
+ }
+
+ /*
+ * Not in tree at all: let's find our symbolic callsite info.
+ * XXX static syms are masked by nearest lower global
+ */
+ info.dli_fname = info.dli_sname = NULL;
+ ok = dladdr(pc, &info);
+ if (ok < 0) {
+ fprintf(stderr, "dladdr failed!\n");
+ return NULL;
+ }
+
+/* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */
+ symbol = info.dli_sname;
+ offset = (char*)pc - (char*)info.dli_fbase;
+ method = symbol
+ ? strdup(symbol)
+ : JS_smprintf("%s+%X",
+ info.dli_fname ? info.dli_fname : "main",
+ offset);
+ if (!method)
+ return NULL;
+
+ /* Create a new callsite record. */
+ site = (JSCallsite *) malloc(sizeof(JSCallsite));
+ if (!site)
+ return NULL;
+
+ /* Insert the new site into the tree. */
+ site->pc = (uint32)pc;
+ site->name = method;
+ site->library = info.dli_fname;
+ site->offset = offset;
+ site->parent = parent;
+ site->siblings = parent->kids;
+ parent->kids = site;
+ site->kids = NULL;
+
+ upward:
+ parent = site;
+ bpdown = bp;
+ bp = bpup;
+ } while (bp);
+
+ return site;
+}
+
+JSCallsite *
+JS_Backtrace(int skip)
+{
+ void **bp, **bpdown;
+
+ /* Stack walking code adapted from Kipp's "leaky". */
+#if defined(__i386)
+ __asm__( "movl %%ebp, %0" : "=g"(bp));
+#elif defined(__x86_64__)
+ __asm__( "movq %%rbp, %0" : "=g"(bp));
+#else
+ /*
+ * It would be nice if this worked uniformly, but at least on i386 and
+ * x86_64, it stopped working with gcc 4.1, because it points to the
+ * end of the saved registers instead of the start.
+ */
+ bp = (void**) __builtin_frame_address(0);
+#endif
+ while (--skip >= 0) {
+ bpdown = (void**) *bp++;
+ if (bpdown < bp)
+ break;
+ bp = bpdown;
+ }
+
+ return CallTree(bp);
+}
+
+#endif /* DEBUG_notme && XP_UNIX */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsutil.h b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.h
new file mode 100644
index 0000000..a6c329c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsutil.h
@@ -0,0 +1,168 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR assertion checker.
+ */
+
+#ifndef jsutil_h___
+#define jsutil_h___
+
+JS_BEGIN_EXTERN_C
+
+#ifdef DEBUG
+
+extern JS_PUBLIC_API(void)
+JS_Assert(const char *s, const char *file, JSIntn ln);
+
+#define JS_ASSERT(expr) \
+ ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+
+#define JS_ASSERT_IF(cond, expr) \
+ ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+
+#define JS_NOT_REACHED(reason) \
+ JS_Assert(reason, __FILE__, __LINE__)
+
+#else
+
+#define JS_ASSERT(expr) ((void) 0)
+#define JS_ASSERT_IF(cond,expr) ((void) 0)
+#define JS_NOT_REACHED(reason)
+
+#endif /* defined(DEBUG) */
+
+/*
+ * Compile-time assert. "condition" must be a constant expression.
+ * The macro can be used only in places where an "extern" declaration is
+ * allowed.
+ */
+
+/*
+ * Sun Studio C++ compiler has a bug
+ * "sizeof expression not accepted as size of array parameter"
+ * The bug number is 6688515. It is not public yet.
+ * Turn off this assert for Sun Studio until this bug is fixed.
+ */
+#ifdef __SUNPRO_CC
+#define JS_STATIC_ASSERT(condition)
+#else
+#define JS_STATIC_ASSERT(condition) \
+ extern void js_static_assert(int arg[(condition) ? 1 : -1])
+#endif
+
+/*
+ * Abort the process in a non-graceful manner. This will cause a core file,
+ * call to the debugger or other moral equivalent as well as causing the
+ * entire process to stop.
+ */
+extern JS_PUBLIC_API(void) JS_Abort(void);
+
+#if 0
+# define JS_BASIC_STATS 1
+# define JS_SCOPE_DEPTH_METER 1
+#endif
+
+#if defined DEBUG && !defined JS_BASIC_STATS
+# define JS_BASIC_STATS 1
+#endif
+
+#ifdef JS_BASIC_STATS
+
+#include <stdio.h>
+
+typedef struct JSBasicStats {
+ uint32 num;
+ uint32 max;
+ double sum;
+ double sqsum;
+ uint32 logscale; /* logarithmic scale: 0 (linear), 2, 10 */
+ uint32 hist[11];
+} JSBasicStats;
+
+#define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
+#define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
+
+#define JS_BASIC_STATS_ACCUM(bs,val) \
+ JS_BasicStatsAccum(bs, val)
+
+#define JS_MeanAndStdDevBS(bs,sigma) \
+ JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
+
+extern void
+JS_BasicStatsAccum(JSBasicStats *bs, uint32 val);
+
+extern double
+JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma);
+
+extern void
+JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
+
+extern void
+JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
+
+#else
+
+#define JS_BASIC_STATS_ACCUM(bs,val) /* nothing */
+
+#endif /* JS_BASIC_STATS */
+
+
+#ifdef XP_UNIX
+
+typedef struct JSCallsite JSCallsite;
+
+struct JSCallsite {
+ uint32 pc;
+ char *name;
+ const char *library;
+ int offset;
+ JSCallsite *parent;
+ JSCallsite *siblings;
+ JSCallsite *kids;
+ void *handy;
+};
+
+extern JSCallsite *JS_Backtrace(int skip);
+
+#endif
+
+JS_END_EXTERN_C
+
+#endif /* jsutil_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsversion.h b/tools/node_modules/expresso/deps/jscoverage/js/jsversion.h
new file mode 100644
index 0000000..b16953b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsversion.h
@@ -0,0 +1,243 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * JS configuration macros.
+ */
+#ifndef JS_VERSION
+#define JS_VERSION 180
+#endif
+
+/*
+ * Compile-time JS version configuration. The JS version numbers lie on the
+ * number line like so:
+ *
+ * 1.0 1.1 1.2 1.3 1.4 ECMAv3 1.5 1.6 1.7 1.8
+ * ^ ^
+ * | |
+ * basis for ECMAv1 close to ECMAv2
+ *
+ * where ECMAv3 stands for ECMA-262 Edition 3. See the runtime version enum
+ * JSVersion in jspubtd.h. Code in the engine can therefore count on version
+ * <= JSVERSION_1_4 to mean "before the Third Edition of ECMA-262" and version
+ * > JSVERSION_1_4 to mean "at or after the Third Edition".
+ *
+ * In the (likely?) event that SpiderMonkey grows to implement JavaScript 2.0,
+ * or ECMA-262 Edition 4 (JS2 without certain extensions), the version number
+ * to use would be near 200, or greater.
+ *
+ * The JS_VERSION_ECMA_3 version is the minimal configuration conforming to
+ * the ECMA-262 Edition 3 specification. Use it for minimal embeddings, where
+ * you're sure you don't need any of the extensions disabled in this version.
+ * In order to facilitate testing, JS_HAS_OBJ_PROTO_PROP is defined as part of
+ * the JS_VERSION_ECMA_3_TEST version.
+ *
+ * To keep things sane in the modern age, where we need exceptions in order to
+ * implement, e.g., iterators and generators, we are dropping support for all
+ * versions <= 1.4.
+ */
+#define JS_VERSION_ECMA_3 148
+#define JS_VERSION_ECMA_3_TEST 149
+
+#if JS_VERSION == JS_VERSION_ECMA_3 || \
+ JS_VERSION == JS_VERSION_ECMA_3_TEST
+
+#define JS_HAS_STR_HTML_HELPERS 0 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 0 /* has str.substr */
+#if JS_VERSION == JS_VERSION_ECMA_3_TEST
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#else
+#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
+#endif
+#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 0 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 0 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 0 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 0 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */
+#define JS_HAS_CONST 0 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 0 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION < 150
+
+#error "unsupported JS_VERSION"
+
+#elif JS_VERSION == 150
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 0 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION == 160
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 1 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 0 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION == 170
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 1 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 0 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 0 /* has function (formals) listexpr */
+
+#elif JS_VERSION == 180
+
+#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
+#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
+#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
+#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
+#define JS_HAS_EVAL_THIS_SCOPE 1 /* Math.eval is same as with (Math) */
+#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
+#define JS_HAS_SCRIPT_OBJECT 0 /* has (new Script("x++")).exec() */
+#define JS_HAS_XDR 1 /* has XDR API and internal support */
+#define JS_HAS_XDR_FREEZE_THAW 0 /* has XDR freeze/thaw script methods */
+#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
+#define JS_HAS_DEBUGGER_KEYWORD 1 /* has hook for debugger keyword */
+#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
+#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
+#define JS_HAS_GETTER_SETTER 1 /* has JS2 getter/setter functions */
+#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
+#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
+#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
+#define JS_HAS_LVALUE_RETURN 1 /* has o.item(i) = j; for native item */
+#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
+#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
+#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
+#define JS_HAS_GENERATORS 1 /* has yield in generator function */
+#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
+#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
+#define JS_HAS_GENERATOR_EXPRS 1 /* has (expr for (lhs in iterable)) */
+#define JS_HAS_EXPR_CLOSURES 1 /* has function (formals) listexpr */
+
+#else
+
+#error "unknown JS_VERSION"
+
+#endif
+
+/* Features that are present in all versions. */
+#define JS_HAS_RESERVED_JAVA_KEYWORDS 1
+#define JS_HAS_RESERVED_ECMA_KEYWORDS 1
+
+/* Feature-test macro for evolving destructuring support. */
+#define JS_HAS_DESTRUCTURING_SHORTHAND (JS_HAS_DESTRUCTURING == 2)
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp
new file mode 100644
index 0000000..5643e73
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.cpp
@@ -0,0 +1,800 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#include "jsstddef.h"
+#include "jsversion.h"
+
+#if JS_HAS_XDR
+
+#include <string.h>
+#include "jstypes.h"
+#include "jsutil.h" /* Added by JSIFY */
+#include "jsdhash.h"
+#include "jsprf.h"
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsnum.h"
+#include "jsobj.h" /* js_XDRObject */
+#include "jsscript.h" /* js_XDRScript */
+#include "jsstr.h"
+#include "jsxdrapi.h"
+
+#ifdef DEBUG
+#define DBG(x) x
+#else
+#define DBG(x) ((void)0)
+#endif
+
+typedef struct JSXDRMemState {
+ JSXDRState state;
+ char *base;
+ uint32 count;
+ uint32 limit;
+} JSXDRMemState;
+
+#define MEM_BLOCK 8192
+#define MEM_PRIV(xdr) ((JSXDRMemState *)(xdr))
+
+#define MEM_BASE(xdr) (MEM_PRIV(xdr)->base)
+#define MEM_COUNT(xdr) (MEM_PRIV(xdr)->count)
+#define MEM_LIMIT(xdr) (MEM_PRIV(xdr)->limit)
+
+#define MEM_LEFT(xdr, bytes) \
+ JS_BEGIN_MACRO \
+ if ((xdr)->mode == JSXDR_DECODE && \
+ MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
+ JS_ReportErrorNumber((xdr)->cx, js_GetErrorMessage, NULL, \
+ JSMSG_END_OF_DATA); \
+ return 0; \
+ } \
+ JS_END_MACRO
+
+#define MEM_NEED(xdr, bytes) \
+ JS_BEGIN_MACRO \
+ if ((xdr)->mode == JSXDR_ENCODE) { \
+ if (MEM_LIMIT(xdr) && \
+ MEM_COUNT(xdr) + bytes > MEM_LIMIT(xdr)) { \
+ uint32 limit_ = JS_ROUNDUP(MEM_COUNT(xdr) + bytes, MEM_BLOCK);\
+ void *data_ = JS_realloc((xdr)->cx, MEM_BASE(xdr), limit_); \
+ if (!data_) \
+ return 0; \
+ MEM_BASE(xdr) = (char *) data_; \
+ MEM_LIMIT(xdr) = limit_; \
+ } \
+ } else { \
+ MEM_LEFT(xdr, bytes); \
+ } \
+ JS_END_MACRO
+
+#define MEM_DATA(xdr) ((void *)(MEM_BASE(xdr) + MEM_COUNT(xdr)))
+#define MEM_INCR(xdr,bytes) (MEM_COUNT(xdr) += (bytes))
+
+static JSBool
+mem_get32(JSXDRState *xdr, uint32 *lp)
+{
+ MEM_LEFT(xdr, 4);
+ *lp = *(uint32 *)MEM_DATA(xdr);
+ MEM_INCR(xdr, 4);
+ return JS_TRUE;
+}
+
+static JSBool
+mem_set32(JSXDRState *xdr, uint32 *lp)
+{
+ MEM_NEED(xdr, 4);
+ *(uint32 *)MEM_DATA(xdr) = *lp;
+ MEM_INCR(xdr, 4);
+ return JS_TRUE;
+}
+
+static JSBool
+mem_getbytes(JSXDRState *xdr, char *bytes, uint32 len)
+{
+ MEM_LEFT(xdr, len);
+ memcpy(bytes, MEM_DATA(xdr), len);
+ MEM_INCR(xdr, len);
+ return JS_TRUE;
+}
+
+static JSBool
+mem_setbytes(JSXDRState *xdr, char *bytes, uint32 len)
+{
+ MEM_NEED(xdr, len);
+ memcpy(MEM_DATA(xdr), bytes, len);
+ MEM_INCR(xdr, len);
+ return JS_TRUE;
+}
+
+static void *
+mem_raw(JSXDRState *xdr, uint32 len)
+{
+ void *data;
+ if (xdr->mode == JSXDR_ENCODE) {
+ MEM_NEED(xdr, len);
+ } else if (xdr->mode == JSXDR_DECODE) {
+ MEM_LEFT(xdr, len);
+ }
+ data = MEM_DATA(xdr);
+ MEM_INCR(xdr, len);
+ return data;
+}
+
+static JSBool
+mem_seek(JSXDRState *xdr, int32 offset, JSXDRWhence whence)
+{
+ switch (whence) {
+ case JSXDR_SEEK_CUR:
+ if ((int32)MEM_COUNT(xdr) + offset < 0) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_SEEK_BEYOND_START);
+ return JS_FALSE;
+ }
+ if (offset > 0)
+ MEM_NEED(xdr, offset);
+ MEM_COUNT(xdr) += offset;
+ return JS_TRUE;
+ case JSXDR_SEEK_SET:
+ if (offset < 0) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_SEEK_BEYOND_START);
+ return JS_FALSE;
+ }
+ if (xdr->mode == JSXDR_ENCODE) {
+ if ((uint32)offset > MEM_COUNT(xdr))
+ MEM_NEED(xdr, offset - MEM_COUNT(xdr));
+ MEM_COUNT(xdr) = offset;
+ } else {
+ if ((uint32)offset > MEM_LIMIT(xdr)) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_SEEK_BEYOND_END);
+ return JS_FALSE;
+ }
+ MEM_COUNT(xdr) = offset;
+ }
+ return JS_TRUE;
+ case JSXDR_SEEK_END:
+ if (offset >= 0 ||
+ xdr->mode == JSXDR_ENCODE ||
+ (int32)MEM_LIMIT(xdr) + offset < 0) {
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_END_SEEK);
+ return JS_FALSE;
+ }
+ MEM_COUNT(xdr) = MEM_LIMIT(xdr) + offset;
+ return JS_TRUE;
+ default: {
+ char numBuf[12];
+ JS_snprintf(numBuf, sizeof numBuf, "%d", whence);
+ JS_ReportErrorNumber(xdr->cx, js_GetErrorMessage, NULL,
+ JSMSG_WHITHER_WHENCE, numBuf);
+ return JS_FALSE;
+ }
+ }
+}
+
+static uint32
+mem_tell(JSXDRState *xdr)
+{
+ return MEM_COUNT(xdr);
+}
+
+static void
+mem_finalize(JSXDRState *xdr)
+{
+ JS_free(xdr->cx, MEM_BASE(xdr));
+}
+
+static JSXDROps xdrmem_ops = {
+ mem_get32, mem_set32, mem_getbytes, mem_setbytes,
+ mem_raw, mem_seek, mem_tell, mem_finalize
+};
+
+JS_PUBLIC_API(void)
+JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx)
+{
+ xdr->mode = mode;
+ xdr->cx = cx;
+ xdr->registry = NULL;
+ xdr->numclasses = xdr->maxclasses = 0;
+ xdr->reghash = NULL;
+ xdr->userdata = NULL;
+ xdr->script = NULL;
+}
+
+JS_PUBLIC_API(JSXDRState *)
+JS_XDRNewMem(JSContext *cx, JSXDRMode mode)
+{
+ JSXDRState *xdr = (JSXDRState *) JS_malloc(cx, sizeof(JSXDRMemState));
+ if (!xdr)
+ return NULL;
+ JS_XDRInitBase(xdr, mode, cx);
+ if (mode == JSXDR_ENCODE) {
+ if (!(MEM_BASE(xdr) = (char *) JS_malloc(cx, MEM_BLOCK))) {
+ JS_free(cx, xdr);
+ return NULL;
+ }
+ } else {
+ /* XXXbe ok, so better not deref MEM_BASE(xdr) if not ENCODE */
+ MEM_BASE(xdr) = NULL;
+ }
+ xdr->ops = &xdrmem_ops;
+ MEM_COUNT(xdr) = 0;
+ MEM_LIMIT(xdr) = MEM_BLOCK;
+ return xdr;
+}
+
+JS_PUBLIC_API(void *)
+JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return NULL;
+ *lp = MEM_COUNT(xdr);
+ return MEM_BASE(xdr);
+}
+
+JS_PUBLIC_API(void)
+JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return;
+ MEM_LIMIT(xdr) = len;
+ MEM_BASE(xdr) = (char *) data;
+ MEM_COUNT(xdr) = 0;
+}
+
+JS_PUBLIC_API(uint32)
+JS_XDRMemDataLeft(JSXDRState *xdr)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return 0;
+ return MEM_LIMIT(xdr) - MEM_COUNT(xdr);
+}
+
+JS_PUBLIC_API(void)
+JS_XDRMemResetData(JSXDRState *xdr)
+{
+ if (xdr->ops != &xdrmem_ops)
+ return;
+ MEM_COUNT(xdr) = 0;
+}
+
+JS_PUBLIC_API(void)
+JS_XDRDestroy(JSXDRState *xdr)
+{
+ JSContext *cx = xdr->cx;
+ xdr->ops->finalize(xdr);
+ if (xdr->registry) {
+ JS_free(cx, xdr->registry);
+ if (xdr->reghash)
+ JS_DHashTableDestroy((JSDHashTable *) xdr->reghash);
+ }
+ JS_free(cx, xdr);
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRUint8(JSXDRState *xdr, uint8 *b)
+{
+ uint32 l = *b;
+ if (!JS_XDRUint32(xdr, &l))
+ return JS_FALSE;
+ *b = (uint8) l;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRUint16(JSXDRState *xdr, uint16 *s)
+{
+ uint32 l = *s;
+ if (!JS_XDRUint32(xdr, &l))
+ return JS_FALSE;
+ *s = (uint16) l;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRUint32(JSXDRState *xdr, uint32 *lp)
+{
+ JSBool ok = JS_TRUE;
+ if (xdr->mode == JSXDR_ENCODE) {
+ uint32 xl = JSXDR_SWAB32(*lp);
+ ok = xdr->ops->set32(xdr, &xl);
+ } else if (xdr->mode == JSXDR_DECODE) {
+ ok = xdr->ops->get32(xdr, lp);
+ *lp = JSXDR_SWAB32(*lp);
+ }
+ return ok;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32 len)
+{
+ uint32 padlen;
+ static char padbuf[JSXDR_ALIGN-1];
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ if (!xdr->ops->setbytes(xdr, bytes, len))
+ return JS_FALSE;
+ } else {
+ if (!xdr->ops->getbytes(xdr, bytes, len))
+ return JS_FALSE;
+ }
+ len = xdr->ops->tell(xdr);
+ if (len % JSXDR_ALIGN) {
+ padlen = JSXDR_ALIGN - (len % JSXDR_ALIGN);
+ if (xdr->mode == JSXDR_ENCODE) {
+ if (!xdr->ops->setbytes(xdr, padbuf, padlen))
+ return JS_FALSE;
+ } else {
+ if (!xdr->ops->seek(xdr, padlen, JSXDR_SEEK_CUR))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+/**
+ * Convert between a C string and the XDR representation:
+ * leading 32-bit count, then counted vector of chars,
+ * then possibly \0 padding to multiple of 4.
+ */
+JS_PUBLIC_API(JSBool)
+JS_XDRCString(JSXDRState *xdr, char **sp)
+{
+ uint32 len;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ len = strlen(*sp);
+ JS_XDRUint32(xdr, &len);
+ if (xdr->mode == JSXDR_DECODE) {
+ if (!(*sp = (char *) JS_malloc(xdr->cx, len + 1)))
+ return JS_FALSE;
+ }
+ if (!JS_XDRBytes(xdr, *sp, len)) {
+ if (xdr->mode == JSXDR_DECODE)
+ JS_free(xdr->cx, *sp);
+ return JS_FALSE;
+ }
+ if (xdr->mode == JSXDR_DECODE) {
+ (*sp)[len] = '\0';
+ } else if (xdr->mode == JSXDR_FREE) {
+ JS_free(xdr->cx, *sp);
+ *sp = NULL;
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRCStringOrNull(JSXDRState *xdr, char **sp)
+{
+ uint32 null = (*sp == NULL);
+ if (!JS_XDRUint32(xdr, &null))
+ return JS_FALSE;
+ if (null) {
+ *sp = NULL;
+ return JS_TRUE;
+ }
+ return JS_XDRCString(xdr, sp);
+}
+
+static JSBool
+XDRChars(JSXDRState *xdr, jschar *chars, uint32 nchars)
+{
+ uint32 i, padlen, nbytes;
+ jschar *raw;
+
+ nbytes = nchars * sizeof(jschar);
+ padlen = nbytes % JSXDR_ALIGN;
+ if (padlen) {
+ padlen = JSXDR_ALIGN - padlen;
+ nbytes += padlen;
+ }
+ if (!(raw = (jschar *) xdr->ops->raw(xdr, nbytes)))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_ENCODE) {
+ for (i = 0; i != nchars; i++)
+ raw[i] = JSXDR_SWAB16(chars[i]);
+ if (padlen)
+ memset((char *)raw + nbytes - padlen, 0, padlen);
+ } else if (xdr->mode == JSXDR_DECODE) {
+ for (i = 0; i != nchars; i++)
+ chars[i] = JSXDR_SWAB16(raw[i]);
+ }
+ return JS_TRUE;
+}
+
+/*
+ * Convert between a JS (Unicode) string and the XDR representation.
+ */
+JS_PUBLIC_API(JSBool)
+JS_XDRString(JSXDRState *xdr, JSString **strp)
+{
+ uint32 nchars;
+ jschar *chars;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ nchars = JSSTRING_LENGTH(*strp);
+ if (!JS_XDRUint32(xdr, &nchars))
+ return JS_FALSE;
+
+ if (xdr->mode == JSXDR_DECODE) {
+ chars = (jschar *) JS_malloc(xdr->cx, (nchars + 1) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ } else {
+ chars = JSSTRING_CHARS(*strp);
+ }
+
+ if (!XDRChars(xdr, chars, nchars))
+ goto bad;
+ if (xdr->mode == JSXDR_DECODE) {
+ chars[nchars] = 0;
+ *strp = JS_NewUCString(xdr->cx, chars, nchars);
+ if (!*strp)
+ goto bad;
+ }
+ return JS_TRUE;
+
+bad:
+ if (xdr->mode == JSXDR_DECODE)
+ JS_free(xdr->cx, chars);
+ return JS_FALSE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp)
+{
+ uint32 null = (*strp == NULL);
+ if (!JS_XDRUint32(xdr, &null))
+ return JS_FALSE;
+ if (null) {
+ *strp = NULL;
+ return JS_TRUE;
+ }
+ return JS_XDRString(xdr, strp);
+}
+
+static JSBool
+XDRDoubleValue(JSXDRState *xdr, jsdouble *dp)
+{
+ jsdpun u;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ u.d = *dp;
+ if (!JS_XDRUint32(xdr, &u.s.lo) || !JS_XDRUint32(xdr, &u.s.hi))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *dp = u.d;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRDouble(JSXDRState *xdr, jsdouble **dpp)
+{
+ jsdouble d;
+
+ if (xdr->mode == JSXDR_ENCODE)
+ d = **dpp;
+ if (!XDRDoubleValue(xdr, &d))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE) {
+ *dpp = JS_NewDouble(xdr->cx, d);
+ if (!*dpp)
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+/* These are magic pseudo-tags: see jsapi.h, near the top, for real tags. */
+#define JSVAL_XDRNULL 0x8
+#define JSVAL_XDRVOID 0xA
+
+static JSBool
+XDRValueBody(JSXDRState *xdr, uint32 type, jsval *vp)
+{
+ switch (type) {
+ case JSVAL_XDRNULL:
+ *vp = JSVAL_NULL;
+ break;
+ case JSVAL_XDRVOID:
+ *vp = JSVAL_VOID;
+ break;
+ case JSVAL_STRING: {
+ JSString *str;
+ if (xdr->mode == JSXDR_ENCODE)
+ str = JSVAL_TO_STRING(*vp);
+ if (!JS_XDRString(xdr, &str))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = STRING_TO_JSVAL(str);
+ break;
+ }
+ case JSVAL_DOUBLE: {
+ jsdouble *dp;
+ if (xdr->mode == JSXDR_ENCODE)
+ dp = JSVAL_TO_DOUBLE(*vp);
+ if (!JS_XDRDouble(xdr, &dp))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = DOUBLE_TO_JSVAL(dp);
+ break;
+ }
+ case JSVAL_OBJECT: {
+ JSObject *obj;
+ if (xdr->mode == JSXDR_ENCODE)
+ obj = JSVAL_TO_OBJECT(*vp);
+ if (!js_XDRObject(xdr, &obj))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = OBJECT_TO_JSVAL(obj);
+ break;
+ }
+ case JSVAL_BOOLEAN: {
+ uint32 b;
+ if (xdr->mode == JSXDR_ENCODE)
+ b = (uint32) JSVAL_TO_BOOLEAN(*vp);
+ if (!JS_XDRUint32(xdr, &b))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = BOOLEAN_TO_JSVAL(!!b);
+ break;
+ }
+ default: {
+ uint32 i;
+
+ JS_ASSERT(type & JSVAL_INT);
+ if (xdr->mode == JSXDR_ENCODE)
+ i = (uint32) JSVAL_TO_INT(*vp);
+ if (!JS_XDRUint32(xdr, &i))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ *vp = INT_TO_JSVAL((int32) i);
+ break;
+ }
+ }
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRValue(JSXDRState *xdr, jsval *vp)
+{
+ uint32 type;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ if (JSVAL_IS_NULL(*vp))
+ type = JSVAL_XDRNULL;
+ else if (JSVAL_IS_VOID(*vp))
+ type = JSVAL_XDRVOID;
+ else
+ type = JSVAL_TAG(*vp);
+ }
+ return JS_XDRUint32(xdr, &type) && XDRValueBody(xdr, type, vp);
+}
+
+JSBool
+js_XDRAtom(JSXDRState *xdr, JSAtom **atomp)
+{
+ jsval v;
+ uint32 type;
+ jsdouble d;
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ v = ATOM_KEY(*atomp);
+ return JS_XDRValue(xdr, &v);
+ }
+
+ /*
+ * Inline JS_XDRValue when decoding to avoid ceation of GC things when
+ * then corresponding atom already exists. See bug 321985.
+ */
+ if (!JS_XDRUint32(xdr, &type))
+ return JS_FALSE;
+ if (type == JSVAL_STRING)
+ return js_XDRStringAtom(xdr, atomp);
+
+ if (type == JSVAL_DOUBLE) {
+ if (!XDRDoubleValue(xdr, &d))
+ return JS_FALSE;
+ *atomp = js_AtomizeDouble(xdr->cx, d);
+ return *atomp != NULL;
+ }
+
+ return XDRValueBody(xdr, type, &v) &&
+ js_AtomizePrimitiveValue(xdr->cx, v, atomp);
+}
+
+extern JSBool
+js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp)
+{
+ JSString *str;
+ uint32 nchars;
+ JSAtom *atom;
+ JSContext *cx;
+ jschar *chars;
+ jschar stackChars[256];
+
+ if (xdr->mode == JSXDR_ENCODE) {
+ JS_ASSERT(ATOM_IS_STRING(*atomp));
+ str = ATOM_TO_STRING(*atomp);
+ return JS_XDRString(xdr, &str);
+ }
+
+ /*
+ * Inline JS_XDRString when decoding to avoid JSString allocation
+ * for already existing atoms. See bug 321985.
+ */
+ if (!JS_XDRUint32(xdr, &nchars))
+ return JS_FALSE;
+ atom = NULL;
+ cx = xdr->cx;
+ if (nchars <= JS_ARRAY_LENGTH(stackChars)) {
+ chars = stackChars;
+ } else {
+ /*
+ * This is very uncommon. Don't use the tempPool arena for this as
+ * most allocations here will be bigger than tempPool's arenasize.
+ */
+ chars = (jschar *) JS_malloc(cx, nchars * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ }
+
+ if (XDRChars(xdr, chars, nchars))
+ atom = js_AtomizeChars(cx, chars, nchars, 0);
+ if (chars != stackChars)
+ JS_free(cx, chars);
+
+ if (!atom)
+ return JS_FALSE;
+ *atomp = atom;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
+{
+ if (!js_XDRScript(xdr, scriptp, NULL))
+ return JS_FALSE;
+ if (xdr->mode == JSXDR_DECODE)
+ js_CallNewScriptHook(xdr->cx, *scriptp, NULL);
+ return JS_TRUE;
+}
+
+#define CLASS_REGISTRY_MIN 8
+#define CLASS_INDEX_TO_ID(i) ((i)+1)
+#define CLASS_ID_TO_INDEX(id) ((id)-1)
+
+typedef struct JSRegHashEntry {
+ JSDHashEntryHdr hdr;
+ const char *name;
+ uint32 index;
+} JSRegHashEntry;
+
+JS_PUBLIC_API(JSBool)
+JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *idp)
+{
+ uintN numclasses, maxclasses;
+ JSClass **registry;
+
+ numclasses = xdr->numclasses;
+ maxclasses = xdr->maxclasses;
+ if (numclasses == maxclasses) {
+ maxclasses = (maxclasses == 0) ? CLASS_REGISTRY_MIN : maxclasses << 1;
+ registry = (JSClass **)
+ JS_realloc(xdr->cx, xdr->registry, maxclasses * sizeof(JSClass *));
+ if (!registry)
+ return JS_FALSE;
+ xdr->registry = registry;
+ xdr->maxclasses = maxclasses;
+ } else {
+ JS_ASSERT(numclasses && numclasses < maxclasses);
+ registry = xdr->registry;
+ }
+
+ registry[numclasses] = clasp;
+ if (xdr->reghash) {
+ JSRegHashEntry *entry = (JSRegHashEntry *)
+ JS_DHashTableOperate((JSDHashTable *) xdr->reghash,
+ clasp->name, JS_DHASH_ADD);
+ if (!entry) {
+ JS_ReportOutOfMemory(xdr->cx);
+ return JS_FALSE;
+ }
+ entry->name = clasp->name;
+ entry->index = numclasses;
+ }
+ *idp = CLASS_INDEX_TO_ID(numclasses);
+ xdr->numclasses = ++numclasses;
+ return JS_TRUE;
+}
+
+JS_PUBLIC_API(uint32)
+JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name)
+{
+ uintN i, numclasses;
+
+ numclasses = xdr->numclasses;
+ if (numclasses >= 10) {
+ JSRegHashEntry *entry;
+
+ /* Bootstrap reghash from registry on first overpopulated Find. */
+ if (!xdr->reghash) {
+ xdr->reghash =
+ JS_NewDHashTable(JS_DHashGetStubOps(), NULL,
+ sizeof(JSRegHashEntry),
+ JS_DHASH_DEFAULT_CAPACITY(numclasses));
+ if (xdr->reghash) {
+ for (i = 0; i < numclasses; i++) {
+ JSClass *clasp = xdr->registry[i];
+ entry = (JSRegHashEntry *)
+ JS_DHashTableOperate((JSDHashTable *) xdr->reghash,
+ clasp->name, JS_DHASH_ADD);
+ entry->name = clasp->name;
+ entry->index = i;
+ }
+ }
+ }
+
+ /* If we managed to create reghash, use it for O(1) Find. */
+ if (xdr->reghash) {
+ entry = (JSRegHashEntry *)
+ JS_DHashTableOperate((JSDHashTable *) xdr->reghash,
+ name, JS_DHASH_LOOKUP);
+ if (JS_DHASH_ENTRY_IS_BUSY(&entry->hdr))
+ return CLASS_INDEX_TO_ID(entry->index);
+ }
+ }
+
+ /* Only a few classes, or we couldn't malloc reghash: use linear search. */
+ for (i = 0; i < numclasses; i++) {
+ if (!strcmp(name, xdr->registry[i]->name))
+ return CLASS_INDEX_TO_ID(i);
+ }
+ return 0;
+}
+
+JS_PUBLIC_API(JSClass *)
+JS_XDRFindClassById(JSXDRState *xdr, uint32 id)
+{
+ uintN i = CLASS_ID_TO_INDEX(id);
+
+ if (i >= xdr->numclasses)
+ return NULL;
+ return xdr->registry[i];
+}
+
+#endif /* JS_HAS_XDR */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h
new file mode 100644
index 0000000..23b2636
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxdrapi.h
@@ -0,0 +1,220 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsxdrapi_h___
+#define jsxdrapi_h___
+
+/*
+ * JS external data representation interface API.
+ *
+ * The XDR system is comprised of three major parts:
+ *
+ * - the state serialization/deserialization APIs, which allow consumers
+ * of the API to serialize JS runtime state (script bytecodes, atom maps,
+ * object graphs, etc.) for later restoration. These portions
+ * are implemented in various appropriate files, such as jsscript.c
+ * for the script portions and jsobj.c for object state.
+ * - the callback APIs through which the runtime requests an opaque
+ * representation of a native object, and through which the runtime
+ * constructs a live native object from an opaque representation. These
+ * portions are the responsibility of the native object implementor.
+ * - utility functions for en/decoding of primitive types, such as
+ * JSStrings. This portion is implemented in jsxdrapi.c.
+ *
+ * Spiritually guided by Sun's XDR, where appropriate.
+ */
+
+#include "jspubtd.h"
+#include "jsprvtd.h"
+
+JS_BEGIN_EXTERN_C
+
+/* We use little-endian byteorder for all encoded data */
+
+#if defined IS_LITTLE_ENDIAN
+#define JSXDR_SWAB32(x) x
+#define JSXDR_SWAB16(x) x
+#elif defined IS_BIG_ENDIAN
+#define JSXDR_SWAB32(x) (((uint32)(x) >> 24) | \
+ (((uint32)(x) >> 8) & 0xff00) | \
+ (((uint32)(x) << 8) & 0xff0000) | \
+ ((uint32)(x) << 24))
+#define JSXDR_SWAB16(x) (((uint16)(x) >> 8) | ((uint16)(x) << 8))
+#else
+#error "unknown byte order"
+#endif
+
+#define JSXDR_ALIGN 4
+
+typedef enum JSXDRMode {
+ JSXDR_ENCODE,
+ JSXDR_DECODE,
+ JSXDR_FREE
+} JSXDRMode;
+
+typedef enum JSXDRWhence {
+ JSXDR_SEEK_SET,
+ JSXDR_SEEK_CUR,
+ JSXDR_SEEK_END
+} JSXDRWhence;
+
+typedef struct JSXDROps {
+ JSBool (*get32)(JSXDRState *, uint32 *);
+ JSBool (*set32)(JSXDRState *, uint32 *);
+ JSBool (*getbytes)(JSXDRState *, char *, uint32);
+ JSBool (*setbytes)(JSXDRState *, char *, uint32);
+ void * (*raw)(JSXDRState *, uint32);
+ JSBool (*seek)(JSXDRState *, int32, JSXDRWhence);
+ uint32 (*tell)(JSXDRState *);
+ void (*finalize)(JSXDRState *);
+} JSXDROps;
+
+struct JSXDRState {
+ JSXDRMode mode;
+ JSXDROps *ops;
+ JSContext *cx;
+ JSClass **registry;
+ uintN numclasses;
+ uintN maxclasses;
+ void *reghash;
+ void *userdata;
+ JSScript *script;
+};
+
+extern JS_PUBLIC_API(void)
+JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx);
+
+extern JS_PUBLIC_API(JSXDRState *)
+JS_XDRNewMem(JSContext *cx, JSXDRMode mode);
+
+extern JS_PUBLIC_API(void *)
+JS_XDRMemGetData(JSXDRState *xdr, uint32 *lp);
+
+extern JS_PUBLIC_API(void)
+JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32 len);
+
+extern JS_PUBLIC_API(uint32)
+JS_XDRMemDataLeft(JSXDRState *xdr);
+
+extern JS_PUBLIC_API(void)
+JS_XDRMemResetData(JSXDRState *xdr);
+
+extern JS_PUBLIC_API(void)
+JS_XDRDestroy(JSXDRState *xdr);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRUint8(JSXDRState *xdr, uint8 *b);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRUint16(JSXDRState *xdr, uint16 *s);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRUint32(JSXDRState *xdr, uint32 *lp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32 len);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRCString(JSXDRState *xdr, char **sp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRCStringOrNull(JSXDRState *xdr, char **sp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRString(JSXDRState *xdr, JSString **strp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRDouble(JSXDRState *xdr, jsdouble **dp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRValue(JSXDRState *xdr, jsval *vp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
+
+extern JS_PUBLIC_API(JSBool)
+JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
+
+extern JS_PUBLIC_API(uint32)
+JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name);
+
+extern JS_PUBLIC_API(JSClass *)
+JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
+
+/*
+ * Magic numbers.
+ */
+#define JSXDR_MAGIC_SCRIPT_1 0xdead0001
+#define JSXDR_MAGIC_SCRIPT_2 0xdead0002
+#define JSXDR_MAGIC_SCRIPT_3 0xdead0003
+#define JSXDR_MAGIC_SCRIPT_4 0xdead0004
+#define JSXDR_MAGIC_SCRIPT_5 0xdead0005
+#define JSXDR_MAGIC_SCRIPT_6 0xdead0006
+#define JSXDR_MAGIC_SCRIPT_7 0xdead0007
+#define JSXDR_MAGIC_SCRIPT_8 0xdead0008
+#define JSXDR_MAGIC_SCRIPT_9 0xdead0009
+#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_9
+
+/*
+ * Bytecode version number. Increment the subtrahend whenever JS bytecode
+ * changes incompatibly.
+ *
+ * This version number should be XDR'ed once near the front of any file or
+ * larger storage unit containing XDR'ed bytecode and other data, and checked
+ * before deserialization of bytecode. If the saved version does not match
+ * the current version, abort deserialization and invalidate the file.
+ */
+#define JSXDR_BYTECODE_VERSION (0xb973c0de - 37)
+
+/*
+ * Library-private functions.
+ */
+extern JSBool
+js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
+
+extern JSBool
+js_XDRStringAtom(JSXDRState *xdr, JSAtom **atomp);
+
+JS_END_EXTERN_C
+
+#endif /* ! jsxdrapi_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp
new file mode 100644
index 0000000..b909219
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.cpp
@@ -0,0 +1,8343 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey E4X code, released August, 2004.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jsstddef.h"
+#include "jsversion.h"
+
+#if JS_HAS_XML_SUPPORT
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "jstypes.h"
+#include "jsbit.h"
+#include "jsprf.h"
+#include "jsutil.h"
+#include "jsapi.h"
+#include "jsarray.h"
+#include "jsatom.h"
+#include "jsbool.h"
+#include "jscntxt.h"
+#include "jsfun.h"
+#include "jsgc.h"
+#include "jsinterp.h"
+#include "jslock.h"
+#include "jsnum.h"
+#include "jsobj.h"
+#include "jsopcode.h"
+#include "jsparse.h"
+#include "jsscan.h"
+#include "jsscope.h"
+#include "jsscript.h"
+#include "jsstr.h"
+#include "jsxml.h"
+#include "jsstaticcheck.h"
+
+#ifdef DEBUG
+#include <string.h> /* for #ifdef DEBUG memset calls */
+#endif
+
+/*
+ * NOTES
+ * - in the js shell, you must use the -x command line option, or call
+ * options('xml') before compiling anything that uses XML literals
+ *
+ * TODO
+ * - XXXbe patrol
+ * - Fuse objects and their JSXML* private data into single GC-things
+ * - fix function::foo vs. x.(foo == 42) collision using proper namespacing
+ * - fix the !TCF_HAS_DEFXMLNS optimization in js_FoldConstants
+ * - JSCLASS_DOCUMENT_OBSERVER support -- live two-way binding to Gecko's DOM!
+ * - JS_TypeOfValue sure could use a cleaner interface to "types"
+ */
+
+#ifdef XML_METERING
+static struct {
+ jsrefcount qname;
+ jsrefcount xmlnamespace;
+ jsrefcount xml;
+ jsrefcount xmlobj;
+} xml_stats;
+
+#define METER(x) JS_ATOMIC_INCREMENT(&(x))
+#define UNMETER(x) JS_ATOMIC_DECREMENT(&(x))
+#else
+#define METER(x) /* nothing */
+#define UNMETER(x) /* nothing */
+#endif
+
+/*
+ * Random utilities and global functions.
+ */
+const char js_isXMLName_str[] = "isXMLName";
+const char js_XMLList_str[] = "XMLList";
+const char js_localName_str[] = "localName";
+const char js_xml_parent_str[] = "parent";
+const char js_prefix_str[] = "prefix";
+const char js_toXMLString_str[] = "toXMLString";
+const char js_uri_str[] = "uri";
+
+const char js_amp_entity_str[] = "&amp;";
+const char js_gt_entity_str[] = "&gt;";
+const char js_lt_entity_str[] = "&lt;";
+const char js_quot_entity_str[] = "&quot;";
+
+#define IS_EMPTY(str) (JSSTRING_LENGTH(str) == 0)
+#define IS_STAR(str) (JSSTRING_LENGTH(str) == 1 && *JSSTRING_CHARS(str) == '*')
+/* Slot indexes shared between Namespace and QName objects. */
+const uint32 JSSLOT_PREFIX = JSSLOT_PRIVATE;
+const uint32 JSSLOT_URI = JSSLOT_PRIVATE + 1;
+
+/* Namespace-specific slot. */
+const uint32 JSSLOT_DECLARED = JSSLOT_PRIVATE + 2;
+
+/* QName-specific slot. */
+const uint32 JSSLOT_LOCAL_NAME = JSSLOT_PRIVATE + 2;
+
+const uint32 NAMESPACE_RESERVED_SLOTS = 3;
+const uint32 QNAME_RESERVED_SLOTS = 3;
+
+static JSBool
+IsQNameClass(JSClass *clasp)
+{
+ return clasp == &js_QNameClass.base ||
+ clasp == &js_AttributeNameClass ||
+ clasp == &js_AnyNameClass;
+}
+
+static JSString *
+GetSlotString(const JSObject *obj, uint32 slot)
+{
+ jsval v;
+
+ JS_ASSERT(slot == JSSLOT_PREFIX ||
+ slot == JSSLOT_URI ||
+ slot == JSSLOT_LOCAL_NAME);
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_NamespaceClass.base ||
+ IsQNameClass(STOBJ_GET_CLASS(obj)));
+ JS_ASSERT_IF(STOBJ_GET_CLASS(obj) == &js_NamespaceClass.base,
+ slot != JSSLOT_LOCAL_NAME);
+
+ v = obj->fslots[slot];
+ if (JSVAL_IS_VOID(v))
+ return NULL;
+ JS_ASSERT(JSVAL_IS_STRING(v));
+ return JSVAL_TO_STRING(v);
+}
+
+static JS_INLINE JSString *
+GetPrefix(const JSObject *obj)
+{
+ return GetSlotString(obj, JSSLOT_PREFIX);
+}
+
+static JSString *
+GetURI(const JSObject *obj)
+{
+ return GetSlotString(obj, JSSLOT_URI);
+}
+
+static JSString *
+GetLocalName(const JSObject *obj)
+{
+ return GetSlotString(obj, JSSLOT_LOCAL_NAME);
+}
+
+static JSBool
+IsDeclared(const JSObject *obj)
+{
+ jsval v;
+
+ JS_ASSERT(STOBJ_GET_CLASS(obj) == &js_NamespaceClass.base);
+ v = obj->fslots[JSSLOT_DECLARED];
+ JS_ASSERT(JSVAL_IS_VOID(v) || v == JSVAL_TRUE);
+ return v == JSVAL_TRUE;
+}
+
+static JSBool
+xml_isXMLName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ *rval = BOOLEAN_TO_JSVAL(js_IsXMLName(cx, argv[0]));
+ return JS_TRUE;
+}
+
+/*
+ * Namespace class and library functions.
+ */
+enum namespace_tinyid {
+ NAMESPACE_PREFIX = -1,
+ NAMESPACE_URI = -2
+};
+
+static JSBool
+namespace_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ if (STOBJ_GET_CLASS(obj) != &js_NamespaceClass.base)
+ return JS_TRUE;
+
+ switch (JSVAL_TO_INT(id)) {
+ case NAMESPACE_PREFIX:
+ *vp = obj->fslots[JSSLOT_PREFIX];
+ break;
+ case NAMESPACE_URI:
+ *vp = obj->fslots[JSSLOT_URI];
+ break;
+ }
+ return JS_TRUE;
+}
+
+static void
+namespace_finalize(JSContext *cx, JSObject *obj)
+{
+ if (cx->runtime->functionNamespaceObject == obj)
+ cx->runtime->functionNamespaceObject = NULL;
+}
+
+static JSBool
+namespace_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSObject *obj2;
+
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ obj2 = JSVAL_TO_OBJECT(v);
+ *bp = (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_NamespaceClass.base)
+ ? JS_FALSE
+ : js_EqualStrings(GetURI(obj), GetURI(obj2));
+ return JS_TRUE;
+}
+
+JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass = {
+ { "Namespace",
+ JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
+ JSCLASS_HAS_RESERVED_SLOTS(NAMESPACE_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_Namespace),
+ JS_PropertyStub, JS_PropertyStub, namespace_getProperty, NULL,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, namespace_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL },
+ namespace_equality,NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+#define NAMESPACE_ATTRS \
+ (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
+
+static JSPropertySpec namespace_props[] = {
+ {js_prefix_str, NAMESPACE_PREFIX, NAMESPACE_ATTRS, 0, 0},
+ {js_uri_str, NAMESPACE_URI, NAMESPACE_ATTRS, 0, 0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+namespace_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_NamespaceClass.base, vp))
+ return JS_FALSE;
+ *vp = obj->fslots[JSSLOT_URI];
+ return JS_TRUE;
+}
+
+static JSFunctionSpec namespace_methods[] = {
+ JS_FN(js_toString_str, namespace_toString, 0,0),
+ JS_FS_END
+};
+
+static JSObject *
+NewXMLNamespace(JSContext *cx, JSString *prefix, JSString *uri, JSBool declared)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_PREFIX]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_URI]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_DECLARED]));
+ if (prefix)
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ if (uri)
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ if (declared)
+ obj->fslots[JSSLOT_DECLARED] = JSVAL_TRUE;
+ METER(xml_stats.xmlnamespace);
+ return obj;
+}
+
+/*
+ * QName class and library functions.
+ */
+enum qname_tinyid {
+ QNAME_URI = -1,
+ QNAME_LOCALNAME = -2
+};
+
+static JSBool
+qname_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ if (!JSVAL_IS_INT(id))
+ return JS_TRUE;
+
+ if (STOBJ_GET_CLASS(obj) != &js_QNameClass.base)
+ return JS_TRUE;
+
+ switch (JSVAL_TO_INT(id)) {
+ case QNAME_URI:
+ *vp = obj->fslots[JSSLOT_URI];
+ if (*vp == JSVAL_VOID)
+ *vp = JSVAL_NULL;
+ break;
+ case QNAME_LOCALNAME:
+ *vp = obj->fslots[JSSLOT_LOCAL_NAME];
+ break;
+ }
+ return JS_TRUE;
+}
+
+static void
+anyname_finalize(JSContext* cx, JSObject* obj)
+{
+ /* Make sure the next call to js_GetAnyName doesn't try to use obj. */
+ if (cx->runtime->anynameObject == obj)
+ cx->runtime->anynameObject = NULL;
+}
+
+static JSBool
+qname_identity(JSObject *qna, JSObject *qnb)
+{
+ JSString *uri1 = GetURI(qna);
+ JSString *uri2 = GetURI(qnb);
+
+ if (!uri1 ^ !uri2)
+ return JS_FALSE;
+ if (uri1 && !js_EqualStrings(uri1, uri2))
+ return JS_FALSE;
+ return js_EqualStrings(GetLocalName(qna), GetLocalName(qnb));
+}
+
+static JSBool
+qname_equality(JSContext *cx, JSObject *qn, jsval v, JSBool *bp)
+{
+ JSObject *obj2;
+
+ JS_ASSERT(JSVAL_IS_OBJECT(v));
+ obj2 = JSVAL_TO_OBJECT(v);
+ *bp = (!obj2 || OBJ_GET_CLASS(cx, obj2) != &js_QNameClass.base)
+ ? JS_FALSE
+ : qname_identity(qn, obj2);
+ return JS_TRUE;
+}
+
+JS_FRIEND_DATA(JSExtendedClass) js_QNameClass = {
+ { "QName",
+ JSCLASS_CONSTRUCT_PROTOTYPE | JSCLASS_IS_EXTENDED |
+ JSCLASS_HAS_RESERVED_SLOTS(QNAME_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_QName),
+ JS_PropertyStub, JS_PropertyStub, qname_getProperty, NULL,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL },
+ qname_equality, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+/*
+ * Classes for the ECMA-357-internal types AttributeName and AnyName, which
+ * are like QName, except that they have no property getters. They share the
+ * qname_toString method, and therefore are exposed as constructable objects
+ * in this implementation.
+ */
+JS_FRIEND_DATA(JSClass) js_AttributeNameClass = {
+ js_AttributeName_str,
+ JSCLASS_CONSTRUCT_PROTOTYPE |
+ JSCLASS_HAS_RESERVED_SLOTS(QNAME_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AttributeName),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+JS_FRIEND_DATA(JSClass) js_AnyNameClass = {
+ js_AnyName_str,
+ JSCLASS_CONSTRUCT_PROTOTYPE |
+ JSCLASS_HAS_RESERVED_SLOTS(QNAME_RESERVED_SLOTS) |
+ JSCLASS_MARK_IS_TRACE | JSCLASS_HAS_CACHED_PROTO(JSProto_AnyName),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, anyname_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL
+};
+
+#define QNAME_ATTRS \
+ (JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED)
+
+static JSPropertySpec qname_props[] = {
+ {js_uri_str, QNAME_URI, QNAME_ATTRS, 0, 0},
+ {js_localName_str, QNAME_LOCALNAME, QNAME_ATTRS, 0, 0},
+ {0,0,0,0,0}
+};
+
+static JSBool
+qname_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ JSClass *clasp;
+ JSString *uri, *str, *qualstr;
+ size_t length;
+ jschar *chars;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp != &js_AttributeNameClass &&
+ clasp != &js_AnyNameClass &&
+ !JS_InstanceOf(cx, obj, &js_QNameClass.base, vp + 2)) {
+ return JS_FALSE;
+ }
+
+ uri = GetURI(obj);
+ if (!uri) {
+ /* No uri means wildcard qualifier. */
+ str = ATOM_TO_STRING(cx->runtime->atomState.starQualifierAtom);
+ } else if (IS_EMPTY(uri)) {
+ /* Empty string for uri means localName is in no namespace. */
+ str = cx->runtime->emptyString;
+ } else {
+ qualstr = ATOM_TO_STRING(cx->runtime->atomState.qualifierAtom);
+ str = js_ConcatStrings(cx, uri, qualstr);
+ if (!str)
+ return JS_FALSE;
+ }
+ str = js_ConcatStrings(cx, str, GetLocalName(obj));
+ if (!str)
+ return JS_FALSE;
+
+ if (str && clasp == &js_AttributeNameClass) {
+ length = JSSTRING_LENGTH(str);
+ chars = (jschar *) JS_malloc(cx, (length + 2) * sizeof(jschar));
+ if (!chars)
+ return JS_FALSE;
+ *chars = '@';
+ js_strncpy(chars + 1, JSSTRING_CHARS(str), length);
+ chars[++length] = 0;
+ str = js_NewString(cx, chars, length);
+ if (!str) {
+ JS_free(cx, chars);
+ return JS_FALSE;
+ }
+ }
+
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSFunctionSpec qname_methods[] = {
+ JS_FN(js_toString_str, qname_toString, 0,0),
+ JS_FS_END
+};
+
+
+static void
+InitXMLQName(JSObject *obj, JSString *uri, JSString *prefix,
+ JSString *localName)
+{
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_PREFIX]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_URI]));
+ JS_ASSERT(JSVAL_IS_VOID(obj->fslots[JSSLOT_LOCAL_NAME]));
+ if (uri)
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ if (prefix)
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ if (localName)
+ obj->fslots[JSSLOT_LOCAL_NAME] = STRING_TO_JSVAL(localName);
+}
+
+static JSObject *
+NewXMLQName(JSContext *cx, JSString *uri, JSString *prefix, JSString *localName,
+ JSClass *clasp = &js_QNameClass.base)
+{
+ JSObject *obj;
+
+ JS_ASSERT(IsQNameClass(clasp));
+ obj = js_NewObject(cx, clasp, NULL, NULL, 0);
+ if (!obj)
+ return NULL;
+ InitXMLQName(obj, uri, prefix, localName);
+ METER(xml_stats.qname);
+ return obj;
+}
+
+JSObject *
+js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval)
+{
+ jsval argv[2];
+
+ /*
+ * ECMA-357 11.1.2,
+ * The _QualifiedIdentifier : PropertySelector :: PropertySelector_
+ * production, step 2.
+ */
+ if (!JSVAL_IS_PRIMITIVE(nsval) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nsval)) == &js_AnyNameClass) {
+ nsval = JSVAL_NULL;
+ }
+
+ argv[0] = nsval;
+ argv[1] = lnval;
+ return js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, argv);
+}
+
+static JSBool
+IsXMLName(const jschar *cp, size_t n)
+{
+ JSBool rv;
+ jschar c;
+
+ rv = JS_FALSE;
+ if (n != 0 && JS_ISXMLNSSTART(*cp)) {
+ while (--n != 0) {
+ c = *++cp;
+ if (!JS_ISXMLNS(c))
+ return rv;
+ }
+ rv = JS_TRUE;
+ }
+ return rv;
+}
+
+JSBool
+js_IsXMLName(JSContext *cx, jsval v)
+{
+ JSString *name;
+ JSErrorReporter older;
+
+ /*
+ * Inline specialization of the QName constructor called with v passed as
+ * the only argument, to compute the localName for the constructed qname,
+ * without actually allocating the object or computing its uri and prefix.
+ * See ECMA-357 13.1.2.1 step 1 and 13.3.2.
+ */
+ if (!JSVAL_IS_PRIMITIVE(v) &&
+ IsQNameClass(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)))) {
+ name = GetLocalName(JSVAL_TO_OBJECT(v));
+ } else {
+ older = JS_SetErrorReporter(cx, NULL);
+ name = js_ValueToString(cx, v);
+ JS_SetErrorReporter(cx, older);
+ if (!name) {
+ JS_ClearPendingException(cx);
+ return JS_FALSE;
+ }
+ }
+
+ return IsXMLName(JSSTRING_CHARS(name), JSSTRING_LENGTH(name));
+}
+
+/*
+ * When argc is -1, it indicates argv is empty but the code should behave as
+ * if argc is 1 and argv[0] is JSVAL_VOID.
+ */
+static JSBool
+NamespaceHelper(JSContext *cx, JSObject *obj, intN argc, jsval *argv,
+ jsval *rval)
+{
+ jsval urival, prefixval;
+ JSObject *uriobj;
+ JSBool isNamespace, isQName;
+ JSClass *clasp;
+ JSString *empty, *uri, *prefix;
+
+ isNamespace = isQName = JS_FALSE;
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ uriobj = NULL;
+#endif
+ if (argc <= 0) {
+ urival = JSVAL_VOID;
+ } else {
+ urival = argv[argc > 1];
+ if (!JSVAL_IS_PRIMITIVE(urival)) {
+ uriobj = JSVAL_TO_OBJECT(urival);
+ clasp = OBJ_GET_CLASS(cx, uriobj);
+ isNamespace = (clasp == &js_NamespaceClass.base);
+ isQName = (clasp == &js_QNameClass.base);
+ }
+ }
+
+ if (!obj) {
+ /* Namespace called as function. */
+ if (argc == 1 && isNamespace) {
+ /* Namespace called with one Namespace argument is identity. */
+ *rval = urival;
+ return JS_TRUE;
+ }
+
+ obj = js_NewObject(cx, &js_NamespaceClass.base, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+ METER(xml_stats.xmlnamespace);
+
+ empty = cx->runtime->emptyString;
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(empty);
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(empty);
+
+ if (argc == 1 || argc == -1) {
+ if (isNamespace) {
+ obj->fslots[JSSLOT_URI] = uriobj->fslots[JSSLOT_URI];
+ obj->fslots[JSSLOT_PREFIX] = uriobj->fslots[JSSLOT_PREFIX];
+ } else if (isQName && (uri = GetURI(uriobj))) {
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ obj->fslots[JSSLOT_PREFIX] = uriobj->fslots[JSSLOT_PREFIX];
+ } else {
+ uri = js_ValueToString(cx, urival);
+ if (!uri)
+ return JS_FALSE;
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+ if (!IS_EMPTY(uri))
+ obj->fslots[JSSLOT_PREFIX] = JSVAL_VOID;
+ }
+ } else if (argc == 2) {
+ if (!isQName || !(uri = GetURI(uriobj))) {
+ uri = js_ValueToString(cx, urival);
+ if (!uri)
+ return JS_FALSE;
+ }
+ obj->fslots[JSSLOT_URI] = STRING_TO_JSVAL(uri);
+
+ prefixval = argv[0];
+ if (IS_EMPTY(uri)) {
+ if (!JSVAL_IS_VOID(prefixval)) {
+ prefix = js_ValueToString(cx, prefixval);
+ if (!prefix)
+ return JS_FALSE;
+ if (!IS_EMPTY(prefix)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_NAMESPACE,
+ js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(prefix)));
+ return JS_FALSE;
+ }
+ }
+ } else if (JSVAL_IS_VOID(prefixval) || !js_IsXMLName(cx, prefixval)) {
+ obj->fslots[JSSLOT_PREFIX] = JSVAL_VOID;
+ } else {
+ prefix = js_ValueToString(cx, prefixval);
+ if (!prefix)
+ return JS_FALSE;
+ obj->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+Namespace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ return NamespaceHelper(cx,
+ (cx->fp->flags & JSFRAME_CONSTRUCTING) ? obj : NULL,
+ argc, argv, rval);
+}
+
+/*
+ * When argc is -1, it indicates argv is empty but the code should behave as
+ * if argc is 1 and argv[0] is JSVAL_VOID.
+ */
+static JSBool
+QNameHelper(JSContext *cx, JSObject *obj, JSClass *clasp, intN argc,
+ jsval *argv, jsval *rval)
+{
+ jsval nameval, nsval;
+ JSBool isQName, isNamespace;
+ JSObject *qn;
+ JSString *uri, *prefix, *name;
+ JSObject *obj2;
+
+ JS_ASSERT(clasp == &js_QNameClass.base ||
+ clasp == &js_AttributeNameClass);
+ if (argc <= 0) {
+ nameval = JSVAL_VOID;
+ isQName = JS_FALSE;
+ } else {
+ nameval = argv[argc > 1];
+ isQName =
+ !JSVAL_IS_PRIMITIVE(nameval) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nameval)) == &js_QNameClass.base;
+ }
+
+ if (!obj) {
+ /* QName called as function. */
+ if (argc == 1 && isQName) {
+ /* QName called with one QName argument is identity. */
+ *rval = nameval;
+ return JS_TRUE;
+ }
+
+ /*
+ * Create and return a new QName or AttributeName object exactly as if
+ * constructed.
+ */
+ obj = js_NewObject(cx, clasp, NULL, NULL, 0);
+ if (!obj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(obj);
+ }
+ METER(xml_stats.qname);
+
+ if (isQName) {
+ /* If namespace is not specified and name is a QName, clone it. */
+ qn = JSVAL_TO_OBJECT(nameval);
+ if (argc == 1) {
+ uri = GetURI(qn);
+ prefix = GetPrefix(qn);
+ name = GetLocalName(qn);
+ goto out;
+ }
+
+ /* Namespace and qname were passed -- use the qname's localName. */
+ nameval = qn->fslots[JSSLOT_LOCAL_NAME];
+ }
+
+ if (argc == 0) {
+ name = cx->runtime->emptyString;
+ } else if (argc < 0) {
+ name = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ } else {
+ name = js_ValueToString(cx, nameval);
+ if (!name)
+ return JS_FALSE;
+ argv[argc > 1] = STRING_TO_JSVAL(name);
+ }
+
+ if (argc > 1 && !JSVAL_IS_VOID(argv[0])) {
+ nsval = argv[0];
+ } else if (IS_STAR(name)) {
+ nsval = JSVAL_NULL;
+ } else {
+ if (!js_GetDefaultXMLNamespace(cx, &nsval))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval));
+ JS_ASSERT(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(nsval)) ==
+ &js_NamespaceClass.base);
+ }
+
+ if (JSVAL_IS_NULL(nsval)) {
+ /* NULL prefix represents *undefined* in ECMA-357 13.3.2 5(a). */
+ uri = prefix = NULL;
+ } else {
+ /*
+ * Inline specialization of the Namespace constructor called with
+ * nsval passed as the only argument, to compute the uri and prefix
+ * for the constructed namespace, without actually allocating the
+ * object or computing other members. See ECMA-357 13.3.2 6(a) and
+ * 13.2.2.
+ */
+ isNamespace = isQName = JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(nsval)) {
+ obj2 = JSVAL_TO_OBJECT(nsval);
+ clasp = OBJ_GET_CLASS(cx, obj2);
+ isNamespace = (clasp == &js_NamespaceClass.base);
+ isQName = (clasp == &js_QNameClass.base);
+ }
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ else obj2 = NULL;
+#endif
+
+ if (isNamespace) {
+ uri = GetURI(obj2);
+ prefix = GetPrefix(obj2);
+ } else if (isQName && (uri = GetURI(obj2))) {
+ JS_ASSERT(argc > 1);
+ prefix = GetPrefix(obj2);
+ } else {
+ JS_ASSERT(argc > 1);
+ uri = js_ValueToString(cx, nsval);
+ if (!uri)
+ return JS_FALSE;
+ argv[0] = STRING_TO_JSVAL(uri); /* local root */
+
+ /* NULL here represents *undefined* in ECMA-357 13.2.2 3(c)iii. */
+ prefix = IS_EMPTY(uri) ? cx->runtime->emptyString : NULL;
+ }
+ }
+
+out:
+ InitXMLQName(obj, uri, prefix, name);
+ return JS_TRUE;
+}
+
+static JSBool
+QName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ return QNameHelper(cx, (cx->fp->flags & JSFRAME_CONSTRUCTING) ? obj : NULL,
+ &js_QNameClass.base, argc, argv, rval);
+}
+
+static JSBool
+AttributeName(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ return QNameHelper(cx, (cx->fp->flags & JSFRAME_CONSTRUCTING) ? obj : NULL,
+ &js_AttributeNameClass, argc, argv, rval);
+}
+
+/*
+ * XMLArray library functions.
+ */
+static JSBool
+namespace_identity(const void *a, const void *b)
+{
+ const JSObject *nsa = (const JSObject *) a;
+ const JSObject *nsb = (const JSObject *) b;
+ JSString *prefixa = GetPrefix(nsa);
+ JSString *prefixb = GetPrefix(nsb);
+
+ if (prefixa && prefixb) {
+ if (!js_EqualStrings(prefixa, prefixb))
+ return JS_FALSE;
+ } else {
+ if (prefixa || prefixb)
+ return JS_FALSE;
+ }
+ return js_EqualStrings(GetURI(nsa), GetURI(nsb));
+}
+
+static JSBool
+attr_identity(const void *a, const void *b)
+{
+ const JSXML *xmla = (const JSXML *) a;
+ const JSXML *xmlb = (const JSXML *) b;
+
+ return qname_identity(xmla->name, xmlb->name);
+}
+
+static void
+XMLArrayCursorInit(JSXMLArrayCursor *cursor, JSXMLArray *array)
+{
+ JSXMLArrayCursor *next;
+
+ cursor->array = array;
+ cursor->index = 0;
+ next = cursor->next = array->cursors;
+ if (next)
+ next->prevp = &cursor->next;
+ cursor->prevp = &array->cursors;
+ array->cursors = cursor;
+ cursor->root = NULL;
+}
+
+static void
+XMLArrayCursorFinish(JSXMLArrayCursor *cursor)
+{
+ JSXMLArrayCursor *next;
+
+ if (!cursor->array)
+ return;
+ next = cursor->next;
+ if (next)
+ next->prevp = cursor->prevp;
+ *cursor->prevp = next;
+ cursor->array = NULL;
+}
+
+static void *
+XMLArrayCursorNext(JSXMLArrayCursor *cursor)
+{
+ JSXMLArray *array;
+
+ array = cursor->array;
+ if (!array || cursor->index >= array->length)
+ return NULL;
+ return cursor->root = array->vector[cursor->index++];
+}
+
+static void *
+XMLArrayCursorItem(JSXMLArrayCursor *cursor)
+{
+ JSXMLArray *array;
+
+ array = cursor->array;
+ if (!array || cursor->index >= array->length)
+ return NULL;
+ return cursor->root = array->vector[cursor->index];
+}
+
+static void
+XMLArrayCursorTrace(JSTracer *trc, JSXMLArrayCursor *cursor)
+{
+ void *root;
+#ifdef DEBUG
+ size_t index = 0;
+#endif
+
+ for (; cursor; cursor = cursor->next) {
+ root = cursor->root;
+ JS_SET_TRACING_INDEX(trc, "cursor_root", index++);
+ js_CallValueTracerIfGCThing(trc, (jsval)root);
+ }
+}
+
+/* NB: called with null cx from the GC, via xml_trace => XMLArrayTrim. */
+static JSBool
+XMLArraySetCapacity(JSContext *cx, JSXMLArray *array, uint32 capacity)
+{
+ void **vector;
+
+ if (capacity == 0) {
+ /* We could let realloc(p, 0) free this, but purify gets confused. */
+ if (array->vector)
+ free(array->vector);
+ vector = NULL;
+ } else {
+ if (
+#if JS_BITS_PER_WORD == 32
+ (size_t)capacity > ~(size_t)0 / sizeof(void *) ||
+#endif
+ !(vector = (void **)
+ realloc(array->vector, capacity * sizeof(void *)))) {
+ if (cx)
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ }
+ array->capacity = JSXML_PRESET_CAPACITY | capacity;
+ array->vector = vector;
+ return JS_TRUE;
+}
+
+static void
+XMLArrayTrim(JSXMLArray *array)
+{
+ if (array->capacity & JSXML_PRESET_CAPACITY)
+ return;
+ if (array->length < array->capacity)
+ XMLArraySetCapacity(NULL, array, array->length);
+}
+
+static JSBool
+XMLArrayInit(JSContext *cx, JSXMLArray *array, uint32 capacity)
+{
+ array->length = array->capacity = 0;
+ array->vector = NULL;
+ array->cursors = NULL;
+ return capacity == 0 || XMLArraySetCapacity(cx, array, capacity);
+}
+
+static void
+XMLArrayFinish(JSContext *cx, JSXMLArray *array)
+{
+ JSXMLArrayCursor *cursor;
+
+ JS_free(cx, array->vector);
+
+ while ((cursor = array->cursors) != NULL)
+ XMLArrayCursorFinish(cursor);
+
+#ifdef DEBUG
+ memset(array, 0xd5, sizeof *array);
+#endif
+}
+
+#define XML_NOT_FOUND ((uint32) -1)
+
+static uint32
+XMLArrayFindMember(const JSXMLArray *array, void *elt, JSIdentityOp identity)
+{
+ void **vector;
+ uint32 i, n;
+
+ /* The identity op must not reallocate array->vector. */
+ vector = array->vector;
+ if (identity) {
+ for (i = 0, n = array->length; i < n; i++) {
+ if (identity(vector[i], elt))
+ return i;
+ }
+ } else {
+ for (i = 0, n = array->length; i < n; i++) {
+ if (vector[i] == elt)
+ return i;
+ }
+ }
+ return XML_NOT_FOUND;
+}
+
+/*
+ * Grow array vector capacity by powers of two to LINEAR_THRESHOLD, and after
+ * that, grow by LINEAR_INCREMENT. Both must be powers of two, and threshold
+ * should be greater than increment.
+ */
+#define LINEAR_THRESHOLD 256
+#define LINEAR_INCREMENT 32
+
+static JSBool
+XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt)
+{
+ uint32 capacity, i;
+ int log2;
+ void **vector;
+
+ if (index >= array->length) {
+ if (index >= JSXML_CAPACITY(array)) {
+ /* Arrange to clear JSXML_PRESET_CAPACITY from array->capacity. */
+ capacity = index + 1;
+ if (index >= LINEAR_THRESHOLD) {
+ capacity = JS_ROUNDUP(capacity, LINEAR_INCREMENT);
+ } else {
+ JS_CEILING_LOG2(log2, capacity);
+ capacity = JS_BIT(log2);
+ }
+ if (
+#if JS_BITS_PER_WORD == 32
+ (size_t)capacity > ~(size_t)0 / sizeof(void *) ||
+#endif
+ !(vector = (void **)
+ realloc(array->vector, capacity * sizeof(void *)))) {
+ JS_ReportOutOfMemory(cx);
+ return JS_FALSE;
+ }
+ array->capacity = capacity;
+ array->vector = vector;
+ for (i = array->length; i < index; i++)
+ vector[i] = NULL;
+ }
+ array->length = index + 1;
+ }
+
+ array->vector[index] = elt;
+ return JS_TRUE;
+}
+
+static JSBool
+XMLArrayInsert(JSContext *cx, JSXMLArray *array, uint32 i, uint32 n)
+{
+ uint32 j;
+ JSXMLArrayCursor *cursor;
+
+ j = array->length;
+ JS_ASSERT(i <= j);
+ if (!XMLArraySetCapacity(cx, array, j + n))
+ return JS_FALSE;
+
+ array->length = j + n;
+ JS_ASSERT(n != (uint32)-1);
+ while (j != i) {
+ --j;
+ array->vector[j + n] = array->vector[j];
+ }
+
+ for (cursor = array->cursors; cursor; cursor = cursor->next) {
+ if (cursor->index > i)
+ cursor->index += n;
+ }
+ return JS_TRUE;
+}
+
+static void *
+XMLArrayDelete(JSContext *cx, JSXMLArray *array, uint32 index, JSBool compress)
+{
+ uint32 length;
+ void **vector, *elt;
+ JSXMLArrayCursor *cursor;
+
+ length = array->length;
+ if (index >= length)
+ return NULL;
+
+ vector = array->vector;
+ elt = vector[index];
+ if (compress) {
+ while (++index < length)
+ vector[index-1] = vector[index];
+ array->length = length - 1;
+ array->capacity = JSXML_CAPACITY(array);
+ } else {
+ vector[index] = NULL;
+ }
+
+ for (cursor = array->cursors; cursor; cursor = cursor->next) {
+ if (cursor->index > index)
+ --cursor->index;
+ }
+ return elt;
+}
+
+static void
+XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length)
+{
+ void **vector;
+
+ JS_ASSERT(!array->cursors);
+ if (length >= array->length)
+ return;
+
+ if (length == 0) {
+ if (array->vector)
+ free(array->vector);
+ vector = NULL;
+ } else {
+ vector = (void **) realloc(array->vector, length * sizeof(void *));
+ if (!vector)
+ return;
+ }
+
+ if (array->length > length)
+ array->length = length;
+ array->capacity = length;
+ array->vector = vector;
+}
+
+#define XMLARRAY_FIND_MEMBER(a,e,f) XMLArrayFindMember(a, (void *)(e), f)
+#define XMLARRAY_HAS_MEMBER(a,e,f) (XMLArrayFindMember(a, (void *)(e), f) != \
+ XML_NOT_FOUND)
+#define XMLARRAY_MEMBER(a,i,t) (((i) < (a)->length) \
+ ? (t *) (a)->vector[i] \
+ : NULL)
+#define XMLARRAY_SET_MEMBER(a,i,e) JS_BEGIN_MACRO \
+ if ((a)->length <= (i)) \
+ (a)->length = (i) + 1; \
+ ((a)->vector[i] = (void *)(e)); \
+ JS_END_MACRO
+#define XMLARRAY_ADD_MEMBER(x,a,i,e)XMLArrayAddMember(x, a, i, (void *)(e))
+#define XMLARRAY_INSERT(x,a,i,n) XMLArrayInsert(x, a, i, n)
+#define XMLARRAY_APPEND(x,a,e) XMLARRAY_ADD_MEMBER(x, a, (a)->length, (e))
+#define XMLARRAY_DELETE(x,a,i,c,t) ((t *) XMLArrayDelete(x, a, i, c))
+#define XMLARRAY_TRUNCATE(x,a,n) XMLArrayTruncate(x, a, n)
+
+/*
+ * Define XML setting property strings and constants early, so everyone can
+ * use the same names and their magic numbers (tinyids, flags).
+ */
+static const char js_ignoreComments_str[] = "ignoreComments";
+static const char js_ignoreProcessingInstructions_str[]
+ = "ignoreProcessingInstructions";
+static const char js_ignoreWhitespace_str[] = "ignoreWhitespace";
+static const char js_prettyPrinting_str[] = "prettyPrinting";
+static const char js_prettyIndent_str[] = "prettyIndent";
+
+/*
+ * NB: These XML static property tinyids must
+ * (a) not collide with the generic negative tinyids at the top of jsfun.c;
+ * (b) index their corresponding xml_static_props array elements.
+ * Don't change 'em!
+ */
+enum xml_static_tinyid {
+ XML_IGNORE_COMMENTS,
+ XML_IGNORE_PROCESSING_INSTRUCTIONS,
+ XML_IGNORE_WHITESPACE,
+ XML_PRETTY_PRINTING,
+ XML_PRETTY_INDENT
+};
+
+static JSBool
+xml_setting_getter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setting_setter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ uint8 flag;
+
+ JS_ASSERT(JSVAL_IS_INT(id));
+
+ flag = JS_BIT(JSVAL_TO_INT(id));
+ if (js_ValueToBoolean(*vp))
+ cx->xmlSettingFlags |= flag;
+ else
+ cx->xmlSettingFlags &= ~flag;
+ return JS_TRUE;
+}
+
+static JSPropertySpec xml_static_props[] = {
+ {js_ignoreComments_str, XML_IGNORE_COMMENTS, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_ignoreProcessingInstructions_str,
+ XML_IGNORE_PROCESSING_INSTRUCTIONS, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_ignoreWhitespace_str, XML_IGNORE_WHITESPACE, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_prettyPrinting_str, XML_PRETTY_PRINTING, JSPROP_PERMANENT,
+ xml_setting_getter, xml_setting_setter},
+ {js_prettyIndent_str, XML_PRETTY_INDENT, JSPROP_PERMANENT,
+ xml_setting_getter, NULL},
+ {0,0,0,0,0}
+};
+
+/* Derive cx->xmlSettingFlags bits from xml_static_props tinyids. */
+#define XSF_IGNORE_COMMENTS JS_BIT(XML_IGNORE_COMMENTS)
+#define XSF_IGNORE_PROCESSING_INSTRUCTIONS \
+ JS_BIT(XML_IGNORE_PROCESSING_INSTRUCTIONS)
+#define XSF_IGNORE_WHITESPACE JS_BIT(XML_IGNORE_WHITESPACE)
+#define XSF_PRETTY_PRINTING JS_BIT(XML_PRETTY_PRINTING)
+#define XSF_CACHE_VALID JS_BIT(XML_PRETTY_INDENT)
+
+/*
+ * Extra, unrelated but necessarily disjoint flag used by ParseNodeToXML.
+ * This flag means a couple of things:
+ *
+ * - The top JSXML created for a parse tree must have an object owning it.
+ *
+ * - That the default namespace normally inherited from the temporary
+ * <parent xmlns='...'> tag that wraps a runtime-concatenated XML source
+ * string must, in the case of a precompiled XML object tree, inherit via
+ * ad-hoc code in ParseNodeToXML.
+ *
+ * Because of the second purpose, we name this flag XSF_PRECOMPILED_ROOT.
+ */
+#define XSF_PRECOMPILED_ROOT (XSF_CACHE_VALID << 1)
+
+/* Macros for special-casing xml:, xmlns= and xmlns:foo= in ParseNodeToQName. */
+#define IS_XML(str) \
+ (JSSTRING_LENGTH(str) == 3 && IS_XML_CHARS(JSSTRING_CHARS(str)))
+
+#define IS_XMLNS(str) \
+ (JSSTRING_LENGTH(str) == 5 && IS_XMLNS_CHARS(JSSTRING_CHARS(str)))
+
+#define IS_XML_CHARS(chars) \
+ (JS_TOLOWER((chars)[0]) == 'x' && \
+ JS_TOLOWER((chars)[1]) == 'm' && \
+ JS_TOLOWER((chars)[2]) == 'l')
+
+#define HAS_NS_AFTER_XML(chars) \
+ (JS_TOLOWER((chars)[3]) == 'n' && \
+ JS_TOLOWER((chars)[4]) == 's')
+
+#define IS_XMLNS_CHARS(chars) \
+ (IS_XML_CHARS(chars) && HAS_NS_AFTER_XML(chars))
+
+#define STARTS_WITH_XML(chars,length) \
+ (length >= 3 && IS_XML_CHARS(chars))
+
+static const char xml_namespace_str[] = "http://www.w3.org/XML/1998/namespace";
+static const char xmlns_namespace_str[] = "http://www.w3.org/2000/xmlns/";
+
+static JSObject *
+ParseNodeToQName(JSContext *cx, JSParseContext *pc, JSParseNode *pn,
+ JSXMLArray *inScopeNSes, JSBool isAttributeName)
+{
+ JSString *str, *uri, *prefix, *localName;
+ size_t length, offset;
+ const jschar *start, *limit, *colon;
+ uint32 n;
+ JSObject *ns;
+ JSString *nsprefix;
+
+ JS_ASSERT(pn->pn_arity == PN_NULLARY);
+ str = ATOM_TO_STRING(pn->pn_atom);
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ JS_ASSERT(length != 0 && *start != '@');
+ JS_ASSERT(length != 1 || *start != '*');
+
+ uri = cx->runtime->emptyString;
+ limit = start + length;
+ colon = js_strchr_limit(start, ':', limit);
+ if (colon) {
+ offset = PTRDIFF(colon, start, jschar);
+ prefix = js_NewDependentString(cx, str, 0, offset);
+ if (!prefix)
+ return NULL;
+
+ if (STARTS_WITH_XML(start, offset)) {
+ if (offset == 3) {
+ uri = JS_InternString(cx, xml_namespace_str);
+ if (!uri)
+ return NULL;
+ } else if (offset == 5 && HAS_NS_AFTER_XML(start)) {
+ uri = JS_InternString(cx, xmlns_namespace_str);
+ if (!uri)
+ return NULL;
+ } else {
+ uri = NULL;
+ }
+ } else {
+ uri = NULL;
+ n = inScopeNSes->length;
+ while (n != 0) {
+ --n;
+ ns = XMLARRAY_MEMBER(inScopeNSes, n, JSObject);
+ nsprefix = GetPrefix(ns);
+ if (nsprefix && js_EqualStrings(nsprefix, prefix)) {
+ uri = GetURI(ns);
+ break;
+ }
+ }
+ }
+
+ if (!uri) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn,
+ JSREPORT_ERROR,
+ JSMSG_BAD_XML_NAMESPACE,
+ js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(prefix)));
+ return NULL;
+ }
+
+ localName = js_NewStringCopyN(cx, colon + 1, length - (offset + 1));
+ if (!localName)
+ return NULL;
+ } else {
+ if (isAttributeName) {
+ /*
+ * An unprefixed attribute is not in any namespace, so set prefix
+ * as well as uri to the empty string.
+ */
+ prefix = uri;
+ } else {
+ /*
+ * Loop from back to front looking for the closest declared default
+ * namespace.
+ */
+ n = inScopeNSes->length;
+ while (n != 0) {
+ --n;
+ ns = XMLARRAY_MEMBER(inScopeNSes, n, JSObject);
+ nsprefix = GetPrefix(ns);
+ if (!nsprefix || IS_EMPTY(nsprefix)) {
+ uri = GetURI(ns);
+ break;
+ }
+ }
+ prefix = IS_EMPTY(uri) ? cx->runtime->emptyString : NULL;
+ }
+ localName = str;
+ }
+
+ return NewXMLQName(cx, uri, prefix, localName);
+}
+
+static JSString *
+ChompXMLWhitespace(JSContext *cx, JSString *str)
+{
+ size_t length, newlength, offset;
+ const jschar *cp, *start, *end;
+ jschar c;
+
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ for (cp = start, end = cp + length; cp < end; cp++) {
+ c = *cp;
+ if (!JS_ISXMLSPACE(c))
+ break;
+ }
+ while (end > cp) {
+ c = end[-1];
+ if (!JS_ISXMLSPACE(c))
+ break;
+ --end;
+ }
+ newlength = PTRDIFF(end, cp, jschar);
+ if (newlength == length)
+ return str;
+ offset = PTRDIFF(cp, start, jschar);
+ return js_NewDependentString(cx, str, offset, newlength);
+}
+
+static JSXML *
+ParseNodeToXML(JSContext *cx, JSParseContext *pc, JSParseNode *pn,
+ JSXMLArray *inScopeNSes, uintN flags)
+{
+ JSXML *xml, *kid, *attr, *attrj;
+ JSString *str;
+ uint32 length, n, i, j;
+ JSParseNode *pn2, *pn3, *head, **pnp;
+ JSObject *ns;
+ JSObject *qn, *attrjqn;
+ JSXMLClass xml_class;
+ int stackDummy;
+
+ if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn, JSREPORT_ERROR,
+ JSMSG_OVER_RECURSED);
+ return NULL;
+ }
+
+#define PN2X_SKIP_CHILD ((JSXML *) 1)
+
+ /*
+ * Cases return early to avoid common code that gets an outermost xml's
+ * object, which protects GC-things owned by xml and its descendants from
+ * garbage collection.
+ */
+ xml = NULL;
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ switch (pn->pn_type) {
+ case TOK_XMLELEM:
+ length = inScopeNSes->length;
+ pn2 = pn->pn_head;
+ xml = ParseNodeToXML(cx, pc, pn2, inScopeNSes, flags);
+ if (!xml)
+ goto fail;
+
+ flags &= ~XSF_PRECOMPILED_ROOT;
+ n = pn->pn_count;
+ JS_ASSERT(n >= 2);
+ n -= 2;
+ if (!XMLArraySetCapacity(cx, &xml->xml_kids, n))
+ goto fail;
+
+ i = 0;
+ while ((pn2 = pn2->pn_next) != NULL) {
+ if (!pn2->pn_next) {
+ /* Don't append the end tag! */
+ JS_ASSERT(pn2->pn_type == TOK_XMLETAGO);
+ break;
+ }
+
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ n > 1 && pn2->pn_type == TOK_XMLSPACE) {
+ --n;
+ continue;
+ }
+
+ kid = ParseNodeToXML(cx, pc, pn2, inScopeNSes, flags);
+ if (kid == PN2X_SKIP_CHILD) {
+ --n;
+ continue;
+ }
+
+ if (!kid)
+ goto fail;
+
+ /* Store kid in xml right away, to protect it from GC. */
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid);
+ kid->parent = xml;
+ ++i;
+
+ /* XXX where is this documented in an XML spec, or in E4X? */
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ n > 1 && kid->xml_class == JSXML_CLASS_TEXT) {
+ str = ChompXMLWhitespace(cx, kid->xml_value);
+ if (!str)
+ goto fail;
+ kid->xml_value = str;
+ }
+ }
+
+ JS_ASSERT(i == n);
+ if (n < pn->pn_count - 2)
+ XMLArrayTrim(&xml->xml_kids);
+ XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
+ break;
+
+ case TOK_XMLLIST:
+ xml = js_NewXML(cx, JSXML_CLASS_LIST);
+ if (!xml)
+ goto fail;
+
+ n = pn->pn_count;
+ if (!XMLArraySetCapacity(cx, &xml->xml_kids, n))
+ goto fail;
+
+ i = 0;
+ for (pn2 = pn->pn_head; pn2; pn2 = pn2->pn_next) {
+ /*
+ * Always ignore insignificant whitespace in lists -- we shouldn't
+ * condition this on an XML.ignoreWhitespace setting when the list
+ * constructor is XMLList (note XML/XMLList unification hazard).
+ */
+ if (pn2->pn_type == TOK_XMLSPACE) {
+ --n;
+ continue;
+ }
+
+ kid = ParseNodeToXML(cx, pc, pn2, inScopeNSes, flags);
+ if (kid == PN2X_SKIP_CHILD) {
+ --n;
+ continue;
+ }
+
+ if (!kid)
+ goto fail;
+
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, kid);
+ ++i;
+ }
+
+ if (n < pn->pn_count)
+ XMLArrayTrim(&xml->xml_kids);
+ break;
+
+ case TOK_XMLSTAGO:
+ case TOK_XMLPTAGC:
+ length = inScopeNSes->length;
+ pn2 = pn->pn_head;
+ JS_ASSERT(pn2->pn_type == TOK_XMLNAME);
+ if (pn2->pn_arity == PN_LIST)
+ goto syntax;
+
+ xml = js_NewXML(cx, JSXML_CLASS_ELEMENT);
+ if (!xml)
+ goto fail;
+
+ /* First pass: check syntax and process namespace declarations. */
+ JS_ASSERT(pn->pn_count >= 1);
+ n = pn->pn_count - 1;
+ pnp = &pn2->pn_next;
+ head = *pnp;
+ while ((pn2 = *pnp) != NULL) {
+ size_t length;
+ const jschar *chars;
+
+ if (pn2->pn_type != TOK_XMLNAME || pn2->pn_arity != PN_NULLARY)
+ goto syntax;
+
+ /* Enforce "Well-formedness constraint: Unique Att Spec". */
+ for (pn3 = head; pn3 != pn2; pn3 = pn3->pn_next->pn_next) {
+ if (pn3->pn_atom == pn2->pn_atom) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn2,
+ JSREPORT_ERROR,
+ JSMSG_DUPLICATE_XML_ATTR,
+ js_ValueToPrintableString(cx,
+ ATOM_KEY(pn2->pn_atom)));
+ goto fail;
+ }
+ }
+
+ str = ATOM_TO_STRING(pn2->pn_atom);
+ pn2 = pn2->pn_next;
+ JS_ASSERT(pn2);
+ if (pn2->pn_type != TOK_XMLATTR)
+ goto syntax;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, length);
+ if (length >= 5 &&
+ IS_XMLNS_CHARS(chars) &&
+ (length == 5 || chars[5] == ':')) {
+ JSString *uri, *prefix;
+
+ uri = ATOM_TO_STRING(pn2->pn_atom);
+ if (length == 5) {
+ /* 10.3.2.1. Step 6(h)(i)(1)(a). */
+ prefix = cx->runtime->emptyString;
+ } else {
+ prefix = js_NewStringCopyN(cx, chars + 6, length - 6);
+ if (!prefix)
+ goto fail;
+ }
+
+ /*
+ * Once the new ns is appended to xml->xml_namespaces, it is
+ * protected from GC by the object that owns xml -- which is
+ * either xml->object if outermost, or the object owning xml's
+ * oldest ancestor if !outermost.
+ */
+ ns = NewXMLNamespace(cx, prefix, uri, JS_TRUE);
+ if (!ns)
+ goto fail;
+
+ /*
+ * Don't add a namespace that's already in scope. If someone
+ * extracts a child property from its parent via [[Get]], then
+ * we enforce the invariant, noted many times in ECMA-357, that
+ * the child's namespaces form a possibly-improper superset of
+ * its ancestors' namespaces.
+ */
+ if (!XMLARRAY_HAS_MEMBER(inScopeNSes, ns, namespace_identity)) {
+ if (!XMLARRAY_APPEND(cx, inScopeNSes, ns) ||
+ !XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns)) {
+ goto fail;
+ }
+ }
+
+ JS_ASSERT(n >= 2);
+ n -= 2;
+ *pnp = pn2->pn_next;
+ /* XXXbe recycle pn2 */
+ continue;
+ }
+
+ pnp = &pn2->pn_next;
+ }
+
+ /*
+ * If called from js_ParseNodeToXMLObject, emulate the effect of the
+ * <parent xmlns='%s'>...</parent> wrapping done by "ToXML Applied to
+ * the String Type" (ECMA-357 10.3.1).
+ */
+ if (flags & XSF_PRECOMPILED_ROOT) {
+ JS_ASSERT(length >= 1);
+ ns = XMLARRAY_MEMBER(inScopeNSes, 0, JSObject);
+ JS_ASSERT(!XMLARRAY_HAS_MEMBER(&xml->xml_namespaces, ns,
+ namespace_identity));
+ ns = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns), JS_FALSE);
+ if (!ns)
+ goto fail;
+ if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
+ goto fail;
+ }
+ XMLArrayTrim(&xml->xml_namespaces);
+
+ /* Second pass: process tag name and attributes, using namespaces. */
+ pn2 = pn->pn_head;
+ qn = ParseNodeToQName(cx, pc, pn2, inScopeNSes, JS_FALSE);
+ if (!qn)
+ goto fail;
+ xml->name = qn;
+
+ JS_ASSERT((n & 1) == 0);
+ n >>= 1;
+ if (!XMLArraySetCapacity(cx, &xml->xml_attrs, n))
+ goto fail;
+
+ for (i = 0; (pn2 = pn2->pn_next) != NULL; i++) {
+ qn = ParseNodeToQName(cx, pc, pn2, inScopeNSes, JS_TRUE);
+ if (!qn) {
+ xml->xml_attrs.length = i;
+ goto fail;
+ }
+
+ /*
+ * Enforce "Well-formedness constraint: Unique Att Spec", part 2:
+ * this time checking local name and namespace URI.
+ */
+ for (j = 0; j < i; j++) {
+ attrj = XMLARRAY_MEMBER(&xml->xml_attrs, j, JSXML);
+ attrjqn = attrj->name;
+ if (js_EqualStrings(GetURI(attrjqn), GetURI(qn)) &&
+ js_EqualStrings(GetLocalName(attrjqn), GetLocalName(qn))) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn2,
+ JSREPORT_ERROR,
+ JSMSG_DUPLICATE_XML_ATTR,
+ js_ValueToPrintableString(cx,
+ ATOM_KEY(pn2->pn_atom)));
+ goto fail;
+ }
+ }
+
+ pn2 = pn2->pn_next;
+ JS_ASSERT(pn2);
+ JS_ASSERT(pn2->pn_type == TOK_XMLATTR);
+
+ attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
+ if (!attr)
+ goto fail;
+
+ XMLARRAY_SET_MEMBER(&xml->xml_attrs, i, attr);
+ attr->parent = xml;
+ attr->name = qn;
+ attr->xml_value = ATOM_TO_STRING(pn2->pn_atom);
+ }
+
+ /* Point tag closes its own namespace scope. */
+ if (pn->pn_type == TOK_XMLPTAGC)
+ XMLARRAY_TRUNCATE(cx, inScopeNSes, length);
+ break;
+
+ case TOK_XMLSPACE:
+ case TOK_XMLTEXT:
+ case TOK_XMLCDATA:
+ case TOK_XMLCOMMENT:
+ case TOK_XMLPI:
+ str = ATOM_TO_STRING(pn->pn_atom);
+ qn = NULL;
+ if (pn->pn_type == TOK_XMLCOMMENT) {
+ if (flags & XSF_IGNORE_COMMENTS)
+ goto skip_child;
+ xml_class = JSXML_CLASS_COMMENT;
+ } else if (pn->pn_type == TOK_XMLPI) {
+ if (IS_XML(str)) {
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn,
+ JSREPORT_ERROR,
+ JSMSG_RESERVED_ID,
+ js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(str)));
+ goto fail;
+ }
+
+ if (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS)
+ goto skip_child;
+
+ qn = ParseNodeToQName(cx, pc, pn, inScopeNSes, JS_FALSE);
+ if (!qn)
+ goto fail;
+
+ str = pn->pn_atom2
+ ? ATOM_TO_STRING(pn->pn_atom2)
+ : cx->runtime->emptyString;
+ xml_class = JSXML_CLASS_PROCESSING_INSTRUCTION;
+ } else {
+ /* CDATA section content, or element text. */
+ xml_class = JSXML_CLASS_TEXT;
+ }
+
+ xml = js_NewXML(cx, xml_class);
+ if (!xml)
+ goto fail;
+ xml->name = qn;
+ if (pn->pn_type == TOK_XMLSPACE)
+ xml->xml_flags |= XMLF_WHITESPACE_TEXT;
+ xml->xml_value = str;
+ break;
+
+ default:
+ goto syntax;
+ }
+
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) xml);
+ if ((flags & XSF_PRECOMPILED_ROOT) && !js_GetXMLObject(cx, xml))
+ return NULL;
+ return xml;
+
+skip_child:
+ js_LeaveLocalRootScope(cx);
+ return PN2X_SKIP_CHILD;
+
+#undef PN2X_SKIP_CHILD
+
+syntax:
+ js_ReportCompileErrorNumber(cx, &pc->tokenStream, pn, JSREPORT_ERROR,
+ JSMSG_BAD_XML_MARKUP);
+fail:
+ js_LeaveLocalRootScope(cx);
+ return NULL;
+}
+
+/*
+ * XML helper, object-ops, and library functions. We start with the helpers,
+ * in ECMA-357 order, but merging XML (9.1) and XMLList (9.2) helpers.
+ */
+static JSBool
+GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
+{
+ jsval v;
+
+ if (!js_FindClassObject(cx, NULL, INT_TO_JSID(JSProto_XML), &v))
+ return JS_FALSE;
+ if (!VALUE_IS_FUNCTION(cx, v)) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ return JS_GetProperty(cx, JSVAL_TO_OBJECT(v), name, vp);
+}
+
+static JSBool
+FillSettingsCache(JSContext *cx)
+{
+ int i;
+ const char *name;
+ jsval v;
+
+ /* Note: XML_PRETTY_INDENT is not a boolean setting. */
+ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
+ name = xml_static_props[i].name;
+ if (!GetXMLSetting(cx, name, &v))
+ return JS_FALSE;
+ if (js_ValueToBoolean(v))
+ cx->xmlSettingFlags |= JS_BIT(i);
+ else
+ cx->xmlSettingFlags &= ~JS_BIT(i);
+ }
+
+ cx->xmlSettingFlags |= XSF_CACHE_VALID;
+ return JS_TRUE;
+}
+
+static JSBool
+GetBooleanXMLSetting(JSContext *cx, const char *name, JSBool *bp)
+{
+ int i;
+
+ if (!(cx->xmlSettingFlags & XSF_CACHE_VALID) && !FillSettingsCache(cx))
+ return JS_FALSE;
+
+ for (i = 0; xml_static_props[i].name; i++) {
+ if (!strcmp(xml_static_props[i].name, name)) {
+ *bp = (cx->xmlSettingFlags & JS_BIT(i)) != 0;
+ return JS_TRUE;
+ }
+ }
+ *bp = JS_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+GetUint32XMLSetting(JSContext *cx, const char *name, uint32 *uip)
+{
+ jsval v;
+
+ return GetXMLSetting(cx, name, &v) && JS_ValueToECMAUint32(cx, v, uip);
+}
+
+static JSBool
+GetXMLSettingFlags(JSContext *cx, uintN *flagsp)
+{
+ JSBool flag;
+
+ /* Just get the first flag to validate the setting flags cache. */
+ if (!GetBooleanXMLSetting(cx, js_ignoreComments_str, &flag))
+ return JS_FALSE;
+ *flagsp = cx->xmlSettingFlags;
+ return JS_TRUE;
+}
+
+static JSXML *
+ParseXMLSource(JSContext *cx, JSString *src)
+{
+ jsval nsval;
+ JSString *uri;
+ size_t urilen, srclen, length, offset, dstlen;
+ jschar *chars;
+ const jschar *srcp, *endp;
+ JSXML *xml;
+ JSParseContext pc;
+ const char *filename;
+ uintN lineno;
+ JSStackFrame *fp;
+ JSOp op;
+ JSParseNode *pn;
+ JSXMLArray nsarray;
+ uintN flags;
+
+ static const char prefix[] = "<parent xmlns=\"";
+ static const char middle[] = "\">";
+ static const char suffix[] = "</parent>";
+
+#define constrlen(constr) (sizeof(constr) - 1)
+
+ if (!js_GetDefaultXMLNamespace(cx, &nsval))
+ return NULL;
+ uri = GetURI(JSVAL_TO_OBJECT(nsval));
+ uri = js_EscapeAttributeValue(cx, uri, JS_FALSE);
+
+ urilen = JSSTRING_LENGTH(uri);
+ srclen = JSSTRING_LENGTH(src);
+ length = constrlen(prefix) + urilen + constrlen(middle) + srclen +
+ constrlen(suffix);
+
+ chars = (jschar *) JS_malloc(cx, (length + 1) * sizeof(jschar));
+ if (!chars)
+ return NULL;
+
+ dstlen = length;
+ js_InflateStringToBuffer(cx, prefix, constrlen(prefix), chars, &dstlen);
+ offset = dstlen;
+ js_strncpy(chars + offset, JSSTRING_CHARS(uri), urilen);
+ offset += urilen;
+ dstlen = length - offset + 1;
+ js_InflateStringToBuffer(cx, middle, constrlen(middle), chars + offset,
+ &dstlen);
+ offset += dstlen;
+ srcp = JSSTRING_CHARS(src);
+ js_strncpy(chars + offset, srcp, srclen);
+ offset += srclen;
+ dstlen = length - offset + 1;
+ js_InflateStringToBuffer(cx, suffix, constrlen(suffix), chars + offset,
+ &dstlen);
+ chars [offset + dstlen] = 0;
+
+ xml = NULL;
+ for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
+ JS_ASSERT(!fp->script);
+ filename = NULL;
+ lineno = 1;
+ if (fp) {
+ op = (JSOp) *fp->regs->pc;
+ if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) {
+ filename = fp->script->filename;
+ lineno = js_FramePCToLineNumber(cx, fp);
+ for (endp = srcp + srclen; srcp < endp; srcp++) {
+ if (*srcp == '\n')
+ --lineno;
+ }
+ }
+ }
+
+ if (!js_InitParseContext(cx, &pc, NULL, NULL, chars, length, NULL,
+ filename, lineno))
+ goto out;
+ pn = js_ParseXMLText(cx, cx->fp->scopeChain, &pc, JS_FALSE);
+ if (pn && XMLArrayInit(cx, &nsarray, 1)) {
+ if (GetXMLSettingFlags(cx, &flags))
+ xml = ParseNodeToXML(cx, &pc, pn, &nsarray, flags);
+
+ XMLArrayFinish(cx, &nsarray);
+ }
+ js_FinishParseContext(cx, &pc);
+
+out:
+ JS_free(cx, chars);
+ return xml;
+
+#undef constrlen
+}
+
+/*
+ * Errata in 10.3.1, 10.4.1, and 13.4.4.24 (at least).
+ *
+ * 10.3.1 Step 6(a) fails to NOTE that implementations that do not enforce
+ * the constraint:
+ *
+ * for all x belonging to XML:
+ * x.[[InScopeNamespaces]] >= x.[[Parent]].[[InScopeNamespaces]]
+ *
+ * must union x.[[InScopeNamespaces]] into x[0].[[InScopeNamespaces]] here
+ * (in new sub-step 6(a), renumbering the others to (b) and (c)).
+ *
+ * Same goes for 10.4.1 Step 7(a).
+ *
+ * In order for XML.prototype.namespaceDeclarations() to work correctly, the
+ * default namespace thereby unioned into x[0].[[InScopeNamespaces]] must be
+ * flagged as not declared, so that 13.4.4.24 Step 8(a) can exclude all such
+ * undeclared namespaces associated with x not belonging to ancestorNS.
+ */
+static JSXML *
+OrphanXMLChild(JSContext *cx, JSXML *xml, uint32 i)
+{
+ JSObject *ns;
+
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, 0, JSObject);
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!ns || !xml)
+ return xml;
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
+ return NULL;
+ ns->fslots[JSSLOT_DECLARED] = JSVAL_VOID;
+ }
+ xml->parent = NULL;
+ return xml;
+}
+
+static JSObject *
+ToXML(JSContext *cx, jsval v)
+{
+ JSObject *obj;
+ JSXML *xml;
+ JSClass *clasp;
+ JSString *str;
+ uint32 length;
+
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ goto bad;
+ } else {
+ obj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, obj)) {
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ if (xml->xml_kids.length != 1)
+ goto bad;
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (xml) {
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
+ return js_GetXMLObject(cx, xml);
+ }
+ }
+ return obj;
+ }
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) {
+ JS_ASSERT(0);
+ }
+
+ if (clasp != &js_StringClass &&
+ clasp != &js_NumberClass &&
+ clasp != &js_BooleanClass) {
+ goto bad;
+ }
+ }
+
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return NULL;
+ if (IS_EMPTY(str)) {
+ length = 0;
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ xml = NULL;
+#endif
+ } else {
+ xml = ParseXMLSource(cx, str);
+ if (!xml)
+ return NULL;
+ length = JSXML_LENGTH(xml);
+ }
+
+ if (length == 0) {
+ obj = js_NewXMLObject(cx, JSXML_CLASS_TEXT);
+ if (!obj)
+ return NULL;
+ } else if (length == 1) {
+ xml = OrphanXMLChild(cx, xml, 0);
+ if (!xml)
+ return NULL;
+ obj = js_GetXMLObject(cx, xml);
+ if (!obj)
+ return NULL;
+ } else {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SYNTAX_ERROR);
+ return NULL;
+ }
+ return obj;
+
+bad:
+ js_ReportValueError(cx, JSMSG_BAD_XML_CONVERSION,
+ JSDVG_IGNORE_STACK, v, NULL);
+ return NULL;
+}
+
+static JSBool
+Append(JSContext *cx, JSXML *list, JSXML *kid);
+
+static JSObject *
+ToXMLList(JSContext *cx, jsval v)
+{
+ JSObject *obj, *listobj;
+ JSXML *xml, *list, *kid;
+ JSClass *clasp;
+ JSString *str;
+ uint32 i, length;
+
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ goto bad;
+ } else {
+ obj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, obj)) {
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return NULL;
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (!Append(cx, list, xml))
+ return NULL;
+ return listobj;
+ }
+ return obj;
+ }
+
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp->flags & JSCLASS_DOCUMENT_OBSERVER) {
+ JS_ASSERT(0);
+ }
+
+ if (clasp != &js_StringClass &&
+ clasp != &js_NumberClass &&
+ clasp != &js_BooleanClass) {
+ goto bad;
+ }
+ }
+
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return NULL;
+ if (IS_EMPTY(str)) {
+ xml = NULL;
+ length = 0;
+ } else {
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ xml = ParseXMLSource(cx, str);
+ if (!xml) {
+ js_LeaveLocalRootScope(cx);
+ return NULL;
+ }
+ length = JSXML_LENGTH(xml);
+ }
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (listobj) {
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ for (i = 0; i < length; i++) {
+ kid = OrphanXMLChild(cx, xml, i);
+ if (!kid || !Append(cx, list, kid)) {
+ listobj = NULL;
+ break;
+ }
+ }
+ }
+
+ if (xml)
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) listobj);
+ return listobj;
+
+bad:
+ js_ReportValueError(cx, JSMSG_BAD_XMLLIST_CONVERSION,
+ JSDVG_IGNORE_STACK, v, NULL);
+ return NULL;
+}
+
+/*
+ * ECMA-357 10.2.1 Steps 5-7 pulled out as common subroutines of XMLToXMLString
+ * and their library-public js_* counterparts. The guts of MakeXMLCDataString,
+ * MakeXMLCommentString, and MakeXMLPIString are further factored into a common
+ * MakeXMLSpecialString subroutine.
+ *
+ * These functions take ownership of sb->base, if sb is non-null, in all cases
+ * of success or failure.
+ */
+static JSString *
+MakeXMLSpecialString(JSContext *cx, JSStringBuffer *sb,
+ JSString *str, JSString *str2,
+ const jschar *prefix, size_t prefixlength,
+ const jschar *suffix, size_t suffixlength)
+{
+ JSStringBuffer localSB;
+ size_t length, length2, newlength;
+ jschar *bp, *base;
+
+ if (!sb) {
+ sb = &localSB;
+ js_InitStringBuffer(sb);
+ }
+
+ length = JSSTRING_LENGTH(str);
+ length2 = str2 ? JSSTRING_LENGTH(str2) : 0;
+ newlength = STRING_BUFFER_OFFSET(sb) +
+ prefixlength + length + ((length2 != 0) ? 1 + length2 : 0) +
+ suffixlength;
+ bp = base = (jschar *)
+ JS_realloc(cx, sb->base, (newlength + 1) * sizeof(jschar));
+ if (!bp) {
+ js_FinishStringBuffer(sb);
+ return NULL;
+ }
+
+ bp += STRING_BUFFER_OFFSET(sb);
+ js_strncpy(bp, prefix, prefixlength);
+ bp += prefixlength;
+ js_strncpy(bp, JSSTRING_CHARS(str), length);
+ bp += length;
+ if (length2 != 0) {
+ *bp++ = (jschar) ' ';
+ js_strncpy(bp, JSSTRING_CHARS(str2), length2);
+ bp += length2;
+ }
+ js_strncpy(bp, suffix, suffixlength);
+ bp[suffixlength] = 0;
+
+ str = js_NewString(cx, base, newlength);
+ if (!str)
+ free(base);
+ return str;
+}
+
+static JSString *
+MakeXMLCDATAString(JSContext *cx, JSStringBuffer *sb, JSString *str)
+{
+ static const jschar cdata_prefix_ucNstr[] = {'<', '!', '[',
+ 'C', 'D', 'A', 'T', 'A',
+ '['};
+ static const jschar cdata_suffix_ucNstr[] = {']', ']', '>'};
+
+ return MakeXMLSpecialString(cx, sb, str, NULL,
+ cdata_prefix_ucNstr, 9,
+ cdata_suffix_ucNstr, 3);
+}
+
+static JSString *
+MakeXMLCommentString(JSContext *cx, JSStringBuffer *sb, JSString *str)
+{
+ static const jschar comment_prefix_ucNstr[] = {'<', '!', '-', '-'};
+ static const jschar comment_suffix_ucNstr[] = {'-', '-', '>'};
+
+ return MakeXMLSpecialString(cx, sb, str, NULL,
+ comment_prefix_ucNstr, 4,
+ comment_suffix_ucNstr, 3);
+}
+
+static JSString *
+MakeXMLPIString(JSContext *cx, JSStringBuffer *sb, JSString *name,
+ JSString *value)
+{
+ static const jschar pi_prefix_ucNstr[] = {'<', '?'};
+ static const jschar pi_suffix_ucNstr[] = {'?', '>'};
+
+ return MakeXMLSpecialString(cx, sb, name, value,
+ pi_prefix_ucNstr, 2,
+ pi_suffix_ucNstr, 2);
+}
+
+/*
+ * ECMA-357 10.2.1 17(d-g) pulled out into a common subroutine that appends
+ * equals, a double quote, an attribute value, and a closing double quote.
+ */
+static void
+AppendAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *valstr)
+{
+ js_AppendChar(sb, '=');
+ valstr = js_EscapeAttributeValue(cx, valstr, JS_TRUE);
+ if (!valstr) {
+ if (STRING_BUFFER_OK(sb)) {
+ free(sb->base);
+ sb->base = STRING_BUFFER_ERROR_BASE;
+ }
+ return;
+ }
+ js_AppendJSString(sb, valstr);
+}
+
+/*
+ * ECMA-357 10.2.1.1 EscapeElementValue helper method.
+ *
+ * This function takes ownership of sb->base, if sb is non-null, in all cases
+ * of success or failure.
+ */
+static JSString *
+EscapeElementValue(JSContext *cx, JSStringBuffer *sb, JSString *str)
+{
+ size_t length, newlength;
+ const jschar *cp, *start, *end;
+ jschar c;
+
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ newlength = length;
+ for (cp = start, end = cp + length; cp < end; cp++) {
+ c = *cp;
+ if (c == '<' || c == '>')
+ newlength += 3;
+ else if (c == '&')
+ newlength += 4;
+
+ if (newlength < length) {
+ js_ReportAllocationOverflow(cx);
+ return NULL;
+ }
+ }
+ if ((sb && STRING_BUFFER_OFFSET(sb) != 0) || newlength > length) {
+ JSStringBuffer localSB;
+ if (!sb) {
+ sb = &localSB;
+ js_InitStringBuffer(sb);
+ }
+ if (!sb->grow(sb, newlength)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ for (cp = start; cp < end; cp++) {
+ c = *cp;
+ if (c == '<')
+ js_AppendCString(sb, js_lt_entity_str);
+ else if (c == '>')
+ js_AppendCString(sb, js_gt_entity_str);
+ else if (c == '&')
+ js_AppendCString(sb, js_amp_entity_str);
+ else
+ js_AppendChar(sb, c);
+ }
+ JS_ASSERT(STRING_BUFFER_OK(sb));
+ str = js_NewString(cx, sb->base, STRING_BUFFER_OFFSET(sb));
+ if (!str)
+ js_FinishStringBuffer(sb);
+ }
+ return str;
+}
+
+/*
+ * ECMA-357 10.2.1.2 EscapeAttributeValue helper method.
+ * This function takes ownership of sb->base, if sb is non-null, in all cases.
+ */
+static JSString *
+EscapeAttributeValue(JSContext *cx, JSStringBuffer *sb, JSString *str,
+ JSBool quote)
+{
+ size_t length, newlength;
+ const jschar *cp, *start, *end;
+ jschar c;
+
+ JSSTRING_CHARS_AND_LENGTH(str, start, length);
+ newlength = length + (quote ? 2 : 0);
+ for (cp = start, end = cp + length; cp < end; cp++) {
+ c = *cp;
+ if (c == '"')
+ newlength += 5;
+ else if (c == '<')
+ newlength += 3;
+ else if (c == '&' || c == '\n' || c == '\r' || c == '\t')
+ newlength += 4;
+
+ if (newlength < length) {
+ js_ReportAllocationOverflow(cx);
+ return NULL;
+ }
+ }
+ if ((sb && STRING_BUFFER_OFFSET(sb) != 0) || newlength > length) {
+ JSStringBuffer localSB;
+ if (!sb) {
+ sb = &localSB;
+ js_InitStringBuffer(sb);
+ }
+ if (!sb->grow(sb, newlength)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ if (quote)
+ js_AppendChar(sb, '"');
+ for (cp = start; cp < end; cp++) {
+ c = *cp;
+ if (c == '"')
+ js_AppendCString(sb, js_quot_entity_str);
+ else if (c == '<')
+ js_AppendCString(sb, js_lt_entity_str);
+ else if (c == '&')
+ js_AppendCString(sb, js_amp_entity_str);
+ else if (c == '\n')
+ js_AppendCString(sb, "&#xA;");
+ else if (c == '\r')
+ js_AppendCString(sb, "&#xD;");
+ else if (c == '\t')
+ js_AppendCString(sb, "&#x9;");
+ else
+ js_AppendChar(sb, c);
+ }
+ if (quote)
+ js_AppendChar(sb, '"');
+ JS_ASSERT(STRING_BUFFER_OK(sb));
+ str = js_NewString(cx, sb->base, STRING_BUFFER_OFFSET(sb));
+ if (!str)
+ js_FinishStringBuffer(sb);
+ }
+ return str;
+}
+
+/* 13.3.5.4 [[GetNamespace]]([InScopeNamespaces]) */
+static JSObject *
+GetNamespace(JSContext *cx, JSObject *qn, const JSXMLArray *inScopeNSes)
+{
+ JSString *uri, *prefix, *nsprefix;
+ JSObject *match, *ns;
+ uint32 i, n;
+ jsval argv[2];
+
+ uri = GetURI(qn);
+ prefix = GetPrefix(qn);
+ JS_ASSERT(uri);
+ if (!uri) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_NAMESPACE,
+ prefix
+ ? js_ValueToPrintableString(cx,
+ STRING_TO_JSVAL(prefix))
+ : js_undefined_str);
+ return NULL;
+ }
+
+ /* Look for a matching namespace in inScopeNSes, if provided. */
+ match = NULL;
+ if (inScopeNSes) {
+ for (i = 0, n = inScopeNSes->length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(inScopeNSes, i, JSObject);
+ if (!ns)
+ continue;
+
+ /*
+ * Erratum, very tricky, and not specified in ECMA-357 13.3.5.4:
+ * If we preserve prefixes, we must match null prefix against
+ * an empty prefix of ns, in order to avoid generating redundant
+ * prefixed and default namespaces for cases such as:
+ *
+ * x = <t xmlns="http://foo.com"/>
+ * print(x.toXMLString());
+ *
+ * Per 10.3.2.1, the namespace attribute in t has an empty string
+ * prefix (*not* a null prefix), per 10.3.2.1 Step 6(h)(i)(1):
+ *
+ * 1. If the [local name] property of a is "xmlns"
+ * a. Map ns.prefix to the empty string
+ *
+ * But t's name has a null prefix in this implementation, meaning
+ * *undefined*, per 10.3.2.1 Step 6(c)'s NOTE (which refers to
+ * the http://www.w3.org/TR/xml-infoset/ spec, item 2.2.3, without
+ * saying how "no value" maps to an ECMA-357 value -- but it must
+ * map to the *undefined* prefix value).
+ *
+ * Since "" != undefined (or null, in the current implementation)
+ * the ECMA-357 spec will fail to match in [[GetNamespace]] called
+ * on t with argument {} U {(prefix="", uri="http://foo.com")}.
+ * This spec bug leads to ToXMLString results that duplicate the
+ * declared namespace.
+ */
+ if (js_EqualStrings(GetURI(ns), uri)) {
+ nsprefix = GetPrefix(ns);
+ if (nsprefix == prefix ||
+ ((nsprefix && prefix)
+ ? js_EqualStrings(nsprefix, prefix)
+ : IS_EMPTY(nsprefix ? nsprefix : prefix))) {
+ match = ns;
+ break;
+ }
+ }
+ }
+ }
+
+ /* If we didn't match, make a new namespace from qn. */
+ if (!match) {
+ argv[0] = prefix ? STRING_TO_JSVAL(prefix) : JSVAL_VOID;
+ argv[1] = STRING_TO_JSVAL(uri);
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL,
+ 2, argv);
+ if (!ns)
+ return NULL;
+ match = ns;
+ }
+ return match;
+}
+
+static JSString *
+GeneratePrefix(JSContext *cx, JSString *uri, JSXMLArray *decls)
+{
+ const jschar *cp, *start, *end;
+ size_t length, newlength, offset;
+ uint32 i, n, m, serial;
+ jschar *bp, *dp;
+ JSBool done;
+ JSObject *ns;
+ JSString *nsprefix, *prefix;
+
+ JS_ASSERT(!IS_EMPTY(uri));
+
+ /*
+ * If there are no *declared* namespaces, skip all collision detection and
+ * return a short prefix quickly; an example of such a situation:
+ *
+ * var x = <f/>;
+ * var n = new Namespace("http://example.com/");
+ * x.@n::att = "val";
+ * x.toXMLString();
+ *
+ * This is necessary for various log10 uses below to be valid.
+ */
+ if (decls->length == 0)
+ return JS_NewStringCopyZ(cx, "a");
+
+ /*
+ * Try peeling off the last filename suffix or pathname component till
+ * we have a valid XML name. This heuristic will prefer "xul" given
+ * ".../there.is.only.xul", "xbl" given ".../xbl", and "xbl2" given any
+ * likely URI of the form ".../xbl2/2005".
+ */
+ JSSTRING_CHARS_AND_END(uri, start, end);
+ cp = end;
+ while (--cp > start) {
+ if (*cp == '.' || *cp == '/' || *cp == ':') {
+ ++cp;
+ length = PTRDIFF(end, cp, jschar);
+ if (IsXMLName(cp, length) && !STARTS_WITH_XML(cp, length))
+ break;
+ end = --cp;
+ }
+ }
+ length = PTRDIFF(end, cp, jschar);
+
+ /*
+ * If the namespace consisted only of non-XML names or names that begin
+ * case-insensitively with "xml", arbitrarily create a prefix consisting
+ * of 'a's of size length (allowing dp-calculating code to work with or
+ * without this branch executing) plus the space for storing a hyphen and
+ * the serial number (avoiding reallocation if a collision happens).
+ */
+ bp = (jschar *) cp;
+ newlength = length;
+ if (STARTS_WITH_XML(cp, length) || !IsXMLName(cp, length)) {
+ newlength = length + 2 + (size_t) log10((double) decls->length);
+ bp = (jschar *)
+ JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+ if (!bp)
+ return NULL;
+
+ bp[newlength] = 0;
+ for (i = 0; i < newlength; i++)
+ bp[i] = 'a';
+ }
+
+ /*
+ * Now search through decls looking for a collision. If we collide with
+ * an existing prefix, start tacking on a hyphen and a serial number.
+ */
+ serial = 0;
+ do {
+ done = JS_TRUE;
+ for (i = 0, n = decls->length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(decls, i, JSObject);
+ if (ns && (nsprefix = GetPrefix(ns)) &&
+ JSSTRING_LENGTH(nsprefix) == newlength &&
+ !memcmp(JSSTRING_CHARS(nsprefix), bp,
+ newlength * sizeof(jschar))) {
+ if (bp == cp) {
+ newlength = length + 2 + (size_t) log10((double) n);
+ bp = (jschar *)
+ JS_malloc(cx, (newlength + 1) * sizeof(jschar));
+ if (!bp)
+ return NULL;
+ js_strncpy(bp, cp, length);
+ }
+
+ ++serial;
+ JS_ASSERT(serial <= n);
+ dp = bp + length + 2 + (size_t) log10((double) serial);
+ *dp = 0;
+ for (m = serial; m != 0; m /= 10)
+ *--dp = (jschar)('0' + m % 10);
+ *--dp = '-';
+ JS_ASSERT(dp == bp + length);
+
+ done = JS_FALSE;
+ break;
+ }
+ }
+ } while (!done);
+
+ if (bp == cp) {
+ offset = PTRDIFF(cp, start, jschar);
+ prefix = js_NewDependentString(cx, uri, offset, length);
+ } else {
+ prefix = js_NewString(cx, bp, newlength);
+ if (!prefix)
+ JS_free(cx, bp);
+ }
+ return prefix;
+}
+
+static JSBool
+namespace_match(const void *a, const void *b)
+{
+ const JSObject *nsa = (const JSObject *) a;
+ const JSObject *nsb = (const JSObject *) b;
+ JSString *prefixa, *prefixb = GetPrefix(nsb);
+
+ if (prefixb) {
+ prefixa = GetPrefix(nsa);
+ return prefixa && js_EqualStrings(prefixa, prefixb);
+ }
+ return js_EqualStrings(GetURI(nsa), GetURI(nsb));
+}
+
+/* ECMA-357 10.2.1 and 10.2.2 */
+#define TO_SOURCE_FLAG 0x80000000
+
+static JSString *
+XMLToXMLString(JSContext *cx, JSXML *xml, const JSXMLArray *ancestorNSes,
+ uint32 indentLevel)
+{
+ JSBool pretty, indentKids;
+ JSStringBuffer sb;
+ JSString *str, *prefix, *kidstr, *nsuri;
+ JSXMLArrayCursor cursor;
+ uint32 i, n, nextIndentLevel;
+ JSXMLArray empty, decls, ancdecls;
+ JSObject *ns, *ns2;
+ JSXML *attr, *kid;
+
+ if (!GetBooleanXMLSetting(cx, js_prettyPrinting_str, &pretty))
+ return NULL;
+
+ js_InitStringBuffer(&sb);
+ if (pretty) {
+ js_RepeatChar(&sb, ' ', indentLevel & ~TO_SOURCE_FLAG);
+
+ if (!STRING_BUFFER_OK(&sb)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+ }
+ str = NULL;
+
+ switch (xml->xml_class) {
+ case JSXML_CLASS_TEXT:
+ /* Step 4. */
+ if (pretty) {
+ str = ChompXMLWhitespace(cx, xml->xml_value);
+ if (!str)
+ return NULL;
+ } else {
+ str = xml->xml_value;
+ }
+ return EscapeElementValue(cx, &sb, str);
+
+ case JSXML_CLASS_ATTRIBUTE:
+ /* Step 5. */
+ return EscapeAttributeValue(cx, &sb, xml->xml_value,
+ (indentLevel & TO_SOURCE_FLAG) != 0);
+
+ case JSXML_CLASS_COMMENT:
+ /* Step 6. */
+ return MakeXMLCommentString(cx, &sb, xml->xml_value);
+
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ /* Step 7. */
+ return MakeXMLPIString(cx, &sb, GetLocalName(xml->name),
+ xml->xml_value);
+
+ case JSXML_CLASS_LIST:
+ /* ECMA-357 10.2.2. */
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ i = 0;
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (pretty && i != 0)
+ js_AppendChar(&sb, '\n');
+
+ kidstr = XMLToXMLString(cx, kid, ancestorNSes, indentLevel);
+ if (!kidstr)
+ break;
+
+ js_AppendJSString(&sb, kidstr);
+ ++i;
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ goto list_out;
+
+ if (!sb.base)
+ return cx->runtime->emptyString;
+
+ if (!STRING_BUFFER_OK(&sb)) {
+ JS_ReportOutOfMemory(cx);
+ return NULL;
+ }
+
+ str = js_NewString(cx, sb.base, STRING_BUFFER_OFFSET(&sb));
+ list_out:
+ if (!str && STRING_BUFFER_OK(&sb))
+ js_FinishStringBuffer(&sb);
+ return str;
+
+ default:;
+ }
+
+ /* After this point, control must flow through label out: to exit. */
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+
+ /* ECMA-357 10.2.1 step 8 onward: handle ToXMLString on an XML element. */
+ if (!ancestorNSes) {
+ XMLArrayInit(cx, &empty, 0);
+ ancestorNSes = &empty;
+ }
+ XMLArrayInit(cx, &decls, 0);
+ ancdecls.capacity = 0;
+
+ /* Clone in-scope namespaces not in ancestorNSes into decls. */
+ XMLArrayCursorInit(&cursor, &xml->xml_namespaces);
+ while ((ns = (JSObject *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (!IsDeclared(ns))
+ continue;
+ if (!XMLARRAY_HAS_MEMBER(ancestorNSes, ns, namespace_identity)) {
+ /* NOTE: may want to exclude unused namespaces here. */
+ ns2 = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns), JS_TRUE);
+ if (!ns2 || !XMLARRAY_APPEND(cx, &decls, ns2))
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (ns)
+ goto out;
+
+ /*
+ * Union ancestorNSes and decls into ancdecls. Note that ancdecls does
+ * not own its member references. In the spec, ancdecls has no name, but
+ * is always written out as (AncestorNamespaces U namespaceDeclarations).
+ */
+ if (!XMLArrayInit(cx, &ancdecls, ancestorNSes->length + decls.length))
+ goto out;
+ for (i = 0, n = ancestorNSes->length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(ancestorNSes, i, JSObject);
+ if (!ns2)
+ continue;
+ JS_ASSERT(!XMLARRAY_HAS_MEMBER(&decls, ns2, namespace_identity));
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns2))
+ goto out;
+ }
+ for (i = 0, n = decls.length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(&decls, i, JSObject);
+ if (!ns2)
+ continue;
+ JS_ASSERT(!XMLARRAY_HAS_MEMBER(&ancdecls, ns2, namespace_identity));
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns2))
+ goto out;
+ }
+
+ /* Step 11, except we don't clone ns unless its prefix is undefined. */
+ ns = GetNamespace(cx, xml->name, &ancdecls);
+ if (!ns)
+ goto out;
+
+ /* Step 12 (NULL means *undefined* here), plus the deferred ns cloning. */
+ prefix = GetPrefix(ns);
+ if (!prefix) {
+ /*
+ * Create a namespace prefix that isn't used by any member of decls.
+ * Assign the new prefix to a copy of ns. Flag this namespace as if
+ * it were declared, for assertion-testing's sake later below.
+ *
+ * Erratum: if prefix and xml->name are both null (*undefined* in
+ * ECMA-357), we know that xml was named using the default namespace
+ * (proof: see GetNamespace and the Namespace constructor called with
+ * two arguments). So we ought not generate a new prefix here, when
+ * we can declare ns as the default namespace for xml.
+ *
+ * This helps descendants inherit the namespace instead of redundantly
+ * redeclaring it with generated prefixes in each descendant.
+ */
+ nsuri = GetURI(ns);
+ if (!GetPrefix(xml->name)) {
+ prefix = cx->runtime->emptyString;
+ } else {
+ prefix = GeneratePrefix(cx, nsuri, &ancdecls);
+ if (!prefix)
+ goto out;
+ }
+ ns = NewXMLNamespace(cx, prefix, nsuri, JS_TRUE);
+ if (!ns)
+ goto out;
+
+ /*
+ * If the xml->name was unprefixed, we must remove any declared default
+ * namespace from decls before appending ns. How can you get a default
+ * namespace in decls that doesn't match the one from name? Apparently
+ * by calling x.setNamespace(ns) where ns has no prefix. The other way
+ * to fix this is to update x's in-scope namespaces when setNamespace
+ * is called, but that's not specified by ECMA-357.
+ *
+ * Likely Erratum here, depending on whether the lack of update to x's
+ * in-scope namespace in XML.prototype.setNamespace (13.4.4.36) is an
+ * erratum or not. Note that changing setNamespace to update the list
+ * of in-scope namespaces will change x.namespaceDeclarations().
+ */
+ if (IS_EMPTY(prefix)) {
+ i = XMLArrayFindMember(&decls, ns, namespace_match);
+ if (i != XML_NOT_FOUND)
+ XMLArrayDelete(cx, &decls, i, JS_TRUE);
+ }
+
+ /*
+ * In the spec, ancdecls has no name, but is always written out as
+ * (AncestorNamespaces U namespaceDeclarations). Since we compute
+ * that union in ancdecls, any time we append a namespace strong
+ * ref to decls, we must also append a weak ref to ancdecls. Order
+ * matters here: code at label out: releases strong refs in decls.
+ */
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns) ||
+ !XMLARRAY_APPEND(cx, &decls, ns)) {
+ goto out;
+ }
+ }
+
+ /* Format the element or point-tag into sb. */
+ js_AppendChar(&sb, '<');
+
+ if (prefix && !IS_EMPTY(prefix)) {
+ js_AppendJSString(&sb, prefix);
+ js_AppendChar(&sb, ':');
+ }
+ js_AppendJSString(&sb, GetLocalName(xml->name));
+
+ /*
+ * Step 16 makes a union to avoid writing two loops in step 17, to share
+ * common attribute value appending spec-code. We prefer two loops for
+ * faster code and less data overhead.
+ */
+
+ /* Step 17(b): append attributes. */
+ XMLArrayCursorInit(&cursor, &xml->xml_attrs);
+ while ((attr = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ js_AppendChar(&sb, ' ');
+ ns2 = GetNamespace(cx, attr->name, &ancdecls);
+ if (!ns2)
+ break;
+
+ /* 17(b)(ii): NULL means *undefined* here. */
+ prefix = GetPrefix(ns2);
+ if (!prefix) {
+ prefix = GeneratePrefix(cx, GetURI(ns2), &ancdecls);
+ if (!prefix)
+ break;
+
+ /* Again, we avoid copying ns2 until we know it's prefix-less. */
+ ns2 = NewXMLNamespace(cx, prefix, GetURI(ns2), JS_TRUE);
+ if (!ns2)
+ break;
+
+ /*
+ * In the spec, ancdecls has no name, but is always written out as
+ * (AncestorNamespaces U namespaceDeclarations). Since we compute
+ * that union in ancdecls, any time we append a namespace strong
+ * ref to decls, we must also append a weak ref to ancdecls. Order
+ * matters here: code at label out: releases strong refs in decls.
+ */
+ if (!XMLARRAY_APPEND(cx, &ancdecls, ns2) ||
+ !XMLARRAY_APPEND(cx, &decls, ns2)) {
+ break;
+ }
+ }
+
+ /* 17(b)(iii). */
+ if (!IS_EMPTY(prefix)) {
+ js_AppendJSString(&sb, prefix);
+ js_AppendChar(&sb, ':');
+ }
+
+ /* 17(b)(iv). */
+ js_AppendJSString(&sb, GetLocalName(attr->name));
+
+ /* 17(d-g). */
+ AppendAttributeValue(cx, &sb, attr->xml_value);
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (attr)
+ goto out;
+
+ /* Step 17(c): append XML namespace declarations. */
+ XMLArrayCursorInit(&cursor, &decls);
+ while ((ns2 = (JSObject *) XMLArrayCursorNext(&cursor)) != NULL) {
+ JS_ASSERT(IsDeclared(ns2));
+
+ js_AppendCString(&sb, " xmlns");
+
+ /* 17(c)(ii): NULL means *undefined* here. */
+ prefix = GetPrefix(ns2);
+ if (!prefix) {
+ prefix = GeneratePrefix(cx, GetURI(ns2), &ancdecls);
+ if (!prefix)
+ break;
+ ns2->fslots[JSSLOT_PREFIX] = STRING_TO_JSVAL(prefix);
+ }
+
+ /* 17(c)(iii). */
+ if (!IS_EMPTY(prefix)) {
+ js_AppendChar(&sb, ':');
+ js_AppendJSString(&sb, prefix);
+ }
+
+ /* 17(d-g). */
+ AppendAttributeValue(cx, &sb, GetURI(ns2));
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (ns2)
+ goto out;
+
+ /* Step 18: handle point tags. */
+ n = xml->xml_kids.length;
+ if (n == 0) {
+ js_AppendCString(&sb, "/>");
+ } else {
+ /* Steps 19 through 25: handle element content, and open the end-tag. */
+ js_AppendChar(&sb, '>');
+ indentKids = n > 1 ||
+ (n == 1 &&
+ (kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML)) &&
+ kid->xml_class != JSXML_CLASS_TEXT);
+
+ if (pretty && indentKids) {
+ if (!GetUint32XMLSetting(cx, js_prettyIndent_str, &i))
+ goto out;
+ nextIndentLevel = indentLevel + i;
+ } else {
+ nextIndentLevel = indentLevel & TO_SOURCE_FLAG;
+ }
+
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (pretty && indentKids)
+ js_AppendChar(&sb, '\n');
+
+ kidstr = XMLToXMLString(cx, kid, &ancdecls, nextIndentLevel);
+ if (!kidstr)
+ break;
+
+ js_AppendJSString(&sb, kidstr);
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ goto out;
+
+ if (pretty && indentKids) {
+ js_AppendChar(&sb, '\n');
+ js_RepeatChar(&sb, ' ', indentLevel & ~TO_SOURCE_FLAG);
+ }
+ js_AppendCString(&sb, "</");
+
+ /* Step 26. */
+ prefix = GetPrefix(ns);
+ if (prefix && !IS_EMPTY(prefix)) {
+ js_AppendJSString(&sb, prefix);
+ js_AppendChar(&sb, ':');
+ }
+
+ /* Step 27. */
+ js_AppendJSString(&sb, GetLocalName(xml->name));
+ js_AppendChar(&sb, '>');
+ }
+
+ if (!STRING_BUFFER_OK(&sb)) {
+ JS_ReportOutOfMemory(cx);
+ goto out;
+ }
+
+ str = js_NewString(cx, sb.base, STRING_BUFFER_OFFSET(&sb));
+out:
+ js_LeaveLocalRootScopeWithResult(cx, STRING_TO_JSVAL(str));
+ if (!str && STRING_BUFFER_OK(&sb))
+ js_FinishStringBuffer(&sb);
+ XMLArrayFinish(cx, &decls);
+ if (ancdecls.capacity != 0)
+ XMLArrayFinish(cx, &ancdecls);
+ return str;
+}
+
+/* ECMA-357 10.2 */
+static JSString *
+ToXMLString(JSContext *cx, jsval v, uint32 toSourceFlag)
+{
+ JSObject *obj;
+ JSString *str;
+ JSXML *xml;
+
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_CONVERSION,
+ JSVAL_IS_NULL(v) ? js_null_str : js_undefined_str);
+ return NULL;
+ }
+
+ if (JSVAL_IS_BOOLEAN(v) || JSVAL_IS_NUMBER(v))
+ return js_ValueToString(cx, v);
+
+ if (JSVAL_IS_STRING(v))
+ return EscapeElementValue(cx, NULL, JSVAL_TO_STRING(v));
+
+ obj = JSVAL_TO_OBJECT(v);
+ if (!OBJECT_IS_XML(cx, obj)) {
+ if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_STRING, &v))
+ return NULL;
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return NULL;
+ return EscapeElementValue(cx, NULL, str);
+ }
+
+ /* Handle non-element cases in this switch, returning from each case. */
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ return XMLToXMLString(cx, xml, NULL, toSourceFlag | 0);
+}
+
+static JSObject *
+ToAttributeName(JSContext *cx, jsval v)
+{
+ JSString *name, *uri, *prefix;
+ JSObject *obj;
+ JSClass *clasp;
+ JSObject *qn;
+
+ if (JSVAL_IS_STRING(v)) {
+ name = JSVAL_TO_STRING(v);
+ uri = prefix = cx->runtime->emptyString;
+ } else {
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ js_ReportValueError(cx, JSMSG_BAD_XML_ATTR_NAME,
+ JSDVG_IGNORE_STACK, v, NULL);
+ return NULL;
+ }
+
+ obj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp == &js_AttributeNameClass)
+ return obj;
+
+ if (clasp == &js_QNameClass.base) {
+ qn = obj;
+ uri = GetURI(qn);
+ prefix = GetPrefix(qn);
+ name = GetLocalName(qn);
+ } else {
+ if (clasp == &js_AnyNameClass) {
+ name = ATOM_TO_STRING(cx->runtime->atomState.starAtom);
+ } else {
+ name = js_ValueToString(cx, v);
+ if (!name)
+ return NULL;
+ }
+ uri = prefix = cx->runtime->emptyString;
+ }
+ }
+
+ qn = NewXMLQName(cx, uri, prefix, name, &js_AttributeNameClass);
+ if (!qn)
+ return NULL;
+ return qn;
+}
+
+static void
+ReportBadXMLName(JSContext *cx, jsval id)
+{
+ js_ReportValueError(cx, JSMSG_BAD_XML_NAME, JSDVG_IGNORE_STACK, id, NULL);
+}
+
+static JSBool
+IsFunctionQName(JSContext *cx, JSObject *qn, jsid *funidp)
+{
+ JSAtom *atom;
+ JSString *uri;
+
+ atom = cx->runtime->atomState.lazy.functionNamespaceURIAtom;
+ uri = GetURI(qn);
+ if (uri && atom &&
+ (uri == ATOM_TO_STRING(atom) ||
+ js_EqualStrings(uri, ATOM_TO_STRING(atom)))) {
+ return JS_ValueToId(cx, STRING_TO_JSVAL(GetLocalName(qn)), funidp);
+ }
+ *funidp = 0;
+ return JS_TRUE;
+}
+
+JSBool
+js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp)
+{
+ if (OBJ_GET_CLASS(cx, obj) == &js_QNameClass.base)
+ return IsFunctionQName(cx, obj, funidp);
+ *funidp = 0;
+ return JS_TRUE;
+}
+
+static JSObject *
+ToXMLName(JSContext *cx, jsval v, jsid *funidp)
+{
+ JSString *name;
+ JSObject *obj;
+ JSClass *clasp;
+ uint32 index;
+
+ if (JSVAL_IS_STRING(v)) {
+ name = JSVAL_TO_STRING(v);
+ } else {
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ ReportBadXMLName(cx, v);
+ return NULL;
+ }
+
+ obj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, obj);
+ if (clasp == &js_AttributeNameClass || clasp == &js_QNameClass.base)
+ goto out;
+ if (clasp == &js_AnyNameClass) {
+ name = ATOM_TO_STRING(cx->runtime->atomState.starAtom);
+ goto construct;
+ }
+ name = js_ValueToString(cx, v);
+ if (!name)
+ return NULL;
+ }
+
+ /*
+ * ECMA-357 10.6.1 step 1 seems to be incorrect. The spec says:
+ *
+ * 1. If ToString(ToNumber(P)) == ToString(P), throw a TypeError exception
+ *
+ * First, _P_ should be _s_, to refer to the given string.
+ *
+ * Second, why does ToXMLName applied to the string type throw TypeError
+ * only for numeric literals without any leading or trailing whitespace?
+ *
+ * If the idea is to reject uint32 property names, then the check needs to
+ * be stricter, to exclude hexadecimal and floating point literals.
+ */
+ if (js_IdIsIndex(STRING_TO_JSVAL(name), &index))
+ goto bad;
+
+ if (*JSSTRING_CHARS(name) == '@') {
+ name = js_NewDependentString(cx, name, 1, JSSTRING_LENGTH(name) - 1);
+ if (!name)
+ return NULL;
+ *funidp = 0;
+ return ToAttributeName(cx, STRING_TO_JSVAL(name));
+ }
+
+construct:
+ v = STRING_TO_JSVAL(name);
+ obj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, &v);
+ if (!obj)
+ return NULL;
+
+out:
+ if (!IsFunctionQName(cx, obj, funidp))
+ return NULL;
+ return obj;
+
+bad:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XML_NAME,
+ js_ValueToPrintableString(cx, STRING_TO_JSVAL(name)));
+ return NULL;
+}
+
+/* ECMA-357 9.1.1.13 XML [[AddInScopeNamespace]]. */
+static JSBool
+AddInScopeNamespace(JSContext *cx, JSXML *xml, JSObject *ns)
+{
+ JSString *prefix, *prefix2;
+ JSObject *match, *ns2;
+ uint32 i, n, m;
+
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ return JS_TRUE;
+
+ /* NULL means *undefined* here -- see ECMA-357 9.1.1.13 step 2. */
+ prefix = GetPrefix(ns);
+ if (!prefix) {
+ match = NULL;
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (ns2 && js_EqualStrings(GetURI(ns2), GetURI(ns))) {
+ match = ns2;
+ break;
+ }
+ }
+ if (!match && !XMLARRAY_ADD_MEMBER(cx, &xml->xml_namespaces, n, ns))
+ return JS_FALSE;
+ } else {
+ if (IS_EMPTY(prefix) && IS_EMPTY(GetURI(xml->name)))
+ return JS_TRUE;
+ match = NULL;
+#ifdef __GNUC__ /* suppress bogus gcc warnings */
+ m = XML_NOT_FOUND;
+#endif
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns2 = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (ns2 && (prefix2 = GetPrefix(ns2)) &&
+ js_EqualStrings(prefix2, prefix)) {
+ match = ns2;
+ m = i;
+ break;
+ }
+ }
+ if (match && !js_EqualStrings(GetURI(match), GetURI(ns))) {
+ ns2 = XMLARRAY_DELETE(cx, &xml->xml_namespaces, m, JS_TRUE,
+ JSObject);
+ JS_ASSERT(ns2 == match);
+ match->fslots[JSSLOT_PREFIX] = JSVAL_VOID;
+ if (!AddInScopeNamespace(cx, xml, match))
+ return JS_FALSE;
+ }
+ if (!XMLARRAY_APPEND(cx, &xml->xml_namespaces, ns))
+ return JS_FALSE;
+ }
+
+ /* OPTION: enforce that descendants have superset namespaces. */
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.2.1.6 XMLList [[Append]]. */
+static JSBool
+Append(JSContext *cx, JSXML *list, JSXML *xml)
+{
+ uint32 i, j, k, n;
+ JSXML *kid;
+
+ JS_ASSERT(list->xml_class == JSXML_CLASS_LIST);
+ i = list->xml_kids.length;
+ n = 1;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ list->xml_target = xml->xml_target;
+ list->xml_targetprop = xml->xml_targetprop;
+ n = JSXML_LENGTH(xml);
+ k = i + n;
+ if (!XMLArraySetCapacity(cx, &list->xml_kids, k))
+ return JS_FALSE;
+ for (j = 0; j < n; j++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, j, JSXML);
+ if (kid)
+ XMLARRAY_SET_MEMBER(&list->xml_kids, i + j, kid);
+ }
+ return JS_TRUE;
+ }
+
+ list->xml_target = xml->parent;
+ if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION)
+ list->xml_targetprop = NULL;
+ else
+ list->xml_targetprop = xml->name;
+ if (!XMLARRAY_ADD_MEMBER(cx, &list->xml_kids, i, xml))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.7 XML [[DeepCopy]] and 9.2.1.7 XMLList [[DeepCopy]]. */
+static JSXML *
+DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags);
+
+static JSXML *
+DeepCopy(JSContext *cx, JSXML *xml, JSObject *obj, uintN flags)
+{
+ JSXML *copy;
+ JSBool ok;
+
+ /* Our caller may not be protecting newborns with a local root scope. */
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ copy = DeepCopyInLRS(cx, xml, flags);
+ if (copy) {
+ if (obj) {
+ /* Caller provided the object for this copy, hook 'em up. */
+ ok = JS_SetPrivate(cx, obj, copy);
+ if (ok)
+ copy->object = obj;
+ } else {
+ ok = js_GetXMLObject(cx, copy) != NULL;
+ }
+ if (!ok)
+ copy = NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) copy);
+ return copy;
+}
+
+/*
+ * (i) We must be in a local root scope (InLRS).
+ * (ii) parent must have a rooted object.
+ * (iii) from's owning object must be locked if not thread-local.
+ */
+static JSBool
+DeepCopySetInLRS(JSContext *cx, JSXMLArray *from, JSXMLArray *to, JSXML *parent,
+ uintN flags)
+{
+ uint32 j, n;
+ JSXMLArrayCursor cursor;
+ JSBool ok;
+ JSXML *kid, *kid2;
+ JSString *str;
+
+ JS_ASSERT(cx->localRootStack);
+
+ n = from->length;
+ if (!XMLArraySetCapacity(cx, to, n))
+ return JS_FALSE;
+
+ XMLArrayCursorInit(&cursor, from);
+ j = 0;
+ ok = JS_TRUE;
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if ((flags & XSF_IGNORE_COMMENTS) &&
+ kid->xml_class == JSXML_CLASS_COMMENT) {
+ continue;
+ }
+ if ((flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS) &&
+ kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) {
+ continue;
+ }
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ (kid->xml_flags & XMLF_WHITESPACE_TEXT)) {
+ continue;
+ }
+ kid2 = DeepCopyInLRS(cx, kid, flags);
+ if (!kid2) {
+ to->length = j;
+ ok = JS_FALSE;
+ break;
+ }
+
+ if ((flags & XSF_IGNORE_WHITESPACE) &&
+ n > 1 && kid2->xml_class == JSXML_CLASS_TEXT) {
+ str = ChompXMLWhitespace(cx, kid2->xml_value);
+ if (!str) {
+ to->length = j;
+ ok = JS_FALSE;
+ break;
+ }
+ kid2->xml_value = str;
+ }
+
+ XMLARRAY_SET_MEMBER(to, j, kid2);
+ ++j;
+ if (parent->xml_class != JSXML_CLASS_LIST)
+ kid2->parent = parent;
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (!ok)
+ return JS_FALSE;
+
+ if (j < n)
+ XMLArrayTrim(to);
+ return JS_TRUE;
+}
+
+static JSXML *
+DeepCopyInLRS(JSContext *cx, JSXML *xml, uintN flags)
+{
+ JSXML *copy;
+ JSObject *qn;
+ JSBool ok;
+ uint32 i, n;
+ JSObject *ns, *ns2;
+
+ /* Our caller must be protecting newborn objects. */
+ JS_ASSERT(cx->localRootStack);
+
+ JS_CHECK_RECURSION(cx, return NULL);
+
+ copy = js_NewXML(cx, (JSXMLClass) xml->xml_class);
+ if (!copy)
+ return NULL;
+ qn = xml->name;
+ if (qn) {
+ qn = NewXMLQName(cx, GetURI(qn), GetPrefix(qn), GetLocalName(qn));
+ if (!qn) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ }
+ copy->name = qn;
+ copy->xml_flags = xml->xml_flags;
+
+ if (JSXML_HAS_VALUE(xml)) {
+ copy->xml_value = xml->xml_value;
+ ok = JS_TRUE;
+ } else {
+ ok = DeepCopySetInLRS(cx, &xml->xml_kids, &copy->xml_kids, copy, flags);
+ if (!ok)
+ goto out;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ copy->xml_target = xml->xml_target;
+ copy->xml_targetprop = xml->xml_targetprop;
+ } else {
+ n = xml->xml_namespaces.length;
+ ok = XMLArraySetCapacity(cx, &copy->xml_namespaces, n);
+ if (!ok)
+ goto out;
+ for (i = 0; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (!ns)
+ continue;
+ ns2 = NewXMLNamespace(cx, GetPrefix(ns), GetURI(ns),
+ IsDeclared(ns));
+ if (!ns2) {
+ copy->xml_namespaces.length = i;
+ ok = JS_FALSE;
+ goto out;
+ }
+ XMLARRAY_SET_MEMBER(&copy->xml_namespaces, i, ns2);
+ }
+
+ ok = DeepCopySetInLRS(cx, &xml->xml_attrs, &copy->xml_attrs, copy,
+ 0);
+ if (!ok)
+ goto out;
+ }
+ }
+
+out:
+ if (!ok)
+ return NULL;
+ return copy;
+}
+
+/* ECMA-357 9.1.1.4 XML [[DeleteByIndex]]. */
+static void
+DeleteByIndex(JSContext *cx, JSXML *xml, uint32 index)
+{
+ JSXML *kid;
+
+ if (JSXML_HAS_KIDS(xml) && index < xml->xml_kids.length) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (kid)
+ kid->parent = NULL;
+ XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE);
+ }
+}
+
+typedef JSBool (*JSXMLNameMatcher)(JSObject *nameqn, JSXML *xml);
+
+static JSBool
+MatchAttrName(JSObject *nameqn, JSXML *attr)
+{
+ JSObject *attrqn = attr->name;
+ JSString *localName = GetLocalName(nameqn);
+ JSString *uri;
+
+ return (IS_STAR(localName) ||
+ js_EqualStrings(GetLocalName(attrqn), localName)) &&
+ (!(uri = GetURI(nameqn)) ||
+ js_EqualStrings(GetURI(attrqn), uri));
+}
+
+static JSBool
+MatchElemName(JSObject *nameqn, JSXML *elem)
+{
+ JSString *localName = GetLocalName(nameqn);
+ JSString *uri;
+
+ return (IS_STAR(localName) ||
+ (elem->xml_class == JSXML_CLASS_ELEMENT &&
+ js_EqualStrings(GetLocalName(elem->name), localName))) &&
+ (!(uri = GetURI(nameqn)) ||
+ (elem->xml_class == JSXML_CLASS_ELEMENT &&
+ js_EqualStrings(GetURI(elem->name), uri)));
+}
+
+/* ECMA-357 9.1.1.8 XML [[Descendants]] and 9.2.1.8 XMLList [[Descendants]]. */
+static JSBool
+DescendantsHelper(JSContext *cx, JSXML *xml, JSObject *nameqn, JSXML *list)
+{
+ uint32 i, n;
+ JSXML *attr, *kid;
+
+ JS_CHECK_RECURSION(cx, return JS_FALSE);
+
+ if (xml->xml_class == JSXML_CLASS_ELEMENT &&
+ OBJ_GET_CLASS(cx, nameqn) == &js_AttributeNameClass) {
+ for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (attr && MatchAttrName(nameqn, attr)) {
+ if (!Append(cx, list, attr))
+ return JS_FALSE;
+ }
+ }
+ }
+
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!kid)
+ continue;
+ if (OBJ_GET_CLASS(cx, nameqn) != &js_AttributeNameClass &&
+ MatchElemName(nameqn, kid)) {
+ if (!Append(cx, list, kid))
+ return JS_FALSE;
+ }
+ if (!DescendantsHelper(cx, kid, nameqn, list))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSXML *
+Descendants(JSContext *cx, JSXML *xml, jsval id)
+{
+ jsid funid;
+ JSObject *nameqn;
+ JSObject *listobj;
+ JSXML *list, *kid;
+ uint32 i, n;
+ JSBool ok;
+
+ nameqn = ToXMLName(cx, id, &funid);
+ if (!nameqn)
+ return NULL;
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return NULL;
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (funid)
+ return list;
+
+ /*
+ * Protect nameqn's object and strings from GC by linking list to it
+ * temporarily. The cx->newborn[GCX_OBJECT] GC root protects listobj,
+ * which protects list. Any other object allocations occuring beneath
+ * DescendantsHelper use local roots.
+ */
+ list->name = nameqn;
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ ok = JS_TRUE;
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = DescendantsHelper(cx, kid, nameqn, list);
+ if (!ok)
+ break;
+ }
+ }
+ } else {
+ ok = DescendantsHelper(cx, xml, nameqn, list);
+ }
+ js_LeaveLocalRootScopeWithResult(cx, (jsval) list);
+ if (!ok)
+ return NULL;
+ list->name = NULL;
+ return list;
+}
+
+static JSBool
+xml_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
+
+/* Recursive (JSXML *) parameterized version of Equals. */
+static JSBool
+XMLEquals(JSContext *cx, JSXML *xml, JSXML *vxml, JSBool *bp)
+{
+ JSObject *qn, *vqn;
+ uint32 i, j, n;
+ JSXMLArrayCursor cursor, vcursor;
+ JSXML *kid, *vkid, *attr, *vattr;
+ JSBool ok;
+ JSObject *xobj, *vobj;
+
+retry:
+ if (xml->xml_class != vxml->xml_class) {
+ if (xml->xml_class == JSXML_CLASS_LIST && xml->xml_kids.length == 1) {
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (xml)
+ goto retry;
+ }
+ if (vxml->xml_class == JSXML_CLASS_LIST && vxml->xml_kids.length == 1) {
+ vxml = XMLARRAY_MEMBER(&vxml->xml_kids, 0, JSXML);
+ if (vxml)
+ goto retry;
+ }
+ *bp = JS_FALSE;
+ return JS_TRUE;
+ }
+
+ qn = xml->name;
+ vqn = vxml->name;
+ if (qn) {
+ *bp = vqn &&
+ js_EqualStrings(GetLocalName(qn), GetLocalName(vqn)) &&
+ js_EqualStrings(GetURI(qn), GetURI(vqn));
+ } else {
+ *bp = vqn == NULL;
+ }
+ if (!*bp)
+ return JS_TRUE;
+
+ if (JSXML_HAS_VALUE(xml)) {
+ *bp = js_EqualStrings(xml->xml_value, vxml->xml_value);
+ } else if (xml->xml_kids.length != vxml->xml_kids.length) {
+ *bp = JS_FALSE;
+ } else {
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ XMLArrayCursorInit(&vcursor, &vxml->xml_kids);
+ for (;;) {
+ kid = (JSXML *) XMLArrayCursorNext(&cursor);
+ vkid = (JSXML *) XMLArrayCursorNext(&vcursor);
+ if (!kid || !vkid) {
+ *bp = !kid && !vkid;
+ ok = JS_TRUE;
+ break;
+ }
+ xobj = js_GetXMLObject(cx, kid);
+ vobj = js_GetXMLObject(cx, vkid);
+ ok = xobj && vobj &&
+ xml_equality(cx, xobj, OBJECT_TO_JSVAL(vobj), bp);
+ if (!ok || !*bp)
+ break;
+ }
+ XMLArrayCursorFinish(&vcursor);
+ XMLArrayCursorFinish(&cursor);
+ if (!ok)
+ return JS_FALSE;
+
+ if (*bp && xml->xml_class == JSXML_CLASS_ELEMENT) {
+ n = xml->xml_attrs.length;
+ if (n != vxml->xml_attrs.length)
+ *bp = JS_FALSE;
+ for (i = 0; *bp && i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (!attr)
+ continue;
+ j = XMLARRAY_FIND_MEMBER(&vxml->xml_attrs, attr, attr_identity);
+ if (j == XML_NOT_FOUND) {
+ *bp = JS_FALSE;
+ break;
+ }
+ vattr = XMLARRAY_MEMBER(&vxml->xml_attrs, j, JSXML);
+ if (!vattr)
+ continue;
+ *bp = js_EqualStrings(attr->xml_value, vattr->xml_value);
+ }
+ }
+ }
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.9 XML [[Equals]] and 9.2.1.9 XMLList [[Equals]]. */
+static JSBool
+Equals(JSContext *cx, JSXML *xml, jsval v, JSBool *bp)
+{
+ JSObject *vobj;
+ JSXML *vxml;
+
+ if (JSVAL_IS_PRIMITIVE(v)) {
+ *bp = JS_FALSE;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ if (xml->xml_kids.length == 1) {
+ vxml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (!vxml)
+ return JS_TRUE;
+ vobj = js_GetXMLObject(cx, vxml);
+ if (!vobj)
+ return JS_FALSE;
+ return js_XMLObjectOps.equality(cx, vobj, v, bp);
+ }
+ if (JSVAL_IS_VOID(v) && xml->xml_kids.length == 0)
+ *bp = JS_TRUE;
+ }
+ } else {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (!OBJECT_IS_XML(cx, vobj)) {
+ *bp = JS_FALSE;
+ } else {
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ if (!XMLEquals(cx, xml, vxml, bp))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+CheckCycle(JSContext *cx, JSXML *xml, JSXML *kid)
+{
+ JS_ASSERT(kid->xml_class != JSXML_CLASS_LIST);
+
+ do {
+ if (xml == kid) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CYCLIC_VALUE, js_XML_str);
+ return JS_FALSE;
+ }
+ } while ((xml = xml->parent) != NULL);
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.11 XML [[Insert]]. */
+static JSBool
+Insert(JSContext *cx, JSXML *xml, uint32 i, jsval v)
+{
+ uint32 j, n;
+ JSXML *vxml, *kid;
+ JSObject *vobj;
+ JSString *str;
+
+ if (!JSXML_HAS_KIDS(xml))
+ return JS_TRUE;
+
+ n = 1;
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj)) {
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ if (vxml->xml_class == JSXML_CLASS_LIST) {
+ n = vxml->xml_kids.length;
+ if (n == 0)
+ return JS_TRUE;
+ for (j = 0; j < n; j++) {
+ kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML);
+ if (!kid)
+ continue;
+ if (!CheckCycle(cx, xml, kid))
+ return JS_FALSE;
+ }
+ } else if (vxml->xml_class == JSXML_CLASS_ELEMENT) {
+ /* OPTION: enforce that descendants have superset namespaces. */
+ if (!CheckCycle(cx, xml, vxml))
+ return JS_FALSE;
+ }
+ }
+ }
+ if (!vxml) {
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+
+ vxml = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!vxml)
+ return JS_FALSE;
+ vxml->xml_value = str;
+ }
+
+ if (i > xml->xml_kids.length)
+ i = xml->xml_kids.length;
+
+ if (!XMLArrayInsert(cx, &xml->xml_kids, i, n))
+ return JS_FALSE;
+
+ if (vxml->xml_class == JSXML_CLASS_LIST) {
+ for (j = 0; j < n; j++) {
+ kid = XMLARRAY_MEMBER(&vxml->xml_kids, j, JSXML);
+ if (!kid)
+ continue;
+ kid->parent = xml;
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i + j, kid);
+
+ /* OPTION: enforce that descendants have superset namespaces. */
+ }
+ } else {
+ vxml->parent = xml;
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+IndexToIdVal(JSContext *cx, uint32 index, jsval *idvp)
+{
+ JSString *str;
+
+ if (index <= JSVAL_INT_MAX) {
+ *idvp = INT_TO_JSVAL(index);
+ } else {
+ str = js_NumberToString(cx, (jsdouble) index);
+ if (!str)
+ return JS_FALSE;
+ *idvp = STRING_TO_JSVAL(str);
+ }
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.12 XML [[Replace]]. */
+static JSBool
+Replace(JSContext *cx, JSXML *xml, uint32 i, jsval v)
+{
+ uint32 n;
+ JSXML *vxml, *kid;
+ JSObject *vobj;
+ JSString *str;
+
+ if (!JSXML_HAS_KIDS(xml))
+ return JS_TRUE;
+
+ /*
+ * 9.1.1.12
+ * [[Replace]] handles _i >= x.[[Length]]_ by incrementing _x.[[Length]_.
+ * It should therefore constrain callers to pass in _i <= x.[[Length]]_.
+ */
+ n = xml->xml_kids.length;
+ if (i > n)
+ i = n;
+
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj))
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+
+ switch (vxml ? vxml->xml_class : JSXML_CLASS_LIMIT) {
+ case JSXML_CLASS_ELEMENT:
+ /* OPTION: enforce that descendants have superset namespaces. */
+ if (!CheckCycle(cx, xml, vxml))
+ return JS_FALSE;
+ case JSXML_CLASS_COMMENT:
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ case JSXML_CLASS_TEXT:
+ goto do_replace;
+
+ case JSXML_CLASS_LIST:
+ if (i < n)
+ DeleteByIndex(cx, xml, i);
+ if (!Insert(cx, xml, i, v))
+ return JS_FALSE;
+ break;
+
+ default:
+ str = js_ValueToString(cx, v);
+ if (!str)
+ return JS_FALSE;
+
+ vxml = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!vxml)
+ return JS_FALSE;
+ vxml->xml_value = str;
+
+ do_replace:
+ vxml->parent = xml;
+ if (i < n) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid)
+ kid->parent = NULL;
+ }
+ if (!XMLARRAY_ADD_MEMBER(cx, &xml->xml_kids, i, vxml))
+ return JS_FALSE;
+ break;
+ }
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.3 XML [[Delete]], 9.2.1.3 XML [[Delete]] qname cases. */
+static void
+DeleteNamedProperty(JSContext *cx, JSXML *xml, JSObject *nameqn,
+ JSBool attributes)
+{
+ JSXMLArray *array;
+ uint32 index, deleteCount;
+ JSXML *kid;
+ JSXMLNameMatcher matcher;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ array = &xml->xml_kids;
+ for (index = 0; index < array->length; index++) {
+ kid = XMLARRAY_MEMBER(array, index, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT)
+ DeleteNamedProperty(cx, kid, nameqn, attributes);
+ }
+ } else if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ if (attributes) {
+ array = &xml->xml_attrs;
+ matcher = MatchAttrName;
+ } else {
+ array = &xml->xml_kids;
+ matcher = MatchElemName;
+ }
+ deleteCount = 0;
+ for (index = 0; index < array->length; index++) {
+ kid = XMLARRAY_MEMBER(array, index, JSXML);
+ if (kid && matcher(nameqn, kid)) {
+ kid->parent = NULL;
+ XMLArrayDelete(cx, array, index, JS_FALSE);
+ ++deleteCount;
+ } else if (deleteCount != 0) {
+ XMLARRAY_SET_MEMBER(array,
+ index - deleteCount,
+ array->vector[index]);
+ }
+ }
+ array->length -= deleteCount;
+ }
+}
+
+/* ECMA-357 9.2.1.3 index case. */
+static void
+DeleteListElement(JSContext *cx, JSXML *xml, uint32 index)
+{
+ JSXML *kid, *parent;
+ uint32 kidIndex;
+
+ JS_ASSERT(xml->xml_class == JSXML_CLASS_LIST);
+
+ if (index < xml->xml_kids.length) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (kid) {
+ parent = kid->parent;
+ if (parent) {
+ JS_ASSERT(parent != xml);
+ JS_ASSERT(JSXML_HAS_KIDS(parent));
+
+ if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ DeleteNamedProperty(cx, parent, kid->name, JS_TRUE);
+ } else {
+ kidIndex = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid,
+ NULL);
+ JS_ASSERT(kidIndex != XML_NOT_FOUND);
+ DeleteByIndex(cx, parent, kidIndex);
+ }
+ }
+ XMLArrayDelete(cx, &xml->xml_kids, index, JS_TRUE);
+ }
+ }
+}
+
+static JSBool
+SyncInScopeNamespaces(JSContext *cx, JSXML *xml)
+{
+ JSXMLArray *nsarray;
+ uint32 i, n;
+ JSObject *ns;
+
+ nsarray = &xml->xml_namespaces;
+ while ((xml = xml->parent) != NULL) {
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (ns && !XMLARRAY_HAS_MEMBER(nsarray, ns, namespace_identity)) {
+ if (!XMLARRAY_APPEND(cx, nsarray, ns))
+ return JS_FALSE;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+GetNamedProperty(JSContext *cx, JSXML *xml, JSObject* nameqn, JSXML *list)
+{
+ JSXMLArray *array;
+ JSXMLNameMatcher matcher;
+ JSXMLArrayCursor cursor;
+ JSXML *kid;
+ JSBool attrs;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class == JSXML_CLASS_ELEMENT &&
+ !GetNamedProperty(cx, kid, nameqn, list)) {
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ return JS_FALSE;
+ } else if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ attrs = (OBJ_GET_CLASS(cx, nameqn) == &js_AttributeNameClass);
+ if (attrs) {
+ array = &xml->xml_attrs;
+ matcher = MatchAttrName;
+ } else {
+ array = &xml->xml_kids;
+ matcher = MatchElemName;
+ }
+
+ XMLArrayCursorInit(&cursor, array);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (matcher(nameqn, kid)) {
+ if (!attrs &&
+ kid->xml_class == JSXML_CLASS_ELEMENT &&
+ !SyncInScopeNamespaces(cx, kid)) {
+ break;
+ }
+ if (!Append(cx, list, kid))
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid)
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.1 XML [[Get]] and 9.2.1.1 XMLList [[Get]]. */
+static JSBool
+GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSXML *xml, *list, *kid;
+ uint32 index;
+ JSObject *kidobj, *listobj;
+ JSObject *nameqn;
+ jsid funid;
+ jsval roots[2];
+ JSTempValueRooter tvr;
+
+ xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL);
+ if (!xml)
+ return JS_TRUE;
+
+ if (js_IdIsIndex(id, &index)) {
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ *vp = (index == 0) ? OBJECT_TO_JSVAL(obj) : JSVAL_VOID;
+ } else {
+ /*
+ * ECMA-357 9.2.1.1 starts here.
+ *
+ * Erratum: 9.2 is not completely clear that indexed properties
+ * correspond to kids, but that's what it seems to say, and it's
+ * what any sane user would want.
+ */
+ if (index < xml->xml_kids.length) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (!kid) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+
+ *vp = OBJECT_TO_JSVAL(kidobj);
+ } else {
+ *vp = JSVAL_VOID;
+ }
+ }
+ return JS_TRUE;
+ }
+
+ /*
+ * ECMA-357 9.2.1.1/9.1.1.1 qname case.
+ */
+ nameqn = ToXMLName(cx, id, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ if (funid)
+ return js_GetXMLFunction(cx, obj, funid, vp);
+
+ roots[0] = OBJECT_TO_JSVAL(nameqn);
+ JS_PUSH_TEMP_ROOT(cx, 1, roots, &tvr);
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (listobj) {
+ roots[1] = OBJECT_TO_JSVAL(listobj);
+ tvr.count++;
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (!GetNamedProperty(cx, xml, nameqn, list)) {
+ listobj = NULL;
+ } else {
+ /*
+ * Erratum: ECMA-357 9.1.1.1 misses that [[Append]] sets the
+ * given list's [[TargetProperty]] to the property that is being
+ * appended. This means that any use of the internal [[Get]]
+ * property returns a list which, when used by e.g. [[Insert]]
+ * duplicates the last element matched by id. See bug 336921.
+ */
+ list->xml_target = xml;
+ list->xml_targetprop = nameqn;
+ *vp = OBJECT_TO_JSVAL(listobj);
+ }
+ }
+
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return listobj != NULL;
+}
+
+static JSXML *
+CopyOnWrite(JSContext *cx, JSXML *xml, JSObject *obj)
+{
+ JS_ASSERT(xml->object != obj);
+
+ xml = DeepCopy(cx, xml, obj, 0);
+ if (!xml)
+ return NULL;
+
+ JS_ASSERT(xml->object == obj);
+ return xml;
+}
+
+#define CHECK_COPY_ON_WRITE(cx,xml,obj) \
+ (xml->object == obj ? xml : CopyOnWrite(cx, xml, obj))
+
+static JSString *
+KidToString(JSContext *cx, JSXML *xml, uint32 index)
+{
+ JSXML *kid;
+ JSObject *kidobj;
+
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (!kid)
+ return cx->runtime->emptyString;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return NULL;
+ return js_ValueToString(cx, OBJECT_TO_JSVAL(kidobj));
+}
+
+/* Forward declared -- its implementation uses other statics that call it. */
+static JSBool
+ResolveValue(JSContext *cx, JSXML *list, JSXML **result);
+
+/* ECMA-357 9.1.1.2 XML [[Put]] and 9.2.1.2 XMLList [[Put]]. */
+static JSBool
+PutProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSBool ok, primitiveAssign;
+ enum { OBJ_ROOT, ID_ROOT, VAL_ROOT };
+ jsval roots[3];
+ JSTempValueRooter tvr;
+ JSXML *xml, *vxml, *rxml, *kid, *attr, *parent, *copy, *kid2, *match;
+ JSObject *vobj, *nameobj, *attrobj, *parentobj, *kidobj, *copyobj;
+ JSObject *targetprop, *nameqn, *attrqn;
+ uint32 index, i, j, k, n, q, matchIndex;
+ jsval attrval, nsval;
+ jsid funid;
+ JSString *left, *right, *space, *uri;
+ JSObject *ns;
+
+ xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL);
+ if (!xml)
+ return JS_TRUE;
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ /* Precompute vxml for 9.2.1.2 2(c)(vii)(2-3) and 2(d) and 9.1.1.2 1. */
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(*vp)) {
+ vobj = JSVAL_TO_OBJECT(*vp);
+ if (OBJECT_IS_XML(cx, vobj))
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ return JS_FALSE;
+ MUST_FLOW_THROUGH("out");
+ roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj);
+ roots[ID_ROOT] = id;
+ roots[VAL_ROOT] = *vp;
+ JS_PUSH_TEMP_ROOT(cx, 3, roots, &tvr);
+
+ if (js_IdIsIndex(id, &index)) {
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ /* See NOTE in spec: this variation is reserved for future use. */
+ ReportBadXMLName(cx, id);
+ goto bad;
+ }
+
+ /*
+ * Step 1 of ECMA-357 9.2.1.2 index case sets i to the property index.
+ */
+ i = index;
+
+ /* 2(a-b). */
+ if (xml->xml_target) {
+ ok = ResolveValue(cx, xml->xml_target, &rxml);
+ if (!ok)
+ goto out;
+ if (!rxml)
+ goto out;
+ JS_ASSERT(rxml->object);
+ } else {
+ rxml = NULL;
+ }
+
+ /* 2(c). */
+ if (index >= xml->xml_kids.length) {
+ /* 2(c)(i). */
+ if (rxml) {
+ if (rxml->xml_class == JSXML_CLASS_LIST) {
+ if (rxml->xml_kids.length != 1)
+ goto out;
+ rxml = XMLARRAY_MEMBER(&rxml->xml_kids, 0, JSXML);
+ if (!rxml)
+ goto out;
+ ok = js_GetXMLObject(cx, rxml) != NULL;
+ if (!ok)
+ goto out;
+ }
+
+ /*
+ * Erratum: ECMA-357 9.2.1.2 step 2(c)(ii) sets
+ * _y.[[Parent]] = r_ where _r_ is the result of
+ * [[ResolveValue]] called on _x.[[TargetObject]] in
+ * 2(a)(i). This can result in text parenting text:
+ *
+ * var MYXML = new XML();
+ * MYXML.appendChild(new XML("<TEAM>Giants</TEAM>"));
+ *
+ * (testcase from Werner Sharp <wsharp@macromedia.com>).
+ *
+ * To match insertChildAfter, insertChildBefore,
+ * prependChild, and setChildren, we should silently
+ * do nothing in this case.
+ */
+ if (!JSXML_HAS_KIDS(rxml))
+ goto out;
+ }
+
+ /* 2(c)(ii) is distributed below as several js_NewXML calls. */
+ targetprop = xml->xml_targetprop;
+ if (!targetprop || IS_STAR(GetLocalName(targetprop))) {
+ /* 2(c)(iv)(1-2), out of order w.r.t. 2(c)(iii). */
+ kid = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!kid)
+ goto bad;
+ } else {
+ nameobj = targetprop;
+ if (!nameobj)
+ goto bad;
+ if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) {
+ /*
+ * 2(c)(iii)(1-3).
+ * Note that rxml can't be null here, because target
+ * and targetprop are non-null.
+ */
+ ok = GetProperty(cx, rxml->object, id, &attrval);
+ if (!ok)
+ goto out;
+ if (JSVAL_IS_PRIMITIVE(attrval)) /* no such attribute */
+ goto out;
+ attrobj = JSVAL_TO_OBJECT(attrval);
+ attr = (JSXML *) JS_GetPrivate(cx, attrobj);
+ if (JSXML_LENGTH(attr) != 0)
+ goto out;
+
+ kid = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
+ } else {
+ /* 2(c)(v). */
+ kid = js_NewXML(cx, JSXML_CLASS_ELEMENT);
+ }
+ if (!kid)
+ goto bad;
+
+ /* An important bit of 2(c)(ii). */
+ kid->name = targetprop;
+ }
+
+ /* Final important bit of 2(c)(ii). */
+ kid->parent = rxml;
+
+ /* 2(c)(vi-vii). */
+ i = xml->xml_kids.length;
+ if (kid->xml_class != JSXML_CLASS_ATTRIBUTE) {
+ /*
+ * 2(c)(vii)(1) tests whether _y.[[Parent]]_ is not null.
+ * y.[[Parent]] is here called kid->parent, which we know
+ * from 2(c)(ii) is _r_, here called rxml. So let's just
+ * test that! Erratum, the spec should be simpler here.
+ */
+ if (rxml) {
+ JS_ASSERT(JSXML_HAS_KIDS(rxml));
+ n = rxml->xml_kids.length;
+ j = n - 1;
+ if (n != 0 && i != 0) {
+ for (n = j, j = 0; j < n; j++) {
+ if (rxml->xml_kids.vector[j] ==
+ xml->xml_kids.vector[i-1]) {
+ break;
+ }
+ }
+ }
+
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ goto bad;
+ ok = Insert(cx, rxml, j + 1, OBJECT_TO_JSVAL(kidobj));
+ if (!ok)
+ goto out;
+ }
+
+ /*
+ * 2(c)(vii)(2-3).
+ * Erratum: [[PropertyName]] in 2(c)(vii)(3) must be a
+ * typo for [[TargetProperty]].
+ */
+ if (vxml) {
+ kid->name = (vxml->xml_class == JSXML_CLASS_LIST)
+ ? vxml->xml_targetprop
+ : vxml->name;
+ }
+ }
+
+ /* 2(c)(viii). */
+ ok = Append(cx, xml, kid);
+ if (!ok)
+ goto out;
+ }
+
+ /* 2(d). */
+ if (!vxml ||
+ vxml->xml_class == JSXML_CLASS_TEXT ||
+ vxml->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (!ok)
+ goto out;
+ roots[VAL_ROOT] = *vp;
+ }
+
+ /* 2(e). */
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!kid)
+ goto out;
+ parent = kid->parent;
+ if (kid->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ nameobj = kid->name;
+ if (OBJ_GET_CLASS(cx, nameobj) != &js_AttributeNameClass) {
+ nameobj = NewXMLQName(cx, GetURI(nameobj), GetPrefix(nameobj),
+ GetLocalName(nameobj),
+ &js_AttributeNameClass);
+ if (!nameobj)
+ goto bad;
+ }
+ id = OBJECT_TO_JSVAL(nameobj);
+
+ if (parent) {
+ /* 2(e)(i). */
+ parentobj = js_GetXMLObject(cx, parent);
+ if (!parentobj)
+ goto bad;
+ ok = PutProperty(cx, parentobj, id, vp);
+ if (!ok)
+ goto out;
+
+ /* 2(e)(ii). */
+ ok = GetProperty(cx, parentobj, id, vp);
+ if (!ok)
+ goto out;
+ attr = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(*vp));
+
+ /* 2(e)(iii). */
+ xml->xml_kids.vector[i] = attr->xml_kids.vector[0];
+ }
+ }
+
+ /* 2(f). */
+ else if (vxml && vxml->xml_class == JSXML_CLASS_LIST) {
+ /*
+ * 2(f)(i)
+ *
+ * Erratum: the spec says to create a shallow copy _c_ of _V_, but
+ * if we do that we never change the parent of each child in the
+ * list. Since [[Put]] when called on an XML object deeply copies
+ * the provided list _V_, we also do so here. Perhaps the shallow
+ * copy was a misguided optimization?
+ */
+ copy = DeepCopyInLRS(cx, vxml, 0);
+ if (!copy)
+ goto bad;
+ copyobj = js_GetXMLObject(cx, copy);
+ if (!copyobj)
+ goto bad;
+
+ JS_ASSERT(parent != xml);
+ if (parent) {
+ q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL);
+ JS_ASSERT(q != XML_NOT_FOUND);
+ ok = Replace(cx, parent, q, OBJECT_TO_JSVAL(copyobj));
+ if (!ok)
+ goto out;
+
+#ifdef DEBUG
+ /* Erratum: this loop in the spec is useless. */
+ for (j = 0, n = copy->xml_kids.length; j < n; j++) {
+ kid2 = XMLARRAY_MEMBER(&parent->xml_kids, q + j, JSXML);
+ JS_ASSERT(XMLARRAY_MEMBER(&copy->xml_kids, j, JSXML)
+ == kid2);
+ }
+#endif
+ }
+
+ /*
+ * 2(f)(iv-vi).
+ * Erratum: notice the unhandled zero-length V basis case and
+ * the off-by-one errors for the n != 0 cases in the spec.
+ */
+ n = copy->xml_kids.length;
+ if (n == 0) {
+ XMLArrayDelete(cx, &xml->xml_kids, i, JS_TRUE);
+ } else {
+ ok = XMLArrayInsert(cx, &xml->xml_kids, i + 1, n - 1);
+ if (!ok)
+ goto out;
+
+ for (j = 0; j < n; j++)
+ xml->xml_kids.vector[i + j] = copy->xml_kids.vector[j];
+ }
+ }
+
+ /* 2(g). */
+ else if (vxml || JSXML_HAS_VALUE(kid)) {
+ if (parent) {
+ q = XMLARRAY_FIND_MEMBER(&parent->xml_kids, kid, NULL);
+ JS_ASSERT(q != XML_NOT_FOUND);
+ ok = Replace(cx, parent, q, *vp);
+ if (!ok)
+ goto out;
+
+ vxml = XMLARRAY_MEMBER(&parent->xml_kids, q, JSXML);
+ if (!vxml)
+ goto out;
+ roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vxml->object);
+ }
+
+ /*
+ * 2(g)(iii).
+ * Erratum: _V_ may not be of type XML, but all index-named
+ * properties _x[i]_ in an XMLList _x_ must be of type XML,
+ * according to 9.2.1.1 Overview and other places in the spec.
+ *
+ * Thanks to 2(d), we know _V_ (*vp here) is either a string
+ * or an XML/XMLList object. If *vp is a string, call ToXML
+ * on it to satisfy the constraint.
+ */
+ if (!vxml) {
+ JS_ASSERT(JSVAL_IS_STRING(*vp));
+ vobj = ToXML(cx, *vp);
+ if (!vobj)
+ goto bad;
+ roots[VAL_ROOT] = *vp = OBJECT_TO_JSVAL(vobj);
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+ XMLARRAY_SET_MEMBER(&xml->xml_kids, i, vxml);
+ }
+
+ /* 2(h). */
+ else {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ goto bad;
+ id = ATOM_KEY(cx->runtime->atomState.starAtom);
+ ok = PutProperty(cx, kidobj, id, vp);
+ if (!ok)
+ goto out;
+ }
+ } else {
+ /*
+ * ECMA-357 9.2.1.2/9.1.1.2 qname case.
+ */
+ nameqn = ToXMLName(cx, id, &funid);
+ if (!nameqn)
+ goto bad;
+ if (funid) {
+ ok = js_SetProperty(cx, obj, funid, vp);
+ goto out;
+ }
+ nameobj = nameqn;
+ roots[ID_ROOT] = OBJECT_TO_JSVAL(nameobj);
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /*
+ * Step 3 of 9.2.1.2.
+ * Erratum: if x.[[Length]] > 1 or [[ResolveValue]] returns null
+ * or an r with r.[[Length]] != 1, throw TypeError.
+ */
+ n = JSXML_LENGTH(xml);
+ if (n > 1)
+ goto type_error;
+ if (n == 0) {
+ ok = ResolveValue(cx, xml, &rxml);
+ if (!ok)
+ goto out;
+ if (!rxml || JSXML_LENGTH(rxml) != 1)
+ goto type_error;
+ ok = Append(cx, xml, rxml);
+ if (!ok)
+ goto out;
+ }
+ JS_ASSERT(JSXML_LENGTH(xml) == 1);
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (!xml)
+ goto out;
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
+ obj = js_GetXMLObject(cx, xml);
+ if (!obj)
+ goto bad;
+ roots[OBJ_ROOT] = OBJECT_TO_JSVAL(obj);
+
+ /* FALL THROUGH to non-list case */
+ }
+
+ /*
+ * ECMA-357 9.1.1.2.
+ * Erratum: move steps 3 and 4 to before 1 and 2, to avoid wasted
+ * effort in ToString or [[DeepCopy]].
+ */
+
+ if (JSXML_HAS_VALUE(xml))
+ goto out;
+
+ if (!vxml ||
+ vxml->xml_class == JSXML_CLASS_TEXT ||
+ vxml->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (!ok)
+ goto out;
+ } else {
+ rxml = DeepCopyInLRS(cx, vxml, 0);
+ if (!rxml || !js_GetXMLObject(cx, rxml))
+ goto bad;
+ vxml = rxml;
+ *vp = OBJECT_TO_JSVAL(vxml->object);
+ }
+ roots[VAL_ROOT] = *vp;
+
+ /*
+ * 6.
+ * Erratum: why is this done here, so early? use is way later....
+ */
+ ok = js_GetDefaultXMLNamespace(cx, &nsval);
+ if (!ok)
+ goto out;
+
+ if (OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass) {
+ /* 7(a). */
+ if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)))
+ goto out;
+
+ /* 7(b-c). */
+ if (vxml && vxml->xml_class == JSXML_CLASS_LIST) {
+ n = vxml->xml_kids.length;
+ if (n == 0) {
+ *vp = STRING_TO_JSVAL(cx->runtime->emptyString);
+ } else {
+ left = KidToString(cx, vxml, 0);
+ if (!left)
+ goto bad;
+
+ space = ATOM_TO_STRING(cx->runtime->atomState.spaceAtom);
+ for (i = 1; i < n; i++) {
+ left = js_ConcatStrings(cx, left, space);
+ if (!left)
+ goto bad;
+ right = KidToString(cx, vxml, i);
+ if (!right)
+ goto bad;
+ left = js_ConcatStrings(cx, left, right);
+ if (!left)
+ goto bad;
+ }
+
+ roots[VAL_ROOT] = *vp = STRING_TO_JSVAL(left);
+ }
+ } else {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (!ok)
+ goto out;
+ roots[VAL_ROOT] = *vp;
+ }
+
+ /* 7(d-e). */
+ match = NULL;
+ for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (!attr)
+ continue;
+ attrqn = attr->name;
+ if (js_EqualStrings(GetLocalName(attrqn),
+ GetLocalName(nameqn))) {
+ uri = GetURI(nameqn);
+ if (!uri || js_EqualStrings(GetURI(attrqn), uri)) {
+ if (!match) {
+ match = attr;
+ } else {
+ DeleteNamedProperty(cx, xml, attrqn, JS_TRUE);
+ --i;
+ }
+ }
+ }
+ }
+
+ /* 7(f). */
+ attr = match;
+ if (!attr) {
+ /* 7(f)(i-ii). */
+ uri = GetURI(nameqn);
+ if (!uri) {
+ left = right = cx->runtime->emptyString;
+ } else {
+ left = uri;
+ right = GetPrefix(nameqn);
+ }
+ nameqn = NewXMLQName(cx, left, right, GetLocalName(nameqn));
+ if (!nameqn)
+ goto bad;
+
+ /* 7(f)(iii). */
+ attr = js_NewXML(cx, JSXML_CLASS_ATTRIBUTE);
+ if (!attr)
+ goto bad;
+ attr->parent = xml;
+ attr->name = nameqn;
+
+ /* 7(f)(iv). */
+ ok = XMLARRAY_ADD_MEMBER(cx, &xml->xml_attrs, n, attr);
+ if (!ok)
+ goto out;
+
+ /* 7(f)(v-vi). */
+ ns = GetNamespace(cx, nameqn, NULL);
+ if (!ns)
+ goto bad;
+ ok = AddInScopeNamespace(cx, xml, ns);
+ if (!ok)
+ goto out;
+ }
+
+ /* 7(g). */
+ attr->xml_value = JSVAL_TO_STRING(*vp);
+ goto out;
+ }
+
+ /* 8-9. */
+ if (!js_IsXMLName(cx, OBJECT_TO_JSVAL(nameobj)) &&
+ !IS_STAR(GetLocalName(nameqn))) {
+ goto out;
+ }
+
+ /* 10-11. */
+ id = JSVAL_VOID;
+ primitiveAssign = !vxml && !IS_STAR(GetLocalName(nameqn));
+
+ /* 12. */
+ k = n = xml->xml_kids.length;
+ matchIndex = XML_NOT_FOUND;
+ kid2 = NULL;
+ while (k != 0) {
+ --k;
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, k, JSXML);
+ if (kid && MatchElemName(nameqn, kid)) {
+ if (matchIndex != XML_NOT_FOUND)
+ DeleteByIndex(cx, xml, matchIndex);
+ matchIndex = k;
+ kid2 = kid;
+ }
+ }
+
+ /*
+ * Erratum: ECMA-357 specified child insertion inconsistently:
+ * insertChildBefore and insertChildAfter insert an arbitrary XML
+ * instance, and therefore can create cycles, but appendChild as
+ * specified by the "Overview" of 13.4.4.3 calls [[DeepCopy]] on
+ * its argument. But the "Semantics" in 13.4.4.3 do not include
+ * any [[DeepCopy]] call.
+ *
+ * Fixing this (https://bugzilla.mozilla.org/show_bug.cgi?id=312692)
+ * required adding cycle detection, and allowing duplicate kids to
+ * be created (see comment 6 in the bug). Allowing duplicate kid
+ * references means the loop above will delete all but the lowest
+ * indexed reference, and each [[DeleteByIndex]] nulls the kid's
+ * parent. Thus the need to restore parent here. This is covered
+ * by https://bugzilla.mozilla.org/show_bug.cgi?id=327564.
+ */
+ if (kid2) {
+ JS_ASSERT(kid2->parent == xml || !kid2->parent);
+ if (!kid2->parent)
+ kid2->parent = xml;
+ }
+
+ /* 13. */
+ if (matchIndex == XML_NOT_FOUND) {
+ /* 13(a). */
+ matchIndex = n;
+
+ /* 13(b). */
+ if (primitiveAssign) {
+ uri = GetURI(nameqn);
+ if (!uri) {
+ ns = JSVAL_TO_OBJECT(nsval);
+ left = GetURI(ns);
+ right = GetPrefix(ns);
+ } else {
+ left = uri;
+ right = GetPrefix(nameqn);
+ }
+ nameqn = NewXMLQName(cx, left, right, GetLocalName(nameqn));
+ if (!nameqn)
+ goto bad;
+
+ /* 13(b)(iii). */
+ vobj = js_NewXMLObject(cx, JSXML_CLASS_ELEMENT);
+ if (!vobj)
+ goto bad;
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ vxml->parent = xml;
+ vxml->name = nameqn;
+
+ /* 13(b)(iv-vi). */
+ ns = GetNamespace(cx, nameqn, NULL);
+ if (!ns)
+ goto bad;
+ ok = Replace(cx, xml, matchIndex, OBJECT_TO_JSVAL(vobj));
+ if (!ok)
+ goto out;
+ ok = AddInScopeNamespace(cx, vxml, ns);
+ if (!ok)
+ goto out;
+ }
+ }
+
+ /* 14. */
+ if (primitiveAssign) {
+ JSXMLArrayCursor cursor;
+
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ cursor.index = matchIndex;
+ kid = (JSXML *) XMLArrayCursorItem(&cursor);
+ if (JSXML_HAS_KIDS(kid)) {
+ XMLArrayFinish(cx, &kid->xml_kids);
+ ok = XMLArrayInit(cx, &kid->xml_kids, 1);
+ }
+
+ /* 14(b-c). */
+ /* XXXbe Erratum? redundant w.r.t. 7(b-c) else clause above */
+ if (ok) {
+ ok = JS_ConvertValue(cx, *vp, JSTYPE_STRING, vp);
+ if (ok && !IS_EMPTY(JSVAL_TO_STRING(*vp))) {
+ roots[VAL_ROOT] = *vp;
+ if ((JSXML *) XMLArrayCursorItem(&cursor) == kid)
+ ok = Replace(cx, kid, 0, *vp);
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ } else {
+ /* 15(a). */
+ ok = Replace(cx, xml, matchIndex, *vp);
+ }
+ }
+
+out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ js_LeaveLocalRootScope(cx);
+ return ok;
+
+type_error:
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_BAD_XMLLIST_PUT,
+ js_ValueToPrintableString(cx, id));
+bad:
+ ok = JS_FALSE;
+ goto out;
+}
+
+/* ECMA-357 9.1.1.10 XML [[ResolveValue]], 9.2.1.10 XMLList [[ResolveValue]]. */
+static JSBool
+ResolveValue(JSContext *cx, JSXML *list, JSXML **result)
+{
+ JSXML *target, *base;
+ JSObject *targetprop;
+ jsval id, tv;
+
+ /* Our caller must be protecting newborn objects. */
+ JS_ASSERT(cx->localRootStack);
+
+ if (list->xml_class != JSXML_CLASS_LIST || list->xml_kids.length != 0) {
+ if (!js_GetXMLObject(cx, list))
+ return JS_FALSE;
+ *result = list;
+ return JS_TRUE;
+ }
+
+ target = list->xml_target;
+ targetprop = list->xml_targetprop;
+ if (!target || !targetprop || IS_STAR(GetLocalName(targetprop))) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+
+ if (OBJ_GET_CLASS(cx, targetprop) == &js_AttributeNameClass) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+
+ if (!ResolveValue(cx, target, &base))
+ return JS_FALSE;
+ if (!base) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+ if (!js_GetXMLObject(cx, base))
+ return JS_FALSE;
+
+ id = OBJECT_TO_JSVAL(targetprop);
+ if (!GetProperty(cx, base->object, id, &tv))
+ return JS_FALSE;
+ target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv));
+
+ if (JSXML_LENGTH(target) == 0) {
+ if (base->xml_class == JSXML_CLASS_LIST && JSXML_LENGTH(base) > 1) {
+ *result = NULL;
+ return JS_TRUE;
+ }
+ tv = STRING_TO_JSVAL(cx->runtime->emptyString);
+ if (!PutProperty(cx, base->object, id, &tv))
+ return JS_FALSE;
+ if (!GetProperty(cx, base->object, id, &tv))
+ return JS_FALSE;
+ target = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(tv));
+ }
+
+ *result = target;
+ return JS_TRUE;
+}
+
+static JSBool
+HasNamedProperty(JSXML *xml, JSObject *nameqn)
+{
+ JSBool found;
+ JSXMLArrayCursor cursor;
+ JSXML *kid;
+ JSXMLArray *array;
+ JSXMLNameMatcher matcher;
+ uint32 i, n;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ found = JS_FALSE;
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ found = HasNamedProperty(kid, nameqn);
+ if (found)
+ break;
+ }
+ XMLArrayCursorFinish(&cursor);
+ return found;
+ }
+
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ if (OBJ_GET_CLASS(cx, nameqn) == &js_AttributeNameClass) {
+ array = &xml->xml_attrs;
+ matcher = MatchAttrName;
+ } else {
+ array = &xml->xml_kids;
+ matcher = MatchElemName;
+ }
+ for (i = 0, n = array->length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(array, i, JSXML);
+ if (kid && matcher(nameqn, kid))
+ return JS_TRUE;
+ }
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool
+HasIndexedProperty(JSXML *xml, uint32 i)
+{
+ if (xml->xml_class == JSXML_CLASS_LIST)
+ return i < JSXML_LENGTH(xml);
+
+ if (xml->xml_class == JSXML_CLASS_ELEMENT)
+ return i == 0;
+
+ return JS_FALSE;
+}
+
+static JSBool
+HasSimpleContent(JSXML *xml);
+
+static JSBool
+HasFunctionProperty(JSContext *cx, JSObject *obj, jsid funid, JSBool *found)
+{
+ JSObject *pobj;
+ JSProperty *prop;
+ JSXML *xml;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_XMLClass);
+
+ if (!js_LookupProperty(cx, obj, funid, &pobj, &prop))
+ return JS_FALSE;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ } else {
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (HasSimpleContent(xml)) {
+ /*
+ * Search in String.prototype to set found whenever
+ * js_GetXMLFunction returns existing function.
+ */
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr);
+ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(JSProto_String),
+ &tvr.u.object);
+ JS_ASSERT(tvr.u.object);
+ if (ok) {
+ ok = js_LookupProperty(cx, tvr.u.object, funid, &pobj, &prop);
+ if (ok && prop)
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ }
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ if (!ok)
+ return JS_FALSE;
+ }
+ }
+ *found = (prop != NULL);
+ return JS_TRUE;
+}
+
+/* ECMA-357 9.1.1.6 XML [[HasProperty]] and 9.2.1.5 XMLList [[HasProperty]]. */
+static JSBool
+HasProperty(JSContext *cx, JSObject *obj, jsval id, JSBool *found)
+{
+ JSXML *xml;
+ uint32 i;
+ JSObject *qn;
+ jsid funid;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (js_IdIsIndex(id, &i)) {
+ *found = HasIndexedProperty(xml, i);
+ } else {
+ qn = ToXMLName(cx, id, &funid);
+ if (!qn)
+ return JS_FALSE;
+ if (funid) {
+ if (!HasFunctionProperty(cx, obj, funid, found))
+ return JS_FALSE;
+ } else {
+ *found = HasNamedProperty(xml, qn);
+ }
+ }
+ return JS_TRUE;
+}
+
+static void
+xml_finalize(JSContext *cx, JSObject *obj)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (!xml)
+ return;
+ if (xml->object == obj)
+ xml->object = NULL;
+}
+
+static void
+xml_trace_vector(JSTracer *trc, JSXML **vec, uint32 len)
+{
+ uint32 i;
+ JSXML *xml;
+
+ for (i = 0; i < len; i++) {
+ xml = vec[i];
+ if (xml) {
+ JS_SET_TRACING_INDEX(trc, "xml_vector", i);
+ JS_CallTracer(trc, xml, JSTRACE_XML);
+ }
+ }
+}
+
+/*
+ * js_XMLObjectOps.newObjectMap == js_NewObjectMap, so XML objects appear to
+ * be native. Therefore, xml_lookupProperty must return a valid JSProperty
+ * pointer parameter via *propp to signify "property found". Since the only
+ * call to xml_lookupProperty is via OBJ_LOOKUP_PROPERTY, and then only from
+ * js_FindProperty (in jsobj.c, called from jsinterp.c) or from JSOP_IN case
+ * in the interpreter, the only time we add a JSScopeProperty here is when an
+ * unqualified name is being accessed or when "name in xml" is called.
+ *
+ * This scope property keeps the JSOP_NAME code in js_Interpret happy by
+ * giving it an sprop with (getter, setter) == (GetProperty, PutProperty).
+ *
+ * NB: xml_deleteProperty must take care to remove any property added here.
+ *
+ * FIXME This clashes with the function namespace implementation which also
+ * uses native properties. Effectively after xml_lookupProperty any property
+ * stored previously using assignments to xml.function::name will be removed.
+ * We partially workaround the problem in js_GetXMLFunction. There we take
+ * advantage of the fact that typically function:: is used to access the
+ * functions from XML.prototype. So when js_GetProperty returns a non-function
+ * property, we assume that it represents the result of GetProperty setter
+ * hiding the function and use an extra prototype chain lookup to recover it.
+ * For a proper solution see bug 355257.
+*/
+static JSBool
+xml_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
+ JSProperty **propp)
+{
+ jsval v;
+ JSBool found;
+ JSXML *xml;
+ uint32 i;
+ JSObject *qn;
+ jsid funid;
+ JSScopeProperty *sprop;
+
+ v = ID_TO_VALUE(id);
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (js_IdIsIndex(v, &i)) {
+ found = HasIndexedProperty(xml, i);
+ } else {
+ qn = ToXMLName(cx, v, &funid);
+ if (!qn)
+ return JS_FALSE;
+ if (funid)
+ return js_LookupProperty(cx, obj, funid, objp, propp);
+ found = HasNamedProperty(xml, qn);
+ }
+ if (!found) {
+ *objp = NULL;
+ *propp = NULL;
+ } else {
+ sprop = js_AddNativeProperty(cx, obj, id, GetProperty, PutProperty,
+ SPROP_INVALID_SLOT, JSPROP_ENUMERATE,
+ 0, 0);
+ if (!sprop)
+ return JS_FALSE;
+
+ JS_LOCK_OBJ(cx, obj);
+ *objp = obj;
+ *propp = (JSProperty *) sprop;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
+ JSPropertyOp getter, JSPropertyOp setter, uintN attrs,
+ JSProperty **propp)
+{
+ if (VALUE_IS_FUNCTION(cx, value) || getter || setter ||
+ (attrs & JSPROP_ENUMERATE) == 0 ||
+ (attrs & (JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED))) {
+ return js_DefineProperty(cx, obj, id, value, getter, setter, attrs,
+ propp);
+ }
+
+ if (!PutProperty(cx, obj, ID_TO_VALUE(id), &value))
+ return JS_FALSE;
+ if (propp)
+ *propp = NULL;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_getProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ if (id == JS_DEFAULT_XML_NAMESPACE_ID) {
+ *vp = JSVAL_VOID;
+ return JS_TRUE;
+ }
+
+ return GetProperty(cx, obj, ID_TO_VALUE(id), vp);
+}
+
+static JSBool
+xml_setProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return PutProperty(cx, obj, ID_TO_VALUE(id), vp);
+}
+
+static JSBool
+FoundProperty(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ JSBool *foundp)
+{
+ if (!prop)
+ return HasProperty(cx, obj, ID_TO_VALUE(id), foundp);
+
+ *foundp = JS_TRUE;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_getAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool found;
+
+ if (!FoundProperty(cx, obj, id, prop, &found))
+ return JS_FALSE;
+ *attrsp = found ? JSPROP_ENUMERATE : 0;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setAttributes(JSContext *cx, JSObject *obj, jsid id, JSProperty *prop,
+ uintN *attrsp)
+{
+ JSBool found;
+
+ if (!FoundProperty(cx, obj, id, prop, &found))
+ return JS_FALSE;
+ if (found) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_CANT_SET_XML_ATTRS);
+ }
+ return !found;
+}
+
+static JSBool
+xml_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
+{
+ JSXML *xml;
+ jsval idval;
+ uint32 index;
+ JSObject *nameqn;
+ jsid funid;
+
+ idval = ID_TO_VALUE(id);
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (js_IdIsIndex(idval, &index)) {
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ /* See NOTE in spec: this variation is reserved for future use. */
+ ReportBadXMLName(cx, id);
+ return JS_FALSE;
+ }
+
+ /* ECMA-357 9.2.1.3. */
+ DeleteListElement(cx, xml, index);
+ } else {
+ nameqn = ToXMLName(cx, idval, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ if (funid)
+ return js_DeleteProperty(cx, obj, funid, rval);
+
+ DeleteNamedProperty(cx, xml, nameqn,
+ OBJ_GET_CLASS(cx, nameqn) ==
+ &js_AttributeNameClass);
+ }
+
+ /*
+ * If this object has its own (mutable) scope, then we may have added a
+ * property to the scope in xml_lookupProperty for it to return to mean
+ * "found" and to provide a handle for access operations to call the
+ * property's getter or setter. But now it's time to remove any such
+ * property, to purge the property cache and remove the scope entry.
+ */
+ if (OBJ_SCOPE(obj)->object == obj && !js_DeleteProperty(cx, obj, id, rval))
+ return JS_FALSE;
+
+ *rval = JSVAL_TRUE;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_defaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp)
+{
+ JSXML *xml;
+
+ if (hint == JSTYPE_OBJECT) {
+ /* Called from for..in code in js_Interpret: return an XMLList. */
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ obj = ToXMLList(cx, OBJECT_TO_JSVAL(obj));
+ if (!obj)
+ return JS_FALSE;
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+
+ return JS_CallFunctionName(cx, obj, js_toString_str, 0, NULL, vp);
+}
+
+static JSBool
+xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp)
+{
+ JSXML *xml;
+ uint32 length, index;
+ JSXMLArrayCursor *cursor;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ length = JSXML_LENGTH(xml);
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (length == 0) {
+ cursor = NULL;
+ } else {
+ cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor);
+ if (!cursor)
+ return JS_FALSE;
+ XMLArrayCursorInit(cursor, &xml->xml_kids);
+ }
+ *statep = PRIVATE_TO_JSVAL(cursor);
+ if (idp)
+ *idp = INT_TO_JSID(length);
+ break;
+
+ case JSENUMERATE_NEXT:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor && cursor->array && (index = cursor->index) < length) {
+ *idp = INT_TO_JSID(index);
+ cursor->index = index + 1;
+ break;
+ }
+ /* FALL THROUGH */
+
+ case JSENUMERATE_DESTROY:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor) {
+ XMLArrayCursorFinish(cursor);
+ JS_free(cx, cursor);
+ }
+ *statep = JSVAL_NULL;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ return JS_TRUE;
+}
+
+static void
+xml_trace(JSTracer *trc, JSObject *obj)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) JS_GetPrivate(trc->context, obj);
+ if (xml)
+ JS_CALL_TRACER(trc, xml, JSTRACE_XML, "private");
+}
+
+static void
+xml_clear(JSContext *cx, JSObject *obj)
+{
+}
+
+static JSBool
+HasSimpleContent(JSXML *xml)
+{
+ JSXML *kid;
+ JSBool simple;
+ uint32 i, n;
+
+again:
+ switch (xml->xml_class) {
+ case JSXML_CLASS_COMMENT:
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ return JS_FALSE;
+ case JSXML_CLASS_LIST:
+ if (xml->xml_kids.length == 0)
+ return JS_TRUE;
+ if (xml->xml_kids.length == 1) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (kid) {
+ xml = kid;
+ goto again;
+ }
+ }
+ /* FALL THROUGH */
+ default:
+ simple = JS_TRUE;
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ simple = JS_FALSE;
+ break;
+ }
+ }
+ return simple;
+ }
+}
+
+/*
+ * 11.2.2.1 Step 3(d) onward.
+ */
+static JSObject *
+xml_getMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSTempValueRooter tvr;
+
+ JS_ASSERT(JS_InstanceOf(cx, obj, &js_XMLClass, NULL));
+
+ /*
+ * As our callers have a bad habit of passing a pointer to an unrooted
+ * local value as vp, we use a proper root here.
+ */
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
+ if (!js_GetXMLFunction(cx, obj, id, &tvr.u.value))
+ obj = NULL;
+ *vp = tvr.u.value;
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+static JSBool
+xml_setMethod(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ return js_SetProperty(cx, obj, id, vp);
+}
+
+static JSBool
+xml_enumerateValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
+ jsval *statep, jsid *idp, jsval *vp)
+{
+ JSXML *xml, *kid;
+ uint32 length, index;
+ JSXMLArrayCursor *cursor;
+ JSObject *kidobj;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ length = JSXML_LENGTH(xml);
+ JS_ASSERT(INT_FITS_IN_JSVAL(length));
+
+ switch (enum_op) {
+ case JSENUMERATE_INIT:
+ if (length == 0) {
+ cursor = NULL;
+ } else {
+ cursor = (JSXMLArrayCursor *) JS_malloc(cx, sizeof *cursor);
+ if (!cursor)
+ return JS_FALSE;
+ XMLArrayCursorInit(cursor, &xml->xml_kids);
+ }
+ *statep = PRIVATE_TO_JSVAL(cursor);
+ if (idp)
+ *idp = INT_TO_JSID(length);
+ if (vp)
+ *vp = JSVAL_VOID;
+ break;
+
+ case JSENUMERATE_NEXT:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor && cursor->array && (index = cursor->index) < length) {
+ while (!(kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML))) {
+ if (++index == length)
+ goto destroy;
+ }
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+ JS_ASSERT(INT_FITS_IN_JSVAL(index));
+ *idp = INT_TO_JSID(index);
+ *vp = OBJECT_TO_JSVAL(kidobj);
+ cursor->index = index + 1;
+ break;
+ }
+ /* FALL THROUGH */
+
+ case JSENUMERATE_DESTROY:
+ cursor = (JSXMLArrayCursor *) JSVAL_TO_PRIVATE(*statep);
+ if (cursor) {
+ destroy:
+ XMLArrayCursorFinish(cursor);
+ JS_free(cx, cursor);
+ }
+ *statep = JSVAL_NULL;
+ break;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
+{
+ JSXML *xml, *vxml;
+ JSObject *vobj;
+ JSBool ok;
+ JSString *str, *vstr;
+ jsdouble d, d2;
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ vxml = NULL;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj))
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ }
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ ok = Equals(cx, xml, v, bp);
+ } else if (vxml) {
+ if (vxml->xml_class == JSXML_CLASS_LIST) {
+ ok = Equals(cx, vxml, OBJECT_TO_JSVAL(obj), bp);
+ } else {
+ if (((xml->xml_class == JSXML_CLASS_TEXT ||
+ xml->xml_class == JSXML_CLASS_ATTRIBUTE) &&
+ HasSimpleContent(vxml)) ||
+ ((vxml->xml_class == JSXML_CLASS_TEXT ||
+ vxml->xml_class == JSXML_CLASS_ATTRIBUTE) &&
+ HasSimpleContent(xml))) {
+ ok = js_EnterLocalRootScope(cx);
+ if (ok) {
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ vstr = js_ValueToString(cx, v);
+ ok = str && vstr;
+ if (ok)
+ *bp = js_EqualStrings(str, vstr);
+ js_LeaveLocalRootScope(cx);
+ }
+ } else {
+ ok = XMLEquals(cx, xml, vxml, bp);
+ }
+ }
+ } else {
+ ok = js_EnterLocalRootScope(cx);
+ if (ok) {
+ if (HasSimpleContent(xml)) {
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ vstr = js_ValueToString(cx, v);
+ ok = str && vstr;
+ if (ok)
+ *bp = js_EqualStrings(str, vstr);
+ } else if (JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v)) {
+ str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
+ if (!str) {
+ ok = JS_FALSE;
+ } else if (JSVAL_IS_STRING(v)) {
+ *bp = js_EqualStrings(str, JSVAL_TO_STRING(v));
+ } else {
+ ok = JS_ValueToNumber(cx, STRING_TO_JSVAL(str), &d);
+ if (ok) {
+ d2 = JSVAL_IS_INT(v) ? JSVAL_TO_INT(v)
+ : *JSVAL_TO_DOUBLE(v);
+ *bp = JSDOUBLE_COMPARE(d, ==, d2, JS_FALSE);
+ }
+ }
+ } else {
+ *bp = JS_FALSE;
+ }
+ js_LeaveLocalRootScope(cx);
+ }
+ }
+ return ok;
+}
+
+static JSBool
+xml_concatenate(JSContext *cx, JSObject *obj, jsval v, jsval *vp)
+{
+ JSBool ok;
+ JSObject *listobj, *robj;
+ JSXML *list, *lxml, *rxml;
+
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ return JS_FALSE;
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ lxml = (JSXML *) JS_GetPrivate(cx, obj);
+ ok = Append(cx, list, lxml);
+ if (!ok)
+ goto out;
+
+ if (VALUE_IS_XML(cx, v)) {
+ rxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ } else {
+ robj = ToXML(cx, v);
+ if (!robj) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ rxml = (JSXML *) JS_GetPrivate(cx, robj);
+ }
+ ok = Append(cx, list, rxml);
+ if (!ok)
+ goto out;
+
+ *vp = OBJECT_TO_JSVAL(listobj);
+out:
+ js_LeaveLocalRootScopeWithResult(cx, *vp);
+ return ok;
+}
+
+/* Use js_NewObjectMap so XML objects satisfy OBJ_IS_NATIVE tests. */
+JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps = {
+ { js_NewObjectMap, js_DestroyObjectMap,
+ xml_lookupProperty, xml_defineProperty,
+ xml_getProperty, xml_setProperty,
+ xml_getAttributes, xml_setAttributes,
+ xml_deleteProperty, xml_defaultValue,
+ xml_enumerate, js_CheckAccess,
+ NULL, NULL,
+ NULL, NULL,
+ NULL, xml_hasInstance,
+ js_SetProtoOrParent, js_SetProtoOrParent,
+ js_TraceObject, xml_clear,
+ NULL, NULL },
+ xml_getMethod, xml_setMethod,
+ xml_enumerateValues, xml_equality,
+ xml_concatenate
+};
+
+static JSObjectOps *
+xml_getObjectOps(JSContext *cx, JSClass *clasp)
+{
+ return &js_XMLObjectOps.base;
+}
+
+JS_FRIEND_DATA(JSClass) js_XMLClass = {
+ js_XML_str,
+ JSCLASS_HAS_PRIVATE | JSCLASS_MARK_IS_TRACE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_XML),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, xml_finalize,
+ xml_getObjectOps, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(xml_trace), NULL
+};
+
+static JSXML *
+StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
+{
+ JSXML *xml;
+ JSFunction *fun;
+ char numBuf[12];
+
+ JS_ASSERT(VALUE_IS_FUNCTION(cx, *vp));
+
+ *objp = JS_THIS_OBJECT(cx, vp);
+ xml = (JSXML *) JS_GetInstancePrivate(cx, *objp, &js_XMLClass, vp + 2);
+ if (!xml || xml->xml_class != JSXML_CLASS_LIST)
+ return xml;
+
+ if (xml->xml_kids.length == 1) {
+ xml = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (xml) {
+ *objp = js_GetXMLObject(cx, xml);
+ if (!*objp)
+ return NULL;
+ vp[1] = OBJECT_TO_JSVAL(*objp);
+ return xml;
+ }
+ }
+
+ fun = GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(*vp));
+ JS_snprintf(numBuf, sizeof numBuf, "%u", xml->xml_kids.length);
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_NON_LIST_XML_METHOD,
+ JS_GetFunctionName(fun), numBuf);
+ return NULL;
+}
+
+/* Beware: these two are not bracketed by JS_BEGIN/END_MACRO. */
+#define XML_METHOD_PROLOG \
+ JSObject *obj = JS_THIS_OBJECT(cx, vp); \
+ JSXML *xml = (JSXML *)JS_GetInstancePrivate(cx, obj, &js_XMLClass, vp+2); \
+ if (!xml) \
+ return JS_FALSE
+
+#define NON_LIST_XML_METHOD_PROLOG \
+ JSObject *obj; \
+ JSXML *xml = StartNonListXMLMethod(cx, vp, &obj); \
+ if (!xml) \
+ return JS_FALSE; \
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST)
+
+static JSBool
+xml_addNamespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ goto done;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (!NamespaceHelper(cx, NULL, argc == 0 ? -1 : 1, vp + 2, vp))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+
+ ns = JSVAL_TO_OBJECT(*vp);
+ if (!AddInScopeNamespace(cx, xml, ns))
+ return JS_FALSE;
+ ns->fslots[JSSLOT_DECLARED] = JSVAL_TRUE;
+
+ done:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_appendChild(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name, v;
+ JSObject *vobj;
+ JSXML *vxml;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (!js_GetAnyName(cx, &name))
+ return JS_FALSE;
+
+ if (!GetProperty(cx, obj, name, &v))
+ return JS_FALSE;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ vobj = JSVAL_TO_OBJECT(v);
+ JS_ASSERT(OBJECT_IS_XML(cx, vobj));
+ vxml = (JSXML *) JS_GetPrivate(cx, vobj);
+ JS_ASSERT(vxml->xml_class == JSXML_CLASS_LIST);
+
+ if (!IndexToIdVal(cx, vxml->xml_kids.length, &name))
+ return JS_FALSE;
+ *vp = (argc != 0) ? vp[2] : JSVAL_VOID;
+ if (!PutProperty(cx, JSVAL_TO_OBJECT(v), name, vp))
+ return JS_FALSE;
+
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_attribute(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *qn;
+
+ if (argc == 0) {
+ js_ReportMissingArg(cx, vp, 0);
+ return JS_FALSE;
+ }
+
+ qn = ToAttributeName(cx, vp[2]);
+ if (!qn)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(qn); /* local root */
+
+ return GetProperty(cx, JS_THIS_OBJECT(cx, vp), vp[2], vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_attributes(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *qn;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ name = ATOM_KEY(cx->runtime->atomState.starAtom);
+ qn = ToAttributeName(cx, name);
+ if (!qn)
+ return JS_FALSE;
+ name = OBJECT_TO_JSVAL(qn);
+ JS_PUSH_SINGLE_TEMP_ROOT(cx, name, &tvr);
+ ok = GetProperty(cx, JS_THIS_OBJECT(cx, vp), name, vp);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSXML *
+xml_list_helper(JSContext *cx, JSXML *xml, jsval *rval)
+{
+ JSObject *listobj;
+ JSXML *list;
+
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return NULL;
+
+ *rval = OBJECT_TO_JSVAL(listobj);
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ list->xml_target = xml;
+ return list;
+}
+
+static JSBool
+xml_child_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval name,
+ jsval *rval)
+{
+ uint32 index;
+ JSXML *kid;
+ JSObject *kidobj;
+
+ /* ECMA-357 13.4.4.6 */
+ JS_ASSERT(xml->xml_class != JSXML_CLASS_LIST);
+
+ if (js_IdIsIndex(name, &index)) {
+ if (index >= JSXML_LENGTH(xml)) {
+ *rval = JSVAL_VOID;
+ } else {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, index, JSXML);
+ if (!kid) {
+ *rval = JSVAL_VOID;
+ } else {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(kidobj);
+ }
+ }
+ return JS_TRUE;
+ }
+
+ return GetProperty(cx, obj, name, rval);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_child(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name, v;
+ JSXML *list, *kid, *vxml;
+ JSXMLArrayCursor cursor;
+ JSObject *kidobj;
+
+ XML_METHOD_PROLOG;
+ name = argc != 0 ? vp[2] : JSVAL_VOID;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* ECMA-357 13.5.4.4 */
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ break;
+ if (!xml_child_helper(cx, kidobj, kid, name, &v))
+ break;
+ if (JSVAL_IS_VOID(v)) {
+ /* The property didn't exist in this kid. */
+ continue;
+ }
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if ((!JSXML_HAS_KIDS(vxml) || vxml->xml_kids.length != 0) &&
+ !Append(cx, list, vxml)) {
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ return !kid;
+ }
+
+ /* ECMA-357 Edition 2 13.3.4.6 (note 13.3, not 13.4 as in Edition 1). */
+ if (!xml_child_helper(cx, obj, xml, name, vp))
+ return JS_FALSE;
+ if (JSVAL_IS_VOID(*vp) && !xml_list_helper(cx, xml, vp))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_childIndex(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *parent;
+ uint32 i, n;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ parent = xml->parent;
+ if (!parent || xml->xml_class == JSXML_CLASS_ATTRIBUTE) {
+ *vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
+ return JS_TRUE;
+ }
+ for (i = 0, n = JSXML_LENGTH(parent); i < n; i++) {
+ if (XMLARRAY_MEMBER(&parent->xml_kids, i, JSXML) == xml)
+ break;
+ }
+ JS_ASSERT(i < n);
+ return js_NewNumberInRootedValue(cx, i, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_children(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+
+ name = ATOM_KEY(cx->runtime->atomState.starAtom);
+ return GetProperty(cx, JS_THIS_OBJECT(cx, vp), name, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_comments_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ JSBool ok;
+ uint32 i, n;
+ JSObject *kidobj;
+ jsval v;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ ok = JS_TRUE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.6 Step 2. */
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_comments_helper(cx, kidobj, kid, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ break;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0) {
+ ok = Append(cx, list, vxml);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ } else {
+ /* 13.4.4.9 Step 2. */
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_COMMENT) {
+ ok = Append(cx, list, kid);
+ if (!ok)
+ break;
+ }
+ }
+ }
+
+ return ok;
+}
+
+static JSBool
+xml_comments(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ return xml_comments_helper(cx, obj, xml, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_contains(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval value;
+ JSBool eq;
+ JSXMLArrayCursor cursor;
+ JSXML *kid;
+ JSObject *kidobj;
+
+ XML_METHOD_PROLOG;
+ value = argc != 0 ? vp[2] : JSVAL_VOID;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ eq = JS_FALSE;
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj || !xml_equality(cx, kidobj, value, &eq))
+ break;
+ if (eq)
+ break;
+ }
+ XMLArrayCursorFinish(&cursor);
+ if (kid && !eq)
+ return JS_FALSE;
+ } else {
+ if (!xml_equality(cx, obj, value, &eq))
+ return JS_FALSE;
+ }
+ *vp = BOOLEAN_TO_JSVAL(eq);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_copy(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *copy;
+
+ XML_METHOD_PROLOG;
+ copy = DeepCopy(cx, xml, NULL, 0);
+ if (!copy)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(copy->object);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_descendants(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSXML *list;
+
+ XML_METHOD_PROLOG;
+ name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : vp[2];
+ list = Descendants(cx, xml, name);
+ if (!list)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(list->object);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_elements_helper(JSContext *cx, JSObject *obj, JSXML *xml,
+ JSObject *nameqn, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ jsval v;
+ JSBool ok;
+ JSXMLArrayCursor cursor;
+ JSObject *kidobj;
+ uint32 i, n;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ list->xml_targetprop = nameqn;
+ ok = JS_TRUE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.6 */
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_elements_helper(cx, kidobj, kid, nameqn, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ break;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0) {
+ ok = Append(cx, list, vxml);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ } else {
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT &&
+ MatchElemName(nameqn, kid)) {
+ ok = Append(cx, list, kid);
+ if (!ok)
+ break;
+ }
+ }
+ }
+
+ return ok;
+}
+
+static JSBool
+xml_elements(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ jsid funid;
+
+ XML_METHOD_PROLOG;
+
+ name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : vp[2];
+ nameqn = ToXMLName(cx, name, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(nameqn);
+
+ if (funid)
+ return xml_list_helper(cx, xml, vp) != NULL;
+
+ return xml_elements_helper(cx, obj, xml, nameqn, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+ jsval name;
+ JSBool found;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!JS_InstanceOf(cx, obj, &js_XMLClass, vp + 2))
+ return JS_FALSE;
+
+ name = argc != 0 ? vp[2] : JSVAL_VOID;
+ if (!HasProperty(cx, obj, name, &found))
+ return JS_FALSE;
+ if (found) {
+ *vp = JSVAL_TRUE;
+ return JS_TRUE;
+ }
+ return js_HasOwnPropertyHelper(cx, js_LookupProperty, argc, vp);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_hasComplexContent(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *kid;
+ JSObject *kidobj;
+ uint32 i, n;
+
+ XML_METHOD_PROLOG;
+again:
+ switch (xml->xml_class) {
+ case JSXML_CLASS_ATTRIBUTE:
+ case JSXML_CLASS_COMMENT:
+ case JSXML_CLASS_PROCESSING_INSTRUCTION:
+ case JSXML_CLASS_TEXT:
+ *vp = JSVAL_FALSE;
+ break;
+ case JSXML_CLASS_LIST:
+ if (xml->xml_kids.length == 0) {
+ *vp = JSVAL_TRUE;
+ } else if (xml->xml_kids.length == 1) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (kid) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj)
+ return JS_FALSE;
+ obj = kidobj;
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ goto again;
+ }
+ }
+ /* FALL THROUGH */
+ default:
+ *vp = JSVAL_FALSE;
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ *vp = JSVAL_TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_hasSimpleContent(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ *vp = BOOLEAN_TO_JSVAL(HasSimpleContent(xml));
+ return JS_TRUE;
+}
+
+typedef struct JSTempRootedNSArray {
+ JSTempValueRooter tvr;
+ JSXMLArray array;
+ jsval value; /* extra root for temporaries */
+} JSTempRootedNSArray;
+
+static void
+TraceObjectVector(JSTracer *trc, JSObject **vec, uint32 len)
+{
+ uint32 i;
+ JSObject *obj;
+
+ for (i = 0; i < len; i++) {
+ obj = vec[i];
+ if (obj) {
+ JS_SET_TRACING_INDEX(trc, "vector", i);
+ JS_CallTracer(trc, obj, JSTRACE_OBJECT);
+ }
+ }
+}
+
+static void
+trace_temp_ns_array(JSTracer *trc, JSTempValueRooter *tvr)
+{
+ JSTempRootedNSArray *tmp = (JSTempRootedNSArray *)tvr;
+
+ TraceObjectVector(trc,
+ (JSObject **) tmp->array.vector,
+ tmp->array.length);
+ XMLArrayCursorTrace(trc, tmp->array.cursors);
+ JS_CALL_VALUE_TRACER(trc, tmp->value, "temp_ns_array_value");
+}
+
+static void
+InitTempNSArray(JSContext *cx, JSTempRootedNSArray *tmp)
+{
+ XMLArrayInit(cx, &tmp->array, 0);
+ tmp->value = JSVAL_NULL;
+ JS_PUSH_TEMP_ROOT_TRACE(cx, trace_temp_ns_array, &tmp->tvr);
+}
+
+static void
+FinishTempNSArray(JSContext *cx, JSTempRootedNSArray *tmp)
+{
+ JS_ASSERT(tmp->tvr.u.trace == trace_temp_ns_array);
+ JS_POP_TEMP_ROOT(cx, &tmp->tvr);
+ XMLArrayFinish(cx, &tmp->array);
+}
+
+/*
+ * Populate a new JS array with elements of JSTempRootedNSArray.array and
+ * place the result into rval. rval must point to a rooted location.
+ */
+static JSBool
+TempNSArrayToJSArray(JSContext *cx, JSTempRootedNSArray *tmp, jsval *rval)
+{
+ JSObject *arrayobj;
+ uint32 i, n;
+ JSObject *ns;
+
+ arrayobj = js_NewArrayObject(cx, 0, NULL);
+ if (!arrayobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(arrayobj);
+ for (i = 0, n = tmp->array.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&tmp->array, i, JSObject);
+ if (!ns)
+ continue;
+ tmp->value = OBJECT_TO_JSVAL(ns);
+ if (!OBJ_SET_PROPERTY(cx, arrayobj, INT_TO_JSID(i), &tmp->value))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+FindInScopeNamespaces(JSContext *cx, JSXML *xml, JSXMLArray *nsarray)
+{
+ uint32 length, i, j, n;
+ JSObject *ns, *ns2;
+ JSString *prefix, *prefix2;
+
+ length = nsarray->length;
+ do {
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ continue;
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (!ns)
+ continue;
+
+ prefix = GetPrefix(ns);
+ for (j = 0; j < length; j++) {
+ ns2 = XMLARRAY_MEMBER(nsarray, j, JSObject);
+ if (ns2) {
+ prefix2 = GetPrefix(ns2);
+ if ((prefix2 && prefix)
+ ? js_EqualStrings(prefix2, prefix)
+ : js_EqualStrings(GetURI(ns2), GetURI(ns))) {
+ break;
+ }
+ }
+ }
+
+ if (j == length) {
+ if (!XMLARRAY_APPEND(cx, nsarray, ns))
+ return JS_FALSE;
+ ++length;
+ }
+ }
+ } while ((xml = xml->parent) != NULL);
+ JS_ASSERT(length == nsarray->length);
+
+ return JS_TRUE;
+}
+
+static JSBool
+xml_inScopeNamespaces(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSTempRootedNSArray namespaces;
+ JSBool ok;
+
+ NON_LIST_XML_METHOD_PROLOG;
+
+ InitTempNSArray(cx, &namespaces);
+ ok = FindInScopeNamespaces(cx, xml, &namespaces.array) &&
+ TempNSArrayToJSArray(cx, &namespaces, vp);
+ FinishTempNSArray(cx, &namespaces);
+ return ok;
+}
+
+static JSBool
+xml_insertChildAfter(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval arg;
+ JSXML *kid;
+ uint32 i;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(obj);
+ if (!JSXML_HAS_KIDS(xml) || argc == 0)
+ return JS_TRUE;
+
+ arg = vp[2];
+ if (JSVAL_IS_NULL(arg)) {
+ kid = NULL;
+ i = 0;
+ } else {
+ if (!VALUE_IS_XML(cx, arg))
+ return JS_TRUE;
+ kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg));
+ i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL);
+ if (i == XML_NOT_FOUND)
+ return JS_TRUE;
+ ++i;
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ return Insert(cx, xml, i, argc >= 2 ? vp[3] : JSVAL_VOID);
+}
+
+static JSBool
+xml_insertChildBefore(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval arg;
+ JSXML *kid;
+ uint32 i;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(obj);
+ if (!JSXML_HAS_KIDS(xml) || argc == 0)
+ return JS_TRUE;
+
+ arg = vp[2];
+ if (JSVAL_IS_NULL(arg)) {
+ kid = NULL;
+ i = xml->xml_kids.length;
+ } else {
+ if (!VALUE_IS_XML(cx, arg))
+ return JS_TRUE;
+ kid = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(arg));
+ i = XMLARRAY_FIND_MEMBER(&xml->xml_kids, kid, NULL);
+ if (i == XML_NOT_FOUND)
+ return JS_TRUE;
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ return Insert(cx, xml, i, argc >= 2 ? vp[3] : JSVAL_VOID);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_length(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_LIST) {
+ *vp = JSVAL_ONE;
+ } else {
+ if (!js_NewNumberInRootedValue(cx, xml->xml_kids.length, vp))
+ return JS_FALSE;
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_localName(JSContext *cx, uintN argc, jsval *vp)
+{
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = xml->name ? xml->name->fslots[JSSLOT_LOCAL_NAME] : JSVAL_NULL;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_name(JSContext *cx, uintN argc, jsval *vp)
+{
+ NON_LIST_XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(xml->name);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_namespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *prefix, *nsprefix;
+ JSTempRootedNSArray inScopeNSes;
+ JSBool ok;
+ jsuint i, length;
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (argc == 0 && !JSXML_HAS_NAME(xml)) {
+ *vp = JSVAL_NULL;
+ return JS_TRUE;
+ }
+
+ if (argc == 0) {
+ prefix = NULL;
+ } else {
+ prefix = js_ValueToString(cx, vp[2]);
+ if (!prefix)
+ return JS_FALSE;
+ vp[2] = STRING_TO_JSVAL(prefix); /* local root */
+ }
+
+ InitTempNSArray(cx, &inScopeNSes);
+ MUST_FLOW_THROUGH("out");
+ ok = FindInScopeNamespaces(cx, xml, &inScopeNSes.array);
+ if (!ok)
+ goto out;
+
+ if (!prefix) {
+ ns = GetNamespace(cx, xml->name, &inScopeNSes.array);
+ if (!ns) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ } else {
+ ns = NULL;
+ for (i = 0, length = inScopeNSes.array.length; i < length; i++) {
+ ns = XMLARRAY_MEMBER(&inScopeNSes.array, i, JSObject);
+ if (ns) {
+ nsprefix = GetPrefix(ns);
+ if (nsprefix && js_EqualStrings(nsprefix, prefix))
+ break;
+ ns = NULL;
+ }
+ }
+ }
+
+ *vp = (!ns) ? JSVAL_VOID : OBJECT_TO_JSVAL(ns);
+
+ out:
+ FinishTempNSArray(cx, &inScopeNSes);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_namespaceDeclarations(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSBool ok;
+ JSTempRootedNSArray ancestors, declared;
+ JSXML *yml;
+ uint32 i, n;
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (JSXML_HAS_VALUE(xml))
+ return JS_TRUE;
+
+ /* From here, control flow must goto out to finish these arrays. */
+ ok = JS_TRUE;
+ InitTempNSArray(cx, &ancestors);
+ InitTempNSArray(cx, &declared);
+ yml = xml;
+
+ while ((yml = yml->parent) != NULL) {
+ JS_ASSERT(yml->xml_class == JSXML_CLASS_ELEMENT);
+ for (i = 0, n = yml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&yml->xml_namespaces, i, JSObject);
+ if (ns &&
+ !XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) {
+ ok = XMLARRAY_APPEND(cx, &ancestors.array, ns);
+ if (!ok)
+ goto out;
+ }
+ }
+ }
+
+ for (i = 0, n = xml->xml_namespaces.length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(&xml->xml_namespaces, i, JSObject);
+ if (!ns)
+ continue;
+ if (!IsDeclared(ns))
+ continue;
+ if (!XMLARRAY_HAS_MEMBER(&ancestors.array, ns, namespace_match)) {
+ ok = XMLARRAY_APPEND(cx, &declared.array, ns);
+ if (!ok)
+ goto out;
+ }
+ }
+
+ ok = TempNSArrayToJSArray(cx, &declared, vp);
+
+out:
+ /* Finishing must be in reverse order of initialization to follow LIFO. */
+ FinishTempNSArray(cx, &declared);
+ FinishTempNSArray(cx, &ancestors);
+ return ok;
+}
+
+static const char js_attribute_str[] = "attribute";
+static const char js_text_str[] = "text";
+
+/* Exported to jsgc.c #ifdef DEBUG. */
+const char *js_xml_class_str[] = {
+ "list",
+ "element",
+ js_attribute_str,
+ "processing-instruction",
+ js_text_str,
+ "comment"
+};
+
+static JSBool
+xml_nodeKind(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ str = JS_InternString(cx, js_xml_class_str[xml->xml_class]);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static void
+NormalizingDelete(JSContext *cx, JSXML *xml, uint32 index)
+{
+ if (xml->xml_class == JSXML_CLASS_LIST)
+ DeleteListElement(cx, xml, index);
+ else
+ DeleteByIndex(cx, xml, index);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_normalize_helper(JSContext *cx, JSObject *obj, JSXML *xml)
+{
+ JSXML *kid, *kid2;
+ uint32 i, n;
+ JSObject *kidobj;
+ JSString *str;
+
+ if (!JSXML_HAS_KIDS(xml))
+ return JS_TRUE;
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (!kid)
+ continue;
+ if (kid->xml_class == JSXML_CLASS_ELEMENT) {
+ kidobj = js_GetXMLObject(cx, kid);
+ if (!kidobj || !xml_normalize_helper(cx, kidobj, kid))
+ return JS_FALSE;
+ } else if (kid->xml_class == JSXML_CLASS_TEXT) {
+ while (i + 1 < n &&
+ (kid2 = XMLARRAY_MEMBER(&xml->xml_kids, i + 1, JSXML)) &&
+ kid2->xml_class == JSXML_CLASS_TEXT) {
+ str = js_ConcatStrings(cx, kid->xml_value, kid2->xml_value);
+ if (!str)
+ return JS_FALSE;
+ NormalizingDelete(cx, xml, i + 1);
+ n = xml->xml_kids.length;
+ kid->xml_value = str;
+ }
+ if (IS_EMPTY(kid->xml_value)) {
+ NormalizingDelete(cx, xml, i);
+ n = xml->xml_kids.length;
+ --i;
+ }
+ }
+ }
+
+ return JS_TRUE;
+}
+
+static JSBool
+xml_normalize(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ *vp = OBJECT_TO_JSVAL(obj);
+ return xml_normalize_helper(cx, obj, xml);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_parent(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSXML *parent, *kid;
+ uint32 i, n;
+ JSObject *parentobj;
+
+ XML_METHOD_PROLOG;
+ parent = xml->parent;
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ *vp = JSVAL_VOID;
+ n = xml->xml_kids.length;
+ if (n == 0)
+ return JS_TRUE;
+
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, 0, JSXML);
+ if (!kid)
+ return JS_TRUE;
+ parent = kid->parent;
+ for (i = 1; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->parent != parent)
+ return JS_TRUE;
+ }
+ }
+
+ if (!parent) {
+ *vp = JSVAL_NULL;
+ return JS_TRUE;
+ }
+
+ parentobj = js_GetXMLObject(cx, parent);
+ if (!parentobj)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(parentobj);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_processingInstructions_helper(JSContext *cx, JSObject *obj, JSXML *xml,
+ JSObject *nameqn, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ JSBool ok;
+ JSXMLArrayCursor cursor;
+ JSObject *kidobj;
+ jsval v;
+ uint32 i, n;
+ JSString *localName;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ list->xml_targetprop = nameqn;
+ ok = JS_TRUE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.17 Step 4 (misnumbered 9 -- Erratum?). */
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_processingInstructions_helper(cx, kidobj, kid,
+ nameqn, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ break;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0) {
+ ok = Append(cx, list, vxml);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ } else {
+ /* 13.4.4.28 Step 4. */
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION) {
+ localName = GetLocalName(nameqn);
+ if (IS_STAR(localName) ||
+ js_EqualStrings(localName, GetLocalName(kid->name))) {
+ ok = Append(cx, list, kid);
+ if (!ok)
+ break;
+ }
+ }
+ }
+ }
+
+ return ok;
+}
+
+static JSBool
+xml_processingInstructions(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ jsid funid;
+
+ XML_METHOD_PROLOG;
+
+ name = (argc == 0) ? ATOM_KEY(cx->runtime->atomState.starAtom) : vp[2];
+ nameqn = ToXMLName(cx, name, &funid);
+ if (!nameqn)
+ return JS_FALSE;
+ vp[2] = OBJECT_TO_JSVAL(nameqn);
+
+ if (funid)
+ return xml_list_helper(cx, xml, vp) != NULL;
+
+ return xml_processingInstructions_helper(cx, obj, xml, nameqn, vp);
+}
+
+static JSBool
+xml_prependChild(JSContext *cx, uintN argc, jsval *vp)
+{
+ NON_LIST_XML_METHOD_PROLOG;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(obj);
+ return Insert(cx, xml, 0, argc != 0 ? vp[2] : JSVAL_VOID);
+}
+
+/* XML and XMLList */
+static JSBool
+xml_propertyIsEnumerable(JSContext *cx, uintN argc, jsval *vp)
+{
+ uint32 index;
+
+ XML_METHOD_PROLOG;
+ *vp = JSVAL_FALSE;
+ if (argc != 0 && js_IdIsIndex(vp[2], &index)) {
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ /* 13.5.4.18. */
+ *vp = BOOLEAN_TO_JSVAL(index < xml->xml_kids.length);
+ } else {
+ /* 13.4.4.30. */
+ *vp = BOOLEAN_TO_JSVAL(index == 0);
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+namespace_full_match(const void *a, const void *b)
+{
+ const JSObject *nsa = (const JSObject *) a;
+ const JSObject *nsb = (const JSObject *) b;
+ JSString *prefixa = GetPrefix(nsa);
+ JSString *prefixb;
+
+ if (prefixa) {
+ prefixb = GetPrefix(nsb);
+ if (prefixb && !js_EqualStrings(prefixa, prefixb))
+ return JS_FALSE;
+ }
+ return js_EqualStrings(GetURI(nsa), GetURI(nsb));
+}
+
+static JSBool
+xml_removeNamespace_helper(JSContext *cx, JSXML *xml, JSObject *ns)
+{
+ JSObject *thisns, *attrns;
+ uint32 i, n;
+ JSXML *attr, *kid;
+
+ thisns = GetNamespace(cx, xml->name, &xml->xml_namespaces);
+ JS_ASSERT(thisns);
+ if (thisns == ns)
+ return JS_TRUE;
+
+ for (i = 0, n = xml->xml_attrs.length; i < n; i++) {
+ attr = XMLARRAY_MEMBER(&xml->xml_attrs, i, JSXML);
+ if (!attr)
+ continue;
+ attrns = GetNamespace(cx, attr->name, &xml->xml_namespaces);
+ JS_ASSERT(attrns);
+ if (attrns == ns)
+ return JS_TRUE;
+ }
+
+ i = XMLARRAY_FIND_MEMBER(&xml->xml_namespaces, ns, namespace_full_match);
+ if (i != XML_NOT_FOUND)
+ XMLArrayDelete(cx, &xml->xml_namespaces, i, JS_TRUE);
+
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ if (!xml_removeNamespace_helper(cx, kid, ns))
+ return JS_FALSE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_removeNamespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ goto done;
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (!NamespaceHelper(cx, NULL, argc == 0 ? -1 : 1, vp + 2, vp))
+ return JS_FALSE;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+ ns = JSVAL_TO_OBJECT(*vp);
+
+ /* NOTE: remove ns from each ancestor if not used by that ancestor. */
+ if (!xml_removeNamespace_helper(cx, xml, ns))
+ return JS_FALSE;
+ done:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_replace(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval value;
+ JSXML *vxml, *kid;
+ uint32 index, i;
+ JSObject *nameqn;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (xml->xml_class != JSXML_CLASS_ELEMENT)
+ goto done;
+
+ if (argc <= 1) {
+ value = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.
+ typeAtoms[JSTYPE_VOID]));
+ } else {
+ value = vp[3];
+ vxml = VALUE_IS_XML(cx, value)
+ ? (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(value))
+ : NULL;
+ if (!vxml) {
+ if (!JS_ConvertValue(cx, value, JSTYPE_STRING, &vp[3]))
+ return JS_FALSE;
+ value = vp[3];
+ } else {
+ vxml = DeepCopy(cx, vxml, NULL, 0);
+ if (!vxml)
+ return JS_FALSE;
+ value = vp[3] = OBJECT_TO_JSVAL(vxml->object);
+ }
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ if (argc == 0 || !js_IdIsIndex(vp[2], &index)) {
+ /*
+ * Call function QName per spec, not ToXMLName, to avoid attribute
+ * names.
+ */
+ if (!QNameHelper(cx, NULL, &js_QNameClass.base, argc == 0 ? -1 : 1,
+ vp + 2, vp)) {
+ return JS_FALSE;
+ }
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(*vp));
+ nameqn = JSVAL_TO_OBJECT(*vp);
+
+ i = xml->xml_kids.length;
+ index = XML_NOT_FOUND;
+ while (i != 0) {
+ --i;
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && MatchElemName(nameqn, kid)) {
+ if (i != XML_NOT_FOUND)
+ DeleteByIndex(cx, xml, i);
+ index = i;
+ }
+ }
+
+ if (index == XML_NOT_FOUND)
+ goto done;
+ }
+
+ if (!Replace(cx, xml, index, value))
+ return JS_FALSE;
+
+ done:
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setChildren(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj;
+
+ if (!StartNonListXMLMethod(cx, vp, &obj))
+ return JS_FALSE;
+
+ *vp = argc != 0 ? vp[2] : JSVAL_VOID; /* local root */
+ if (!PutProperty(cx, obj, ATOM_KEY(cx->runtime->atomState.starAtom), vp))
+ return JS_FALSE;
+
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setLocalName(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ JSString *namestr;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (!JSXML_HAS_NAME(xml))
+ return JS_TRUE;
+
+ if (argc == 0) {
+ namestr = ATOM_TO_STRING(cx->runtime->atomState.typeAtoms[JSTYPE_VOID]);
+ } else {
+ name = vp[2];
+ if (!JSVAL_IS_PRIMITIVE(name) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(name)) == &js_QNameClass.base) {
+ nameqn = JSVAL_TO_OBJECT(name);
+ namestr = GetLocalName(nameqn);
+ } else {
+ if (!JS_ConvertValue(cx, name, JSTYPE_STRING, &vp[2]))
+ return JS_FALSE;
+ name = vp[2];
+ namestr = JSVAL_TO_STRING(name);
+ }
+ }
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ xml->name->fslots[JSSLOT_LOCAL_NAME] = namestr
+ ? STRING_TO_JSVAL(namestr)
+ : JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setName(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval name;
+ JSObject *nameqn;
+ JSXML *nsowner;
+ JSXMLArray *nsarray;
+ uint32 i, n;
+ JSObject *ns;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (!JSXML_HAS_NAME(xml))
+ return JS_TRUE;
+
+ if (argc == 0) {
+ name = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.
+ typeAtoms[JSTYPE_VOID]));
+ } else {
+ name = vp[2];
+ if (!JSVAL_IS_PRIMITIVE(name) &&
+ OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(name)) == &js_QNameClass.base &&
+ !GetURI(nameqn = JSVAL_TO_OBJECT(name))) {
+ name = vp[2] = nameqn->fslots[JSSLOT_LOCAL_NAME];
+ }
+ }
+
+ nameqn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1, &name);
+ if (!nameqn)
+ return JS_FALSE;
+
+ /* ECMA-357 13.4.4.35 Step 4. */
+ if (xml->xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION)
+ nameqn->fslots[JSSLOT_URI] = STRING_TO_JSVAL(cx->runtime->emptyString);
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+ xml->name = nameqn;
+
+ /*
+ * Erratum: nothing in 13.4.4.35 talks about making the name match the
+ * in-scope namespaces, either by finding an in-scope namespace with a
+ * matching uri and setting the new name's prefix to that namespace's
+ * prefix, or by extending the in-scope namespaces for xml (which are in
+ * xml->parent if xml is an attribute or a PI).
+ */
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ nsowner = xml;
+ } else {
+ if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT)
+ return JS_TRUE;
+ nsowner = xml->parent;
+ }
+
+ if (GetPrefix(nameqn)) {
+ /*
+ * The name being set has a prefix, which originally came from some
+ * namespace object (which may be the null namespace, where both the
+ * prefix and uri are the empty string). We must go through a full
+ * GetNamespace in case that namespace is in-scope in nsowner.
+ *
+ * If we find such an in-scope namespace, we return true right away,
+ * in this block. Otherwise, we fall through to the final return of
+ * AddInScopeNamespace(cx, nsowner, ns).
+ */
+ ns = GetNamespace(cx, nameqn, &nsowner->xml_namespaces);
+ if (!ns)
+ return JS_FALSE;
+
+ /* XXXbe have to test membership to see whether GetNamespace added */
+ if (XMLARRAY_HAS_MEMBER(&nsowner->xml_namespaces, ns, NULL))
+ return JS_TRUE;
+ } else {
+ /*
+ * At this point, we know prefix of nameqn is null, so its uri can't
+ * be the empty string (the null namespace always uses the empty string
+ * for both prefix and uri).
+ *
+ * This means we must inline GetNamespace and specialize it to match
+ * uri only, never prefix. If we find a namespace with nameqn's uri
+ * already in nsowner->xml_namespaces, then all that we need do is set
+ * prefix of nameqn to that namespace's prefix.
+ *
+ * If no such namespace exists, we can create one without going through
+ * the constructor, because we know uri of nameqn is non-empty (so
+ * prefix does not need to be converted from null to empty by QName).
+ */
+ JS_ASSERT(!IS_EMPTY(GetURI(nameqn)));
+
+ nsarray = &nsowner->xml_namespaces;
+ for (i = 0, n = nsarray->length; i < n; i++) {
+ ns = XMLARRAY_MEMBER(nsarray, i, JSObject);
+ if (ns && js_EqualStrings(GetURI(ns), GetURI(nameqn))) {
+ nameqn->fslots[JSSLOT_PREFIX] = ns->fslots[JSSLOT_PREFIX];
+ return JS_TRUE;
+ }
+ }
+
+ ns = NewXMLNamespace(cx, NULL, GetURI(nameqn), JS_TRUE);
+ if (!ns)
+ return JS_FALSE;
+ }
+
+ if (!AddInScopeNamespace(cx, nsowner, ns))
+ return JS_FALSE;
+ vp[0] = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+xml_setNamespace(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *qn;
+ JSObject *ns;
+ jsval qnargv[2];
+ JSXML *nsowner;
+
+ NON_LIST_XML_METHOD_PROLOG;
+ if (!JSXML_HAS_NAME(xml))
+ return JS_TRUE;
+
+ xml = CHECK_COPY_ON_WRITE(cx, xml, obj);
+ if (!xml)
+ return JS_FALSE;
+
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj,
+ argc == 0 ? 0 : 1, vp + 2);
+ if (!ns)
+ return JS_FALSE;
+ vp[0] = OBJECT_TO_JSVAL(ns);
+ ns->fslots[JSSLOT_DECLARED] = JSVAL_TRUE;
+
+ qnargv[0] = vp[2] = OBJECT_TO_JSVAL(ns);
+ qnargv[1] = OBJECT_TO_JSVAL(xml->name);
+ qn = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 2, qnargv);
+ if (!qn)
+ return JS_FALSE;
+
+ xml->name = qn;
+
+ /*
+ * Erratum: the spec fails to update the governing in-scope namespaces.
+ * See the erratum noted in xml_setName, above.
+ */
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ nsowner = xml;
+ } else {
+ if (!xml->parent || xml->parent->xml_class != JSXML_CLASS_ELEMENT)
+ return JS_TRUE;
+ nsowner = xml->parent;
+ }
+ if (!AddInScopeNamespace(cx, nsowner, ns))
+ return JS_FALSE;
+ vp[0] = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_text_helper(JSContext *cx, JSObject *obj, JSXML *xml, jsval *vp)
+{
+ JSXML *list, *kid, *vxml;
+ uint32 i, n;
+ JSBool ok;
+ JSObject *kidobj;
+ jsval v;
+
+ list = xml_list_helper(cx, xml, vp);
+ if (!list)
+ return JS_FALSE;
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ ok = JS_TRUE;
+ for (i = 0, n = xml->xml_kids.length; i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_ELEMENT) {
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ break;
+ kidobj = js_GetXMLObject(cx, kid);
+ if (kidobj) {
+ ok = xml_text_helper(cx, kidobj, kid, &v);
+ } else {
+ ok = JS_FALSE;
+ v = JSVAL_NULL;
+ }
+ js_LeaveLocalRootScopeWithResult(cx, v);
+ if (!ok)
+ return JS_FALSE;
+ vxml = (JSXML *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ if (JSXML_LENGTH(vxml) != 0 && !Append(cx, list, vxml))
+ return JS_FALSE;
+ }
+ }
+ } else {
+ for (i = 0, n = JSXML_LENGTH(xml); i < n; i++) {
+ kid = XMLARRAY_MEMBER(&xml->xml_kids, i, JSXML);
+ if (kid && kid->xml_class == JSXML_CLASS_TEXT) {
+ if (!Append(cx, list, kid))
+ return JS_FALSE;
+ }
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+xml_text(JSContext *cx, uintN argc, jsval *vp)
+{
+ XML_METHOD_PROLOG;
+ return xml_text_helper(cx, obj, xml, vp);
+}
+
+/* XML and XMLList */
+static JSString *
+xml_toString_helper(JSContext *cx, JSXML *xml)
+{
+ JSString *str, *kidstr;
+ JSXML *kid;
+ JSXMLArrayCursor cursor;
+
+ if (xml->xml_class == JSXML_CLASS_ATTRIBUTE ||
+ xml->xml_class == JSXML_CLASS_TEXT) {
+ return xml->xml_value;
+ }
+
+ if (!HasSimpleContent(xml))
+ return ToXMLString(cx, OBJECT_TO_JSVAL(xml->object), 0);
+
+ str = cx->runtime->emptyString;
+ if (!js_EnterLocalRootScope(cx))
+ return NULL;
+ XMLArrayCursorInit(&cursor, &xml->xml_kids);
+ while ((kid = (JSXML *) XMLArrayCursorNext(&cursor)) != NULL) {
+ if (kid->xml_class != JSXML_CLASS_COMMENT &&
+ kid->xml_class != JSXML_CLASS_PROCESSING_INSTRUCTION) {
+ kidstr = xml_toString_helper(cx, kid);
+ if (!kidstr) {
+ str = NULL;
+ break;
+ }
+ str = js_ConcatStrings(cx, str, kidstr);
+ if (!str)
+ break;
+ }
+ }
+ XMLArrayCursorFinish(&cursor);
+ js_LeaveLocalRootScopeWithResult(cx, STRING_TO_JSVAL(str));
+ return str;
+}
+
+static JSBool
+xml_toSource(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval thisv;
+ JSString *str;
+
+ thisv = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(thisv))
+ return JS_FALSE;
+ str = ToXMLString(cx, thisv, TO_SOURCE_FLAG);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+static JSBool
+xml_toString(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSString *str;
+
+ XML_METHOD_PROLOG;
+ str = xml_toString_helper(cx, xml);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_toXMLString(JSContext *cx, uintN argc, jsval *vp)
+{
+ jsval thisv;
+ JSString *str;
+
+ thisv = JS_THIS(cx, vp);
+ if (JSVAL_IS_NULL(thisv))
+ return JS_FALSE;
+ str = ToXMLString(cx, thisv, 0);
+ if (!str)
+ return JS_FALSE;
+ *vp = STRING_TO_JSVAL(str);
+ return JS_TRUE;
+}
+
+/* XML and XMLList */
+static JSBool
+xml_valueOf(JSContext *cx, uintN argc, jsval *vp)
+{
+ *vp = JS_THIS(cx, vp);
+ return !JSVAL_IS_NULL(*vp);
+}
+
+static JSFunctionSpec xml_methods[] = {
+ JS_FN("addNamespace", xml_addNamespace, 1,0),
+ JS_FN("appendChild", xml_appendChild, 1,0),
+ JS_FN(js_attribute_str, xml_attribute, 1,0),
+ JS_FN("attributes", xml_attributes, 0,0),
+ JS_FN("child", xml_child, 1,0),
+ JS_FN("childIndex", xml_childIndex, 0,0),
+ JS_FN("children", xml_children, 0,0),
+ JS_FN("comments", xml_comments, 0,0),
+ JS_FN("contains", xml_contains, 1,0),
+ JS_FN("copy", xml_copy, 0,0),
+ JS_FN("descendants", xml_descendants, 1,0),
+ JS_FN("elements", xml_elements, 1,0),
+ JS_FN("hasOwnProperty", xml_hasOwnProperty, 1,0),
+ JS_FN("hasComplexContent", xml_hasComplexContent, 1,0),
+ JS_FN("hasSimpleContent", xml_hasSimpleContent, 1,0),
+ JS_FN("inScopeNamespaces", xml_inScopeNamespaces, 0,0),
+ JS_FN("insertChildAfter", xml_insertChildAfter, 2,0),
+ JS_FN("insertChildBefore", xml_insertChildBefore, 2,0),
+ JS_FN(js_length_str, xml_length, 0,0),
+ JS_FN(js_localName_str, xml_localName, 0,0),
+ JS_FN(js_name_str, xml_name, 0,0),
+ JS_FN(js_namespace_str, xml_namespace, 1,0),
+ JS_FN("namespaceDeclarations", xml_namespaceDeclarations, 0,0),
+ JS_FN("nodeKind", xml_nodeKind, 0,0),
+ JS_FN("normalize", xml_normalize, 0,0),
+ JS_FN(js_xml_parent_str, xml_parent, 0,0),
+ JS_FN("processingInstructions",xml_processingInstructions,1,0),
+ JS_FN("prependChild", xml_prependChild, 1,0),
+ JS_FN("propertyIsEnumerable", xml_propertyIsEnumerable, 1,0),
+ JS_FN("removeNamespace", xml_removeNamespace, 1,0),
+ JS_FN("replace", xml_replace, 2,0),
+ JS_FN("setChildren", xml_setChildren, 1,0),
+ JS_FN("setLocalName", xml_setLocalName, 1,0),
+ JS_FN("setName", xml_setName, 1,0),
+ JS_FN("setNamespace", xml_setNamespace, 1,0),
+ JS_FN(js_text_str, xml_text, 0,0),
+ JS_FN(js_toSource_str, xml_toSource, 0,0),
+ JS_FN(js_toString_str, xml_toString, 0,0),
+ JS_FN(js_toXMLString_str, xml_toXMLString, 0,0),
+ JS_FN(js_valueOf_str, xml_valueOf, 0,0),
+ JS_FS_END
+};
+
+static JSBool
+CopyXMLSettings(JSContext *cx, JSObject *from, JSObject *to)
+{
+ int i;
+ const char *name;
+ jsval v;
+
+ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
+ name = xml_static_props[i].name;
+ if (!JS_GetProperty(cx, from, name, &v))
+ return JS_FALSE;
+ if (JSVAL_IS_BOOLEAN(v) && !JS_SetProperty(cx, to, name, &v))
+ return JS_FALSE;
+ }
+
+ name = xml_static_props[i].name;
+ if (!JS_GetProperty(cx, from, name, &v))
+ return JS_FALSE;
+ if (JSVAL_IS_NUMBER(v) && !JS_SetProperty(cx, to, name, &v))
+ return JS_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+SetDefaultXMLSettings(JSContext *cx, JSObject *obj)
+{
+ int i;
+ jsval v;
+
+ for (i = XML_IGNORE_COMMENTS; i < XML_PRETTY_INDENT; i++) {
+ v = JSVAL_TRUE;
+ if (!JS_SetProperty(cx, obj, xml_static_props[i].name, &v))
+ return JS_FALSE;
+ }
+ v = INT_TO_JSVAL(2);
+ return JS_SetProperty(cx, obj, xml_static_props[i].name, &v);
+}
+
+static JSBool
+xml_settings(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *settings;
+ JSObject *obj;
+
+ settings = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!settings)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(settings);
+ obj = JS_THIS_OBJECT(cx, vp);
+ return obj && CopyXMLSettings(cx, obj, settings);
+}
+
+static JSBool
+xml_setSettings(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *obj, *settings;
+ jsval v;
+ JSBool ok;
+
+ obj = JS_THIS_OBJECT(cx, vp);
+ if (!obj)
+ return JS_FALSE;
+ v = (argc == 0) ? JSVAL_VOID : vp[2];
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v)) {
+ cx->xmlSettingFlags = 0;
+ ok = SetDefaultXMLSettings(cx, obj);
+ } else {
+ if (JSVAL_IS_PRIMITIVE(v))
+ return JS_TRUE;
+ settings = JSVAL_TO_OBJECT(v);
+ cx->xmlSettingFlags = 0;
+ ok = CopyXMLSettings(cx, settings, obj);
+ }
+ if (ok)
+ cx->xmlSettingFlags |= XSF_CACHE_VALID;
+ return ok;
+}
+
+static JSBool
+xml_defaultSettings(JSContext *cx, uintN argc, jsval *vp)
+{
+ JSObject *settings;
+
+ settings = JS_NewObject(cx, NULL, NULL, NULL);
+ if (!settings)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(settings);
+ return SetDefaultXMLSettings(cx, settings);
+}
+
+static JSFunctionSpec xml_static_methods[] = {
+ JS_FN("settings", xml_settings, 0,0),
+ JS_FN("setSettings", xml_setSettings, 1,0),
+ JS_FN("defaultSettings", xml_defaultSettings, 0,0),
+ JS_FS_END
+};
+
+static JSBool
+XML(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval v;
+ JSXML *xml, *copy;
+ JSObject *xobj, *vobj;
+ JSClass *clasp;
+
+ v = argv[0];
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ v = STRING_TO_JSVAL(cx->runtime->emptyString);
+
+ xobj = ToXML(cx, v);
+ if (!xobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(xobj);
+ xml = (JSXML *) JS_GetPrivate(cx, xobj);
+
+ if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && !JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ clasp = OBJ_GET_CLASS(cx, vobj);
+ if (clasp == &js_XMLClass ||
+ (clasp->flags & JSCLASS_DOCUMENT_OBSERVER)) {
+ /* No need to lock obj, it's newly constructed and thread local. */
+ copy = DeepCopy(cx, xml, obj, 0);
+ if (!copy)
+ return JS_FALSE;
+ JS_ASSERT(copy->object == obj);
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+XMLList(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+ jsval v;
+ JSObject *vobj, *listobj;
+ JSXML *xml, *list;
+
+ v = argv[0];
+ if (JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
+ v = STRING_TO_JSVAL(cx->runtime->emptyString);
+
+ if ((cx->fp->flags & JSFRAME_CONSTRUCTING) && !JSVAL_IS_PRIMITIVE(v)) {
+ vobj = JSVAL_TO_OBJECT(v);
+ if (OBJECT_IS_XML(cx, vobj)) {
+ xml = (JSXML *) JS_GetPrivate(cx, vobj);
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ listobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!listobj)
+ return JS_FALSE;
+ *rval = OBJECT_TO_JSVAL(listobj);
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ if (!Append(cx, list, xml))
+ return JS_FALSE;
+ return JS_TRUE;
+ }
+ }
+ }
+
+ /* Toggle on XML support since the script has explicitly requested it. */
+ listobj = ToXMLList(cx, v);
+ if (!listobj)
+ return JS_FALSE;
+
+ *rval = OBJECT_TO_JSVAL(listobj);
+ return JS_TRUE;
+}
+
+#define JSXML_LIST_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLListVar))
+#define JSXML_ELEMENT_SIZE (offsetof(JSXML, u) + sizeof(struct JSXMLElemVar))
+#define JSXML_LEAF_SIZE (offsetof(JSXML, u) + sizeof(JSString *))
+
+static size_t sizeof_JSXML[JSXML_CLASS_LIMIT] = {
+ JSXML_LIST_SIZE, /* JSXML_CLASS_LIST */
+ JSXML_ELEMENT_SIZE, /* JSXML_CLASS_ELEMENT */
+ JSXML_LEAF_SIZE, /* JSXML_CLASS_ATTRIBUTE */
+ JSXML_LEAF_SIZE, /* JSXML_CLASS_PROCESSING_INSTRUCTION */
+ JSXML_LEAF_SIZE, /* JSXML_CLASS_TEXT */
+ JSXML_LEAF_SIZE /* JSXML_CLASS_COMMENT */
+};
+
+#ifdef DEBUG_notme
+JSCList xml_leaks = JS_INIT_STATIC_CLIST(&xml_leaks);
+uint32 xml_serial;
+#endif
+
+JSXML *
+js_NewXML(JSContext *cx, JSXMLClass xml_class)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) js_NewGCThing(cx, GCX_XML, sizeof_JSXML[xml_class]);
+ if (!xml)
+ return NULL;
+
+ xml->object = NULL;
+ xml->domnode = NULL;
+ xml->parent = NULL;
+ xml->name = NULL;
+ xml->xml_class = xml_class;
+ xml->xml_flags = 0;
+ if (JSXML_CLASS_HAS_VALUE(xml_class)) {
+ xml->xml_value = cx->runtime->emptyString;
+ } else {
+ XMLArrayInit(cx, &xml->xml_kids, 0);
+ if (xml_class == JSXML_CLASS_LIST) {
+ xml->xml_target = NULL;
+ xml->xml_targetprop = NULL;
+ } else {
+ XMLArrayInit(cx, &xml->xml_namespaces, 0);
+ XMLArrayInit(cx, &xml->xml_attrs, 0);
+ }
+ }
+
+#ifdef DEBUG_notme
+ JS_APPEND_LINK(&xml->links, &xml_leaks);
+ xml->serial = xml_serial++;
+#endif
+ METER(xml_stats.xml);
+ return xml;
+}
+
+void
+js_TraceXML(JSTracer *trc, JSXML *xml)
+{
+ if (xml->object)
+ JS_CALL_OBJECT_TRACER(trc, xml->object, "object");
+ if (xml->name)
+ JS_CALL_OBJECT_TRACER(trc, xml->name, "name");
+ if (xml->parent)
+ JS_CALL_TRACER(trc, xml->parent, JSTRACE_XML, "xml_parent");
+
+ if (JSXML_HAS_VALUE(xml)) {
+ if (xml->xml_value)
+ JS_CALL_STRING_TRACER(trc, xml->xml_value, "value");
+ return;
+ }
+
+ xml_trace_vector(trc,
+ (JSXML **) xml->xml_kids.vector,
+ xml->xml_kids.length);
+ XMLArrayCursorTrace(trc, xml->xml_kids.cursors);
+ if (IS_GC_MARKING_TRACER(trc))
+ XMLArrayTrim(&xml->xml_kids);
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ if (xml->xml_target)
+ JS_CALL_TRACER(trc, xml->xml_target, JSTRACE_XML, "target");
+ if (xml->xml_targetprop)
+ JS_CALL_OBJECT_TRACER(trc, xml->xml_targetprop, "targetprop");
+ } else {
+ TraceObjectVector(trc,
+ (JSObject **) xml->xml_namespaces.vector,
+ xml->xml_namespaces.length);
+ XMLArrayCursorTrace(trc, xml->xml_namespaces.cursors);
+ if (IS_GC_MARKING_TRACER(trc))
+ XMLArrayTrim(&xml->xml_namespaces);
+
+ xml_trace_vector(trc,
+ (JSXML **) xml->xml_attrs.vector,
+ xml->xml_attrs.length);
+ XMLArrayCursorTrace(trc, xml->xml_attrs.cursors);
+ if (IS_GC_MARKING_TRACER(trc))
+ XMLArrayTrim(&xml->xml_attrs);
+ }
+}
+
+void
+js_FinalizeXML(JSContext *cx, JSXML *xml)
+{
+ if (JSXML_HAS_KIDS(xml)) {
+ XMLArrayFinish(cx, &xml->xml_kids);
+ if (xml->xml_class == JSXML_CLASS_ELEMENT) {
+ XMLArrayFinish(cx, &xml->xml_namespaces);
+ XMLArrayFinish(cx, &xml->xml_attrs);
+ }
+ }
+
+#ifdef DEBUG_notme
+ JS_REMOVE_LINK(&xml->links);
+#endif
+}
+
+JSObject *
+js_ParseNodeToXMLObject(JSContext *cx, JSParseContext *pc, JSParseNode *pn)
+{
+ jsval nsval;
+ JSObject *ns;
+ JSXMLArray nsarray;
+ JSXML *xml;
+
+ if (!js_GetDefaultXMLNamespace(cx, &nsval))
+ return NULL;
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(nsval));
+ ns = JSVAL_TO_OBJECT(nsval);
+
+ if (!XMLArrayInit(cx, &nsarray, 1))
+ return NULL;
+
+ XMLARRAY_APPEND(cx, &nsarray, ns);
+ xml = ParseNodeToXML(cx, pc, pn, &nsarray, XSF_PRECOMPILED_ROOT);
+ XMLArrayFinish(cx, &nsarray);
+ if (!xml)
+ return NULL;
+
+ return xml->object;
+}
+
+JSObject *
+js_NewXMLObject(JSContext *cx, JSXMLClass xml_class)
+{
+ JSXML *xml;
+ JSObject *obj;
+ JSTempValueRooter tvr;
+
+ xml = js_NewXML(cx, xml_class);
+ if (!xml)
+ return NULL;
+ JS_PUSH_TEMP_ROOT_XML(cx, xml, &tvr);
+ obj = js_GetXMLObject(cx, xml);
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return obj;
+}
+
+static JSObject *
+NewXMLObject(JSContext *cx, JSXML *xml)
+{
+ JSObject *obj;
+
+ obj = js_NewObject(cx, &js_XMLClass, NULL, NULL, 0);
+ if (!obj || !JS_SetPrivate(cx, obj, xml)) {
+ cx->weakRoots.newborn[GCX_OBJECT] = NULL;
+ return NULL;
+ }
+ METER(xml_stats.xmlobj);
+ return obj;
+}
+
+JSObject *
+js_GetXMLObject(JSContext *cx, JSXML *xml)
+{
+ JSObject *obj;
+
+ obj = xml->object;
+ if (obj) {
+ JS_ASSERT(JS_GetPrivate(cx, obj) == xml);
+ return obj;
+ }
+
+ /*
+ * A JSXML cannot be shared among threads unless it has an object.
+ * A JSXML cannot be given an object unless:
+ * (a) it has no parent; or
+ * (b) its parent has no object (therefore is thread-private); or
+ * (c) its parent's object is locked.
+ *
+ * Once given an object, a JSXML is immutable.
+ */
+ JS_ASSERT(!xml->parent ||
+ !xml->parent->object ||
+ JS_IS_OBJ_LOCKED(cx, xml->parent->object));
+
+ obj = NewXMLObject(cx, xml);
+ if (!obj)
+ return NULL;
+ xml->object = obj;
+ return obj;
+}
+
+JSObject *
+js_InitNamespaceClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_NamespaceClass.base, Namespace, 2,
+ namespace_props, namespace_methods, NULL, NULL);
+}
+
+JSObject *
+js_InitQNameClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_QNameClass.base, QName, 2,
+ qname_props, qname_methods, NULL, NULL);
+}
+
+JSObject *
+js_InitAttributeNameClass(JSContext *cx, JSObject *obj)
+{
+ return JS_InitClass(cx, obj, NULL, &js_AttributeNameClass, AttributeName, 2,
+ qname_props, qname_methods, NULL, NULL);
+}
+
+JSObject *
+js_InitAnyNameClass(JSContext *cx, JSObject *obj)
+{
+ jsval v;
+
+ if (!js_GetAnyName(cx, &v))
+ return NULL;
+ return JSVAL_TO_OBJECT(v);
+}
+
+JSObject *
+js_InitXMLClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto, *pobj;
+ JSFunction *fun;
+ JSXML *xml;
+ JSProperty *prop;
+ JSScopeProperty *sprop;
+ jsval cval, vp[3];
+
+ /* Define the isXMLName function. */
+ if (!JS_DefineFunction(cx, obj, js_isXMLName_str, xml_isXMLName, 1, 0))
+ return NULL;
+
+ /* Define the XML class constructor and prototype. */
+ proto = JS_InitClass(cx, obj, NULL, &js_XMLClass, XML, 1,
+ NULL, xml_methods,
+ xml_static_props, xml_static_methods);
+ if (!proto)
+ return NULL;
+
+ xml = js_NewXML(cx, JSXML_CLASS_TEXT);
+ if (!xml || !JS_SetPrivate(cx, proto, xml))
+ return NULL;
+ xml->object = proto;
+ METER(xml_stats.xmlobj);
+
+ /*
+ * Prepare to set default settings on the XML constructor we just made.
+ * NB: We can't use JS_GetConstructor, because it calls OBJ_GET_PROPERTY,
+ * which is xml_getProperty, which creates a new XMLList every time! We
+ * must instead call js_LookupProperty directly.
+ */
+ if (!js_LookupProperty(cx, proto,
+ ATOM_TO_JSID(cx->runtime->atomState.constructorAtom),
+ &pobj, &prop)) {
+ return NULL;
+ }
+ JS_ASSERT(prop);
+ sprop = (JSScopeProperty *) prop;
+ JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
+ cval = OBJ_GET_SLOT(cx, pobj, sprop->slot);
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ JS_ASSERT(VALUE_IS_FUNCTION(cx, cval));
+
+ /* Set default settings. */
+ vp[0] = JSVAL_NULL;
+ vp[1] = cval;
+ vp[2] = JSVAL_VOID;
+ if (!xml_setSettings(cx, 1, vp))
+ return NULL;
+
+ /* Define the XMLList function and give it the same prototype as XML. */
+ fun = JS_DefineFunction(cx, obj, js_XMLList_str, XMLList, 1, 0);
+ if (!fun)
+ return NULL;
+ if (!js_SetClassPrototype(cx, FUN_OBJECT(fun), proto,
+ JSPROP_READONLY | JSPROP_PERMANENT)) {
+ return NULL;
+ }
+ return proto;
+}
+
+JSObject *
+js_InitXMLClasses(JSContext *cx, JSObject *obj)
+{
+ if (!js_InitNamespaceClass(cx, obj))
+ return NULL;
+ if (!js_InitQNameClass(cx, obj))
+ return NULL;
+ if (!js_InitAttributeNameClass(cx, obj))
+ return NULL;
+ if (!js_InitAnyNameClass(cx, obj))
+ return NULL;
+ if (!js_InitXMLFilterClass(cx, obj))
+ return NULL;
+ return js_InitXMLClass(cx, obj);
+}
+
+JSBool
+js_GetFunctionNamespace(JSContext *cx, jsval *vp)
+{
+ JSRuntime *rt;
+ JSObject *obj;
+ JSAtom *atom;
+ JSString *prefix, *uri;
+
+ /* An invalid URI, for internal use only, guaranteed not to collide. */
+ static const char anti_uri[] = "@mozilla.org/js/function";
+
+ /* Optimize by avoiding JS_LOCK_GC(rt) for the common case. */
+ rt = cx->runtime;
+ obj = rt->functionNamespaceObject;
+ if (!obj) {
+ JS_LOCK_GC(rt);
+ obj = rt->functionNamespaceObject;
+ if (!obj) {
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * Note that any race to atomize anti_uri here is resolved by
+ * the atom table code, such that at most one atom for anti_uri
+ * is created. We store in rt->atomState.lazy unconditionally,
+ * since we are guaranteed to overwrite either null or the same
+ * atom pointer.
+ */
+ atom = js_Atomize(cx, anti_uri, sizeof anti_uri - 1, ATOM_PINNED);
+ if (!atom)
+ return JS_FALSE;
+ rt->atomState.lazy.functionNamespaceURIAtom = atom;
+
+ prefix = ATOM_TO_STRING(rt->atomState.typeAtoms[JSTYPE_FUNCTION]);
+ uri = ATOM_TO_STRING(atom);
+ obj = NewXMLNamespace(cx, prefix, uri, JS_FALSE);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * Avoid entraining any in-scope Object.prototype. The loss of
+ * Namespace.prototype is not detectable, as there is no way to
+ * refer to this instance in scripts. When used to qualify method
+ * names, its prefix and uri references are copied to the QName.
+ */
+ OBJ_CLEAR_PROTO(cx, obj);
+ OBJ_CLEAR_PARENT(cx, obj);
+
+ JS_LOCK_GC(rt);
+ if (!rt->functionNamespaceObject)
+ rt->functionNamespaceObject = obj;
+ else
+ obj = rt->functionNamespaceObject;
+ }
+ JS_UNLOCK_GC(rt);
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+/*
+ * Note the asymmetry between js_GetDefaultXMLNamespace and js_SetDefaultXML-
+ * Namespace. Get searches fp->scopeChain for JS_DEFAULT_XML_NAMESPACE_ID,
+ * while Set sets JS_DEFAULT_XML_NAMESPACE_ID in fp->varobj (unless fp is a
+ * lightweight function activation). There's no requirement that fp->varobj
+ * lie directly on fp->scopeChain, although it should be reachable using the
+ * prototype chain from a scope object (cf. JSOPTION_VAROBJFIX in jsapi.h).
+ *
+ * If Get can't find JS_DEFAULT_XML_NAMESPACE_ID along the scope chain, it
+ * creates a default namespace via 'new Namespace()'. In contrast, Set uses
+ * its v argument as the uri of a new Namespace, with "" as the prefix. See
+ * ECMA-357 12.1 and 12.1.1. Note that if Set is called with a Namespace n,
+ * the default XML namespace will be set to ("", n.uri). So the uri string
+ * is really the only usefully stored value of the default namespace.
+ */
+JSBool
+js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
+{
+ JSStackFrame *fp;
+ JSObject *ns, *obj, *tmp;
+ jsval v;
+
+ fp = cx->fp;
+ ns = fp->xmlNamespace;
+ if (ns) {
+ *vp = OBJECT_TO_JSVAL(ns);
+ return JS_TRUE;
+ }
+
+ obj = NULL;
+ for (tmp = fp->scopeChain; tmp; tmp = OBJ_GET_PARENT(cx, obj)) {
+ obj = tmp;
+ if (!OBJ_GET_PROPERTY(cx, obj, JS_DEFAULT_XML_NAMESPACE_ID, &v))
+ return JS_FALSE;
+ if (!JSVAL_IS_PRIMITIVE(v)) {
+ fp->xmlNamespace = JSVAL_TO_OBJECT(v);
+ *vp = v;
+ return JS_TRUE;
+ }
+ }
+
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, obj, 0, NULL);
+ if (!ns)
+ return JS_FALSE;
+ v = OBJECT_TO_JSVAL(ns);
+ if (obj &&
+ !OBJ_DEFINE_PROPERTY(cx, obj, JS_DEFAULT_XML_NAMESPACE_ID, v,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+ fp->xmlNamespace = ns;
+ *vp = v;
+ return JS_TRUE;
+}
+
+JSBool
+js_SetDefaultXMLNamespace(JSContext *cx, jsval v)
+{
+ jsval argv[2];
+ JSObject *ns, *varobj;
+ JSStackFrame *fp;
+
+ argv[0] = STRING_TO_JSVAL(cx->runtime->emptyString);
+ argv[1] = v;
+ ns = js_ConstructObject(cx, &js_NamespaceClass.base, NULL, NULL, 2, argv);
+ if (!ns)
+ return JS_FALSE;
+ v = OBJECT_TO_JSVAL(ns);
+
+ fp = cx->fp;
+ varobj = fp->varobj;
+ if (varobj) {
+ if (!OBJ_DEFINE_PROPERTY(cx, varobj, JS_DEFAULT_XML_NAMESPACE_ID, v,
+ JS_PropertyStub, JS_PropertyStub,
+ JSPROP_PERMANENT, NULL)) {
+ return JS_FALSE;
+ }
+ } else {
+ JS_ASSERT(fp->fun && !JSFUN_HEAVYWEIGHT_TEST(fp->fun->flags));
+ }
+ fp->xmlNamespace = JSVAL_TO_OBJECT(v);
+ return JS_TRUE;
+}
+
+JSBool
+js_ToAttributeName(JSContext *cx, jsval *vp)
+{
+ JSObject *qn;
+
+ qn = ToAttributeName(cx, *vp);
+ if (!qn)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(qn);
+ return JS_TRUE;
+}
+
+JSString *
+js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote)
+{
+ return EscapeAttributeValue(cx, NULL, str, quote);
+}
+
+JSString *
+js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str, JSString *str2)
+{
+ size_t len, len2, newlen;
+ jschar *chars, *chars2;
+
+ JSSTRING_CHARS_AND_LENGTH(str, chars, len);
+ if (!JSSTRING_IS_MUTABLE(str)) {
+ str = js_NewStringCopyN(cx, chars, len);
+ if (!str)
+ return NULL;
+ chars = JSFLATSTR_CHARS(str);
+ } else {
+ /*
+ * Reallocating str (because we know it has no other references)
+ * requires purging any deflated string cached for it.
+ */
+ js_PurgeDeflatedStringCache(cx->runtime, str);
+ }
+
+ JSSTRING_CHARS_AND_LENGTH(str2, chars2, len2);
+ newlen = (isName) ? len + 1 + len2 : len + 2 + len2 + 1;
+ chars = (jschar *) JS_realloc(cx, chars, (newlen+1) * sizeof(jschar));
+ if (!chars)
+ return NULL;
+
+ JSFLATSTR_INIT(str, chars, newlen);
+ chars += len;
+ if (isName) {
+ *chars++ = ' ';
+ js_strncpy(chars, chars2, len2);
+ chars += len2;
+ } else {
+ *chars++ = '=';
+ *chars++ = '"';
+ js_strncpy(chars, chars2, len2);
+ chars += len2;
+ *chars++ = '"';
+ }
+ *chars = 0;
+ return str;
+}
+
+JSString *
+js_EscapeElementValue(JSContext *cx, JSString *str)
+{
+ return EscapeElementValue(cx, NULL, str);
+}
+
+JSString *
+js_ValueToXMLString(JSContext *cx, jsval v)
+{
+ return ToXMLString(cx, v, 0);
+}
+
+static JSBool
+anyname_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
+ jsval *rval)
+{
+ *rval = ATOM_KEY(cx->runtime->atomState.starAtom);
+ return JS_TRUE;
+}
+
+JSBool
+js_GetAnyName(JSContext *cx, jsval *vp)
+{
+ JSRuntime *rt;
+ JSObject *obj;
+ JSBool ok;
+
+ /* Optimize by avoiding JS_LOCK_GC(rt) for the common case. */
+ rt = cx->runtime;
+ obj = rt->anynameObject;
+ if (!obj) {
+ JS_LOCK_GC(rt);
+ obj = rt->anynameObject;
+ if (!obj) {
+ JS_UNLOCK_GC(rt);
+
+ /*
+ * Protect multiple newborns created below, in the do-while(0)
+ * loop used to ensure that we leave this local root scope.
+ */
+ ok = js_EnterLocalRootScope(cx);
+ if (!ok)
+ return JS_FALSE;
+
+ do {
+ obj = js_NewObjectWithGivenProto(cx, &js_AnyNameClass, NULL,
+ NULL, 0);
+ if (!obj) {
+ ok = JS_FALSE;
+ break;
+ }
+ InitXMLQName(obj, rt->emptyString, rt->emptyString,
+ ATOM_TO_STRING(rt->atomState.starAtom));
+ METER(xml_stats.qname);
+
+ /*
+ * Avoid entraining any Object.prototype found via cx's scope
+ * chain or global object. This loses the default toString,
+ * but no big deal: we want to customize toString anyway for
+ * clearer diagnostics.
+ */
+ if (!JS_DefineFunction(cx, obj, js_toString_str,
+ anyname_toString, 0, 0)) {
+ ok = JS_FALSE;
+ break;
+ }
+ JS_ASSERT(!OBJ_GET_PROTO(cx, obj));
+ JS_ASSERT(!OBJ_GET_PARENT(cx, obj));
+ } while (0);
+
+ js_LeaveLocalRootScopeWithResult(cx, OBJECT_TO_JSVAL(obj));
+ if (!ok)
+ return JS_FALSE;
+
+ JS_LOCK_GC(rt);
+ if (!rt->anynameObject)
+ rt->anynameObject = obj;
+ else
+ obj = rt->anynameObject;
+ }
+ JS_UNLOCK_GC(rt);
+ }
+ *vp = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+}
+
+JSBool
+js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp)
+{
+ JSObject *nameobj;
+ jsval v;
+ JSObject *qn;
+ jsid funid;
+ JSObject *obj, *target, *proto, *pobj;
+ JSXML *xml;
+ JSBool found;
+ JSProperty *prop;
+ const char *printable;
+
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(nameval));
+ nameobj = JSVAL_TO_OBJECT(nameval);
+ if (OBJ_GET_CLASS(cx, nameobj) == &js_AnyNameClass) {
+ v = STRING_TO_JSVAL(ATOM_TO_STRING(cx->runtime->atomState.starAtom));
+ nameobj = js_ConstructObject(cx, &js_QNameClass.base, NULL, NULL, 1,
+ &v);
+ if (!nameobj)
+ return JS_FALSE;
+ } else {
+ JS_ASSERT(OBJ_GET_CLASS(cx, nameobj) == &js_AttributeNameClass ||
+ OBJ_GET_CLASS(cx, nameobj) == &js_QNameClass.base);
+ }
+
+ qn = nameobj;
+ if (!IsFunctionQName(cx, qn, &funid))
+ return JS_FALSE;
+
+ obj = cx->fp->scopeChain;
+ do {
+ /* Skip any With object that can wrap XML. */
+ target = obj;
+ while (OBJ_GET_CLASS(cx, target) == &js_WithClass) {
+ proto = OBJ_GET_PROTO(cx, target);
+ if (!proto)
+ break;
+ target = proto;
+ }
+
+ if (OBJECT_IS_XML(cx, target)) {
+ if (funid == 0) {
+ xml = (JSXML *) JS_GetPrivate(cx, target);
+ found = HasNamedProperty(xml, qn);
+ } else {
+ if (!HasFunctionProperty(cx, target, funid, &found))
+ return JS_FALSE;
+ }
+ if (found) {
+ *idp = OBJECT_TO_JSID(nameobj);
+ *objp = target;
+ return JS_TRUE;
+ }
+ } else if (funid != 0) {
+ if (!OBJ_LOOKUP_PROPERTY(cx, target, funid, &pobj, &prop))
+ return JS_FALSE;
+ if (prop) {
+ OBJ_DROP_PROPERTY(cx, pobj, prop);
+ *idp = funid;
+ *objp = target;
+ return JS_TRUE;
+ }
+ }
+ } while ((obj = OBJ_GET_PARENT(cx, obj)) != NULL);
+
+ printable = js_ValueToPrintableString(cx, OBJECT_TO_JSVAL(nameobj));
+ if (printable) {
+ JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR,
+ js_GetErrorMessage, NULL,
+ JSMSG_UNDEFINED_XML_NAME, printable);
+ }
+ return JS_FALSE;
+}
+
+JSBool
+js_GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
+{
+ JSObject *target;
+ JSXML *xml;
+ JSTempValueRooter tvr;
+ JSBool ok;
+
+ JS_ASSERT(OBJECT_IS_XML(cx, obj));
+
+ MUST_FLOW_THROUGH("out");
+ JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr);
+
+ /*
+ * See comments before xml_lookupProperty about the need for the proto
+ * chain lookup.
+ */
+ target = obj;
+ for (;;) {
+ ok = js_GetProperty(cx, target, id, vp);
+ if (!ok)
+ goto out;
+ if (VALUE_IS_FUNCTION(cx, *vp)) {
+ ok = JS_TRUE;
+ goto out;
+ }
+ target = OBJ_GET_PROTO(cx, target);
+ if (target == NULL)
+ break;
+ tvr.u.object = target;
+ }
+
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (HasSimpleContent(xml)) {
+ /* Search in String.prototype to implement 11.2.2.1 Step 3(f). */
+ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(JSProto_String),
+ &tvr.u.object);
+ if (!ok)
+ goto out;
+ JS_ASSERT(tvr.u.object);
+ ok = OBJ_GET_PROPERTY(cx, tvr.u.object, id, vp);
+ }
+
+ out:
+ JS_POP_TEMP_ROOT(cx, &tvr);
+ return ok;
+}
+
+static JSXML *
+GetPrivate(JSContext *cx, JSObject *obj, const char *method)
+{
+ JSXML *xml;
+
+ xml = (JSXML *) JS_GetInstancePrivate(cx, obj, &js_XMLClass, NULL);
+ if (!xml) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+ JSMSG_INCOMPATIBLE_METHOD,
+ js_XML_str, method, OBJ_GET_CLASS(cx, obj)->name);
+ }
+ return xml;
+}
+
+JSBool
+js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+ JSXML *xml, *list;
+
+ xml = GetPrivate(cx, obj, "descendants internal method");
+ if (!xml)
+ return JS_FALSE;
+
+ list = Descendants(cx, xml, id);
+ if (!list)
+ return JS_FALSE;
+ *vp = OBJECT_TO_JSVAL(list->object);
+ return JS_TRUE;
+}
+
+JSBool
+js_DeleteXMLListElements(JSContext *cx, JSObject *listobj)
+{
+ JSXML *list;
+ uint32 n;
+
+ list = (JSXML *) JS_GetPrivate(cx, listobj);
+ for (n = list->xml_kids.length; n != 0; --n)
+ DeleteListElement(cx, list, 0);
+
+ return JS_TRUE;
+}
+
+typedef struct JSXMLFilter {
+ JSXML *list;
+ JSXML *result;
+ JSXML *kid;
+ JSXMLArrayCursor cursor;
+
+} JSXMLFilter;
+
+static void
+xmlfilter_trace(JSTracer *trc, JSObject *obj)
+{
+ JSXMLFilter *filter;
+
+ filter = (JSXMLFilter *) JS_GetPrivate(trc->context, obj);
+ if (!filter)
+ return;
+
+ JS_ASSERT(filter->list);
+ JS_CALL_TRACER(trc, filter->list, JSTRACE_XML, "list");
+ if (filter->result)
+ JS_CALL_TRACER(trc, filter->result, JSTRACE_XML, "result");
+ if (filter->kid)
+ JS_CALL_TRACER(trc, filter->kid, JSTRACE_XML, "kid");
+
+ /*
+ * We do not need to trace the cursor as that would be done when
+ * tracing the filter->list.
+ */
+}
+
+static void
+xmlfilter_finalize(JSContext *cx, JSObject *obj)
+{
+ JSXMLFilter *filter;
+
+ filter = (JSXMLFilter *) JS_GetPrivate(cx, obj);
+ if (!filter)
+ return;
+
+ XMLArrayCursorFinish(&filter->cursor);
+ JS_free(cx, filter);
+}
+
+JSClass js_XMLFilterClass = {
+ "XMLFilter",
+ JSCLASS_HAS_PRIVATE |
+ JSCLASS_IS_ANONYMOUS |
+ JSCLASS_MARK_IS_TRACE |
+ JSCLASS_HAS_CACHED_PROTO(JSProto_XMLFilter),
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, xmlfilter_finalize,
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, JS_CLASS_TRACE(xmlfilter_trace), NULL
+};
+
+JSObject *
+js_InitXMLFilterClass(JSContext *cx, JSObject *obj)
+{
+ JSObject *proto;
+
+ proto = JS_InitClass(cx, obj, NULL, &js_XMLFilterClass, NULL, 0, NULL,
+ NULL, NULL, NULL);
+ if (!proto)
+ return NULL;
+
+ OBJ_CLEAR_PROTO(cx, proto);
+ return proto;
+}
+
+JSBool
+js_StepXMLListFilter(JSContext *cx, JSBool initialized)
+{
+ jsval *sp;
+ JSObject *obj, *filterobj, *resobj, *kidobj;
+ JSXML *xml, *list;
+ JSXMLFilter *filter;
+
+ sp = cx->fp->regs->sp;
+ if (!initialized) {
+ /*
+ * We haven't iterated yet, so initialize the filter based on the
+ * value stored in sp[-2].
+ */
+ if (!VALUE_IS_XML(cx, sp[-2])) {
+ js_ReportValueError(cx, JSMSG_NON_XML_FILTER, -2, sp[-2], NULL);
+ return JS_FALSE;
+ }
+ obj = JSVAL_TO_OBJECT(sp[-2]);
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+
+ if (xml->xml_class == JSXML_CLASS_LIST) {
+ list = xml;
+ } else {
+ obj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!obj)
+ return JS_FALSE;
+
+ /*
+ * Root just-created obj. sp[-2] cannot be used yet for rooting
+ * as it may be the only root holding xml.
+ */
+ sp[-1] = OBJECT_TO_JSVAL(obj);
+ list = (JSXML *) JS_GetPrivate(cx, obj);
+ if (!Append(cx, list, xml))
+ return JS_FALSE;
+ }
+
+ filterobj = js_NewObject(cx, &js_XMLFilterClass, NULL, NULL, 0);
+ if (!filterobj)
+ return JS_FALSE;
+
+ filter = (JSXMLFilter *) JS_malloc(cx, sizeof *filter);
+ if (!filter)
+ return JS_FALSE;
+
+ /*
+ * Init all filter fields before JS_SetPrivate exposes it to
+ * xmlfilter_trace or xmlfilter_finalize.
+ */
+ filter->list = list;
+ filter->result = NULL;
+ filter->kid = NULL;
+ XMLArrayCursorInit(&filter->cursor, &list->xml_kids);
+ JS_SetPrivate(cx, filterobj, filter);
+
+ /* Store filterobj to use in the later iterations. */
+ sp[-2] = OBJECT_TO_JSVAL(filterobj);
+
+ resobj = js_NewXMLObject(cx, JSXML_CLASS_LIST);
+ if (!resobj)
+ return JS_FALSE;
+
+ /* This also roots resobj. */
+ filter->result = (JSXML *) JS_GetPrivate(cx, resobj);
+ } else {
+ /* We have iterated at least once. */
+ JS_ASSERT(!JSVAL_IS_PRIMITIVE(sp[-2]));
+ JS_ASSERT(OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(sp[-2])) ==
+ &js_XMLFilterClass);
+ filter = (JSXMLFilter *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(sp[-2]));
+ JS_ASSERT(filter->kid);
+
+ /* Check if the filter expression wants to append the element. */
+ if (js_ValueToBoolean(sp[-1]) &&
+ !Append(cx, filter->result, filter->kid)) {
+ return JS_FALSE;
+ }
+ }
+
+ /* Do the iteration. */
+ filter->kid = (JSXML *) XMLArrayCursorNext(&filter->cursor);
+ if (!filter->kid) {
+ /*
+ * Do not defer finishing the cursor until the next GC cycle to avoid
+ * accumulation of dead cursors associated with filter->list.
+ */
+ XMLArrayCursorFinish(&filter->cursor);
+ JS_ASSERT(filter->result->object);
+ sp[-2] = OBJECT_TO_JSVAL(filter->result->object);
+ kidobj = NULL;
+ } else {
+ kidobj = js_GetXMLObject(cx, filter->kid);
+ if (!kidobj)
+ return JS_FALSE;
+ }
+
+ /* Null as kidobj at sp[-1] signals filter termination. */
+ sp[-1] = OBJECT_TO_JSVAL(kidobj);
+ return JS_TRUE;
+}
+
+JSObject *
+js_ValueToXMLObject(JSContext *cx, jsval v)
+{
+ return ToXML(cx, v);
+}
+
+JSObject *
+js_ValueToXMLListObject(JSContext *cx, jsval v)
+{
+ return ToXMLList(cx, v);
+}
+
+JSObject *
+js_CloneXMLObject(JSContext *cx, JSObject *obj)
+{
+ uintN flags;
+ JSXML *xml;
+
+ if (!GetXMLSettingFlags(cx, &flags))
+ return NULL;
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (flags & (XSF_IGNORE_COMMENTS |
+ XSF_IGNORE_PROCESSING_INSTRUCTIONS |
+ XSF_IGNORE_WHITESPACE)) {
+ xml = DeepCopy(cx, xml, NULL, flags);
+ if (!xml)
+ return NULL;
+ return xml->object;
+ }
+ return NewXMLObject(cx, xml);
+}
+
+JSObject *
+js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name,
+ JSString *value)
+{
+ uintN flags;
+ JSObject *obj;
+ JSXML *xml;
+ JSObject *qn;
+
+ if (!GetXMLSettingFlags(cx, &flags))
+ return NULL;
+
+ if ((xml_class == JSXML_CLASS_COMMENT &&
+ (flags & XSF_IGNORE_COMMENTS)) ||
+ (xml_class == JSXML_CLASS_PROCESSING_INSTRUCTION &&
+ (flags & XSF_IGNORE_PROCESSING_INSTRUCTIONS))) {
+ return js_NewXMLObject(cx, JSXML_CLASS_TEXT);
+ }
+
+ obj = js_NewXMLObject(cx, xml_class);
+ if (!obj)
+ return NULL;
+ xml = (JSXML *) JS_GetPrivate(cx, obj);
+ if (name) {
+ qn = NewXMLQName(cx, cx->runtime->emptyString, NULL, name);
+ if (!qn)
+ return NULL;
+ xml->name = qn;
+ }
+ xml->xml_value = value;
+ return obj;
+}
+
+JSString *
+js_MakeXMLCDATAString(JSContext *cx, JSString *str)
+{
+ return MakeXMLCDATAString(cx, NULL, str);
+}
+
+JSString *
+js_MakeXMLCommentString(JSContext *cx, JSString *str)
+{
+ return MakeXMLCommentString(cx, NULL, str);
+}
+
+JSString *
+js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str)
+{
+ return MakeXMLPIString(cx, NULL, name, str);
+}
+
+#endif /* JS_HAS_XML_SUPPORT */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/jsxml.h b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.h
new file mode 100644
index 0000000..6952efc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/jsxml.h
@@ -0,0 +1,298 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey E4X code, released August, 2004.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsxml_h___
+#define jsxml_h___
+
+#include "jsstddef.h"
+#include "jspubtd.h"
+
+JS_BEGIN_EXTERN_C
+
+extern const char js_AnyName_str[];
+extern const char js_AttributeName_str[];
+extern const char js_isXMLName_str[];
+extern const char js_XMLList_str[];
+
+extern const char js_amp_entity_str[];
+extern const char js_gt_entity_str[];
+extern const char js_lt_entity_str[];
+extern const char js_quot_entity_str[];
+
+typedef JSBool
+(* JSIdentityOp)(const void *a, const void *b);
+
+struct JSXMLArray {
+ uint32 length;
+ uint32 capacity;
+ void **vector;
+ JSXMLArrayCursor *cursors;
+};
+
+#define JSXML_PRESET_CAPACITY JS_BIT(31)
+#define JSXML_CAPACITY_MASK JS_BITMASK(31)
+#define JSXML_CAPACITY(array) ((array)->capacity & JSXML_CAPACITY_MASK)
+
+struct JSXMLArrayCursor {
+ JSXMLArray *array;
+ uint32 index;
+ JSXMLArrayCursor *next;
+ JSXMLArrayCursor **prevp;
+ void *root;
+};
+
+/*
+ * NB: don't reorder this enum without changing all array initializers that
+ * depend on it in jsxml.c.
+ */
+typedef enum JSXMLClass {
+ JSXML_CLASS_LIST,
+ JSXML_CLASS_ELEMENT,
+ JSXML_CLASS_ATTRIBUTE,
+ JSXML_CLASS_PROCESSING_INSTRUCTION,
+ JSXML_CLASS_TEXT,
+ JSXML_CLASS_COMMENT,
+ JSXML_CLASS_LIMIT
+} JSXMLClass;
+
+#define JSXML_CLASS_HAS_KIDS(class_) ((class_) < JSXML_CLASS_ATTRIBUTE)
+#define JSXML_CLASS_HAS_VALUE(class_) ((class_) >= JSXML_CLASS_ATTRIBUTE)
+#define JSXML_CLASS_HAS_NAME(class_) \
+ ((uintN)((class_) - JSXML_CLASS_ELEMENT) <= \
+ (uintN)(JSXML_CLASS_PROCESSING_INSTRUCTION - JSXML_CLASS_ELEMENT))
+
+#ifdef DEBUG_notme
+#include "jsclist.h"
+#endif
+
+typedef struct JSXMLListVar {
+ JSXMLArray kids; /* NB: must come first */
+ JSXML *target;
+ JSObject *targetprop;
+} JSXMLListVar;
+
+typedef struct JSXMLElemVar {
+ JSXMLArray kids; /* NB: must come first */
+ JSXMLArray namespaces;
+ JSXMLArray attrs;
+} JSXMLElemVar;
+
+struct JSXML {
+#ifdef DEBUG_notme
+ JSCList links;
+ uint32 serial;
+#endif
+ JSObject *object;
+ void *domnode; /* DOM node if mapped info item */
+ JSXML *parent;
+ JSObject *name;
+ uint16 xml_class; /* discriminates u, below */
+ uint16 xml_flags; /* flags, see below */
+ union {
+ JSXMLListVar list;
+ JSXMLElemVar elem;
+ JSString *value;
+ } u;
+
+ /* Don't add anything after u -- see js_NewXML for why. */
+};
+
+/* union member shorthands */
+#define xml_kids u.list.kids
+#define xml_target u.list.target
+#define xml_targetprop u.list.targetprop
+#define xml_namespaces u.elem.namespaces
+#define xml_attrs u.elem.attrs
+#define xml_value u.value
+
+/* xml_flags values */
+#define XMLF_WHITESPACE_TEXT 0x1
+
+/* xml_class-testing macros */
+#define JSXML_HAS_KIDS(xml) JSXML_CLASS_HAS_KIDS((xml)->xml_class)
+#define JSXML_HAS_VALUE(xml) JSXML_CLASS_HAS_VALUE((xml)->xml_class)
+#define JSXML_HAS_NAME(xml) JSXML_CLASS_HAS_NAME((xml)->xml_class)
+#define JSXML_LENGTH(xml) (JSXML_CLASS_HAS_KIDS((xml)->xml_class) \
+ ? (xml)->xml_kids.length \
+ : 0)
+
+extern JSXML *
+js_NewXML(JSContext *cx, JSXMLClass xml_class);
+
+extern void
+js_TraceXML(JSTracer *trc, JSXML *xml);
+
+extern void
+js_FinalizeXML(JSContext *cx, JSXML *xml);
+
+extern JSObject *
+js_ParseNodeToXMLObject(JSContext *cx, JSParseContext *pc, JSParseNode *pn);
+
+extern JSObject *
+js_NewXMLObject(JSContext *cx, JSXMLClass xml_class);
+
+extern JSObject *
+js_GetXMLObject(JSContext *cx, JSXML *xml);
+
+extern JS_FRIEND_DATA(JSXMLObjectOps) js_XMLObjectOps;
+extern JS_FRIEND_DATA(JSClass) js_XMLClass;
+extern JS_FRIEND_DATA(JSExtendedClass) js_NamespaceClass;
+extern JS_FRIEND_DATA(JSExtendedClass) js_QNameClass;
+extern JS_FRIEND_DATA(JSClass) js_AttributeNameClass;
+extern JS_FRIEND_DATA(JSClass) js_AnyNameClass;
+extern JSClass js_XMLFilterClass;
+
+/*
+ * Macros to test whether an object or a value is of type "xml" (per typeof).
+ * NB: jsobj.h must be included before any call to OBJECT_IS_XML, and jsapi.h
+ * and jsobj.h must be included before any call to VALUE_IS_XML.
+ */
+#define OBJECT_IS_XML(cx,obj) ((obj)->map->ops == &js_XMLObjectOps.base)
+#define VALUE_IS_XML(cx,v) (!JSVAL_IS_PRIMITIVE(v) && \
+ OBJECT_IS_XML(cx, JSVAL_TO_OBJECT(v)))
+
+extern JSObject *
+js_InitNamespaceClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitQNameClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitAttributeNameClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitAnyNameClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitXMLClass(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_InitXMLClasses(JSContext *cx, JSObject *obj);
+
+extern JSBool
+js_GetFunctionNamespace(JSContext *cx, jsval *vp);
+
+/*
+ * If obj is QName corresponding to function::name, set *funidp to name's id,
+ * otherwise set *funidp to 0.
+ */
+JSBool
+js_IsFunctionQName(JSContext *cx, JSObject *obj, jsid *funidp);
+
+extern JSBool
+js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp);
+
+extern JSBool
+js_SetDefaultXMLNamespace(JSContext *cx, jsval v);
+
+/*
+ * Return true if v is a XML QName object, or if it converts to a string that
+ * contains a valid XML qualified name (one containing no :), false otherwise.
+ * NB: This function is an infallible predicate, it hides exceptions.
+ */
+extern JSBool
+js_IsXMLName(JSContext *cx, jsval v);
+
+extern JSBool
+js_ToAttributeName(JSContext *cx, jsval *vp);
+
+extern JSString *
+js_EscapeAttributeValue(JSContext *cx, JSString *str, JSBool quote);
+
+extern JSString *
+js_AddAttributePart(JSContext *cx, JSBool isName, JSString *str,
+ JSString *str2);
+
+extern JSString *
+js_EscapeElementValue(JSContext *cx, JSString *str);
+
+extern JSString *
+js_ValueToXMLString(JSContext *cx, jsval v);
+
+extern JSObject *
+js_ConstructXMLQNameObject(JSContext *cx, jsval nsval, jsval lnval);
+
+extern JSBool
+js_GetAnyName(JSContext *cx, jsval *vp);
+
+/*
+ * Note: nameval must be either QName, AttributeName, or AnyName.
+ */
+extern JSBool
+js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp);
+
+extern JSBool
+js_GetXMLFunction(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
+
+extern JSBool
+js_GetXMLDescendants(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+
+extern JSBool
+js_DeleteXMLListElements(JSContext *cx, JSObject *listobj);
+
+extern JSObject *
+js_InitXMLFilterClass(JSContext *cx, JSObject* obj);
+
+extern JSBool
+js_StepXMLListFilter(JSContext *cx, JSBool initialized);
+
+extern JSObject *
+js_ValueToXMLObject(JSContext *cx, jsval v);
+
+extern JSObject *
+js_ValueToXMLListObject(JSContext *cx, jsval v);
+
+extern JSObject *
+js_CloneXMLObject(JSContext *cx, JSObject *obj);
+
+extern JSObject *
+js_NewXMLSpecialObject(JSContext *cx, JSXMLClass xml_class, JSString *name,
+ JSString *value);
+
+extern JSString *
+js_MakeXMLCDATAString(JSContext *cx, JSString *str);
+
+extern JSString *
+js_MakeXMLCommentString(JSContext *cx, JSString *str);
+
+extern JSString *
+js_MakeXMLPIString(JSContext *cx, JSString *name, JSString *str);
+
+JS_END_EXTERN_C
+
+#endif /* jsxml_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s b/tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s
new file mode 100644
index 0000000..6feb202
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/lock_SunOS.s
@@ -0,0 +1,119 @@
+!
+! ***** BEGIN LICENSE BLOCK *****
+! Version: MPL 1.1/GPL 2.0/LGPL 2.1
+!
+! The contents of this file are subject to the Mozilla Public License Version
+! 1.1 (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.mozilla.org/MPL/
+!
+! Software distributed under the License is distributed on an "AS IS" basis,
+! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+! for the specific language governing rights and limitations under the
+! License.
+!
+! The Original Code is Mozilla Communicator client code, released
+! March 31, 1998.
+!
+! The Initial Developer of the Original Code is
+! Netscape Communications Corporation.
+! Portions created by the Initial Developer are Copyright (C) 1998-1999
+! the Initial Developer. All Rights Reserved.
+!
+! Contributor(s):
+!
+! Alternatively, the contents of this file may be used under the terms of
+! either the GNU General Public License Version 2 or later (the "GPL"), or
+! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+! in which case the provisions of the GPL or the LGPL are applicable instead
+! of those above. If you wish to allow use of your version of this file only
+! under the terms of either the GPL or the LGPL, and not to allow others to
+! use your version of this file under the terms of the MPL, indicate your
+! decision by deleting the provisions above and replace them with the notice
+! and other provisions required by the GPL or the LGPL. If you do not delete
+! the provisions above, a recipient may use your version of this file under
+! the terms of any one of the MPL, the GPL or the LGPL.
+!
+! ***** END LICENSE BLOCK *****
+
+!
+! atomic compare-and-swap routines for V8 sparc
+! and for V8+ (ultrasparc)
+!
+!
+! standard asm linkage macros; this module must be compiled
+! with the -P option (use C preprocessor)
+
+#include <sys/asm_linkage.h>
+
+! ======================================================================
+!
+! Perform the sequence *a = b atomically with respect to previous value
+! of a (a0). If *a==a0 then assign *a to b, all in one atomic operation.
+! Returns 1 if assignment happened, and 0 otherwise.
+!
+! usage : old_val = compare_and_swap(address, oldval, newval)
+!
+! -----------------------
+! Note on REGISTER USAGE:
+! as this is a LEAF procedure, a new stack frame is not created;
+! we use the caller stack frame so what would normally be %i (input)
+! registers are actually %o (output registers). Also, we must not
+! overwrite the contents of %l (local) registers as they are not
+! assumed to be volatile during calls.
+!
+! So, the registers used are:
+! %o0 [input] - the address of the value to increment
+! %o1 [input] - the old value to compare with
+! %o2 [input] - the new value to set for [%o0]
+! %o3 [local] - work register
+! -----------------------
+#ifndef ULTRA_SPARC
+! v8
+
+ ENTRY(compare_and_swap) ! standard assembler/ELF prologue
+
+ stbar
+ mov -1,%o3 ! busy flag
+ swap [%o0],%o3 ! get current value
+l1: cmp %o3,-1 ! busy?
+ be,a l1 ! if so, spin
+ swap [%o0],%o3 ! using branch-delay to swap back value
+ cmp %o1,%o3 ! compare old with current
+ be,a l2 ! if equal then swap in new value
+ swap [%o0],%o2 ! done.
+ swap [%o0],%o3 ! otherwise, swap back current value
+ retl
+ mov 0,%o0 ! return false
+l2: retl
+ mov 1,%o0 ! return true
+
+ SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+#else /* ULTRA_SPARC */
+! ======================================================================
+!
+! v9
+
+ ENTRY(compare_and_swap) ! standard assembler/ELF prologue
+
+ stbar
+ cas [%o0],%o1,%o2 ! compare *w with old value and set to new if equal
+ cmp %o1,%o2 ! did we succeed?
+ be,a m1 ! yes
+ mov 1,%o0 ! return true (annulled when no jump)
+ mov 0,%o0 ! return false
+m1: retl
+ nop
+
+ SET_SIZE(compare_and_swap) ! standard assembler/ELF epilogue
+
+!
+! end
+!
+! ======================================================================
+!
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d
new file mode 100644
index 0000000..31ad136
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/editline.d
@@ -0,0 +1 @@
+../obj/editline/editline.o: editline.c editline.h unix.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.a b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.a
new file mode 100644
index 0000000..18c6db8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/libedit.a
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d
new file mode 100644
index 0000000..4a0da6f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/editline/sysunix.d
@@ -0,0 +1 @@
+../obj/editline/sysunix.o: sysunix.c editline.h unix.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js b/tools/node_modules/expresso/deps/jscoverage/js/obj/js
new file mode 100755
index 0000000..cd46434
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h
new file mode 100644
index 0000000..600253e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_config_h___
+#define js_config_h___
+
+/* Definitions set at build time that affect SpiderMonkey's public API.
+ This header file is generated by the SpiderMonkey configure script,
+ and installed along with jsapi.h. */
+
+/* Define to 1 if SpiderMonkey should support multi-threaded clients. */
+#undef JS_THREADSAFE
+
+/* Define to 1 if SpiderMonkey should support the ability to perform
+ entirely too much GC. */
+#undef JS_GC_ZEAL
+
+#endif /* js_config_h___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js-config.h.stamp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/js.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/js.d
new file mode 100644
index 0000000..65fab29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/js.d
@@ -0,0 +1,7 @@
+obj/js.o: js.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsprf.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h \
+ jsdhash.h jslock.h jsbuiltins.h builtins.tbl jscntxt.h jsclist.h jsgc.h \
+ jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h \
+ jsregexp.h jsstr.h js.msg jsdbgapi.h jsemit.h jsnum.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h jsshell.msg
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d
new file mode 100644
index 0000000..9a6b6c0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsapi.d
@@ -0,0 +1,8 @@
+obj/jsapi.o: jsapi.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsclist.h jsdhash.h jsprf.h \
+ jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h \
+ jsprvtd.h jsatom.h jshash.h jslock.h jsbool.h jsbuiltins.h builtins.tbl \
+ jscntxt.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdate.h jsdtoa.h \
+ jsemit.h jsexn.h jsiter.h jsmath.h jsnum.h json.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h prmjtime.h jsstaticcheck.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d
new file mode 100644
index 0000000..8a77c8c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarena.d
@@ -0,0 +1,2 @@
+obj/jsarena.o: jsarena.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsbit.h jsutil.h jsarena.h jscompat.h jslong.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d
new file mode 100644
index 0000000..ae6af74
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsarray.d
@@ -0,0 +1,7 @@
+obj/jsarray.o: jsarray.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h \
+ jsdhash.h jslock.h jsbit.h jsbool.h jsbuiltins.h builtins.tbl jscntxt.h \
+ jsarena.h jsclist.h jsgc.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h jsdtoa.h \
+ jsnum.h jsscope.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d
new file mode 100644
index 0000000..61fb258
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsatom.d
@@ -0,0 +1,6 @@
+obj/jsatom.o: jsatom.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jshash.h jscompat.h jslong.h jsprf.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsversion.h jsatom.h jsdhash.h jsprvtd.h jslock.h \
+ jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h \
+ jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsnum.h \
+ jsscan.h jskeyword.tbl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h
new file mode 100644
index 0000000..f5b2da8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautocfg.h
@@ -0,0 +1,56 @@
+#ifndef js_cpucfg___
+#define js_cpucfg___
+
+/* AUTOMATICALLY GENERATED - DO NOT EDIT */
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 8L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 8L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 64L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 64L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 6L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 6L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 8L
+#define JS_ALIGN_OF_INT64 8L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 8L
+#define JS_ALIGN_OF_POINTER 8L
+#define JS_ALIGN_OF_WORD 8L
+
+#define JS_BYTES_PER_WORD_LOG2 3L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define JS_WORDS_PER_DWORD_LOG2 0L
+
+#define JS_STACK_GROWTH_DIRECTION (-1)
+
+#define JS_HAVE_LONG_LONG
+
+#define HAVE_VA_LIST_AS_ARRAY 1
+
+#endif /* js_cpucfg___ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h
new file mode 100644
index 0000000..f3d58f9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautokw.h
@@ -0,0 +1,401 @@
+ /*
+ * Generating switch for the list of 61 entries:
+ * break
+ * case
+ * continue
+ * default
+ * delete
+ * do
+ * else
+ * export
+ * false
+ * for
+ * function
+ * if
+ * in
+ * new
+ * null
+ * return
+ * switch
+ * this
+ * true
+ * typeof
+ * var
+ * void
+ * while
+ * with
+ * const
+ * try
+ * catch
+ * finally
+ * throw
+ * instanceof
+ * abstract
+ * boolean
+ * byte
+ * char
+ * class
+ * double
+ * extends
+ * final
+ * float
+ * goto
+ * implements
+ * import
+ * int
+ * interface
+ * long
+ * native
+ * package
+ * private
+ * protected
+ * public
+ * short
+ * static
+ * super
+ * synchronized
+ * throws
+ * transient
+ * volatile
+ * enum
+ * debugger
+ * yield
+ * let
+ */
+ switch (JSKW_LENGTH()) {
+ case 2:
+ if (JSKW_AT(0) == 'd') {
+ if (JSKW_AT(1)=='o') {
+ JSKW_GOT_MATCH(5) /* do */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'i') {
+ if (JSKW_AT(1) == 'f') {
+ JSKW_GOT_MATCH(11) /* if */
+ }
+ if (JSKW_AT(1) == 'n') {
+ JSKW_GOT_MATCH(12) /* in */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 3:
+ switch (JSKW_AT(2)) {
+ case 'r':
+ if (JSKW_AT(0) == 'f') {
+ if (JSKW_AT(1)=='o') {
+ JSKW_GOT_MATCH(9) /* for */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'v') {
+ if (JSKW_AT(1)=='a') {
+ JSKW_GOT_MATCH(20) /* var */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 't':
+ if (JSKW_AT(0) == 'i') {
+ if (JSKW_AT(1)=='n') {
+ JSKW_GOT_MATCH(42) /* int */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'l') {
+ if (JSKW_AT(1)=='e') {
+ JSKW_GOT_MATCH(60) /* let */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'w':
+ if (JSKW_AT(0)=='n' && JSKW_AT(1)=='e') {
+ JSKW_GOT_MATCH(13) /* new */
+ }
+ JSKW_NO_MATCH()
+ case 'y':
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='r') {
+ JSKW_GOT_MATCH(25) /* try */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 4:
+ switch (JSKW_AT(3)) {
+ case 'd':
+ if (JSKW_AT(0)=='v' && JSKW_AT(1)=='o' && JSKW_AT(2)=='i') {
+ JSKW_GOT_MATCH(21) /* void */
+ }
+ JSKW_NO_MATCH()
+ case 'e':
+ if (JSKW_AT(2) == 's') {
+ if (JSKW_AT(0) == 'c') {
+ if (JSKW_AT(1)=='a') {
+ JSKW_GOT_MATCH(1) /* case */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'e') {
+ if (JSKW_AT(1)=='l') {
+ JSKW_GOT_MATCH(6) /* else */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(2) == 't') {
+ if (JSKW_AT(0)=='b' && JSKW_AT(1)=='y') {
+ JSKW_GOT_MATCH(32) /* byte */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(2) == 'u') {
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='r') {
+ JSKW_GOT_MATCH(18) /* true */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'g':
+ if (JSKW_AT(0)=='l' && JSKW_AT(1)=='o' && JSKW_AT(2)=='n') {
+ JSKW_GOT_MATCH(44) /* long */
+ }
+ JSKW_NO_MATCH()
+ case 'h':
+ if (JSKW_AT(0)=='w' && JSKW_AT(1)=='i' && JSKW_AT(2)=='t') {
+ JSKW_GOT_MATCH(23) /* with */
+ }
+ JSKW_NO_MATCH()
+ case 'l':
+ if (JSKW_AT(0)=='n' && JSKW_AT(1)=='u' && JSKW_AT(2)=='l') {
+ JSKW_GOT_MATCH(14) /* null */
+ }
+ JSKW_NO_MATCH()
+ case 'm':
+ if (JSKW_AT(0)=='e' && JSKW_AT(1)=='n' && JSKW_AT(2)=='u') {
+ JSKW_GOT_MATCH(57) /* enum */
+ }
+ JSKW_NO_MATCH()
+ case 'o':
+ if (JSKW_AT(0)=='g' && JSKW_AT(1)=='o' && JSKW_AT(2)=='t') {
+ JSKW_GOT_MATCH(39) /* goto */
+ }
+ JSKW_NO_MATCH()
+ case 'r':
+ if (JSKW_AT(0)=='c' && JSKW_AT(1)=='h' && JSKW_AT(2)=='a') {
+ JSKW_GOT_MATCH(33) /* char */
+ }
+ JSKW_NO_MATCH()
+ case 's':
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='h' && JSKW_AT(2)=='i') {
+ JSKW_GOT_MATCH(17) /* this */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 5:
+ switch (JSKW_AT(3)) {
+ case 'a':
+ if (JSKW_AT(0) == 'b') {
+ if (JSKW_AT(4)=='k' && JSKW_AT(1)=='r' && JSKW_AT(2)=='e') {
+ JSKW_GOT_MATCH(0) /* break */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'f') {
+ if (JSKW_AT(4) == 'l') {
+ if (JSKW_AT(2)=='n' && JSKW_AT(1)=='i') {
+ JSKW_GOT_MATCH(37) /* final */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(4) == 't') {
+ if (JSKW_AT(2)=='o' && JSKW_AT(1)=='l') {
+ JSKW_GOT_MATCH(38) /* float */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'c':
+ if (JSKW_AT(0)=='c' && JSKW_AT(1)=='a' && JSKW_AT(2)=='t' && JSKW_AT(4)=='h') {
+ JSKW_GOT_MATCH(26) /* catch */
+ }
+ JSKW_NO_MATCH()
+ case 'e':
+ if (JSKW_AT(0)=='s' && JSKW_AT(1)=='u' && JSKW_AT(2)=='p' && JSKW_AT(4)=='r') {
+ JSKW_GOT_MATCH(52) /* super */
+ }
+ JSKW_NO_MATCH()
+ case 'l':
+ if (JSKW_AT(0) == 'w') {
+ if (JSKW_AT(4)=='e' && JSKW_AT(1)=='h' && JSKW_AT(2)=='i') {
+ JSKW_GOT_MATCH(22) /* while */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'y') {
+ if (JSKW_AT(4)=='d' && JSKW_AT(1)=='i' && JSKW_AT(2)=='e') {
+ JSKW_GOT_MATCH(59) /* yield */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'o':
+ if (JSKW_AT(0)=='t' && JSKW_AT(1)=='h' && JSKW_AT(2)=='r' && JSKW_AT(4)=='w') {
+ JSKW_GOT_MATCH(28) /* throw */
+ }
+ JSKW_NO_MATCH()
+ case 'r':
+ if (JSKW_AT(0)=='s' && JSKW_AT(1)=='h' && JSKW_AT(2)=='o' && JSKW_AT(4)=='t') {
+ JSKW_GOT_MATCH(50) /* short */
+ }
+ JSKW_NO_MATCH()
+ case 's':
+ if (JSKW_AT(0) == 'c') {
+ if (JSKW_AT(4) == 's') {
+ if (JSKW_AT(2)=='a' && JSKW_AT(1)=='l') {
+ JSKW_GOT_MATCH(34) /* class */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(4) == 't') {
+ if (JSKW_AT(2)=='n' && JSKW_AT(1)=='o') {
+ JSKW_GOT_MATCH(24) /* const */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(0) == 'f') {
+ if (JSKW_AT(4)=='e' && JSKW_AT(1)=='a' && JSKW_AT(2)=='l') {
+ JSKW_GOT_MATCH(8) /* false */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 6:
+ switch (JSKW_AT(0)) {
+ case 'd':
+ if (JSKW_AT(1) == 'o') {
+ if (JSKW_AT(5)=='e' && JSKW_AT(4)=='l' && JSKW_AT(2)=='u' && JSKW_AT(3)=='b') {
+ JSKW_GOT_MATCH(35) /* double */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(1) == 'e') {
+ if (JSKW_AT(5)=='e' && JSKW_AT(4)=='t' && JSKW_AT(2)=='l' && JSKW_AT(3)=='e') {
+ JSKW_GOT_MATCH(4) /* delete */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 'e':
+ JSKW_TEST_GUESS(7) /* export */
+ case 'i':
+ JSKW_TEST_GUESS(41) /* import */
+ case 'n':
+ JSKW_TEST_GUESS(45) /* native */
+ case 'p':
+ JSKW_TEST_GUESS(49) /* public */
+ case 'r':
+ JSKW_TEST_GUESS(15) /* return */
+ case 's':
+ if (JSKW_AT(1) == 't') {
+ if (JSKW_AT(5)=='c' && JSKW_AT(4)=='i' && JSKW_AT(2)=='a' && JSKW_AT(3)=='t') {
+ JSKW_GOT_MATCH(51) /* static */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(1) == 'w') {
+ if (JSKW_AT(5)=='h' && JSKW_AT(4)=='c' && JSKW_AT(2)=='i' && JSKW_AT(3)=='t') {
+ JSKW_GOT_MATCH(16) /* switch */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 't':
+ if (JSKW_AT(5) == 'f') {
+ if (JSKW_AT(4)=='o' && JSKW_AT(1)=='y' && JSKW_AT(2)=='p' && JSKW_AT(3)=='e') {
+ JSKW_GOT_MATCH(19) /* typeof */
+ }
+ JSKW_NO_MATCH()
+ }
+ if (JSKW_AT(5) == 's') {
+ if (JSKW_AT(4)=='w' && JSKW_AT(1)=='h' && JSKW_AT(2)=='r' && JSKW_AT(3)=='o') {
+ JSKW_GOT_MATCH(54) /* throws */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 7:
+ switch (JSKW_AT(0)) {
+ case 'b':
+ JSKW_TEST_GUESS(31) /* boolean */
+ case 'd':
+ JSKW_TEST_GUESS(3) /* default */
+ case 'e':
+ JSKW_TEST_GUESS(36) /* extends */
+ case 'f':
+ JSKW_TEST_GUESS(27) /* finally */
+ case 'p':
+ if (JSKW_AT(1) == 'a') {
+ JSKW_TEST_GUESS(46) /* package */
+ }
+ if (JSKW_AT(1) == 'r') {
+ JSKW_TEST_GUESS(47) /* private */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 8:
+ switch (JSKW_AT(4)) {
+ case 'g':
+ JSKW_TEST_GUESS(58) /* debugger */
+ case 'i':
+ JSKW_TEST_GUESS(2) /* continue */
+ case 'r':
+ JSKW_TEST_GUESS(30) /* abstract */
+ case 't':
+ if (JSKW_AT(1) == 'o') {
+ JSKW_TEST_GUESS(56) /* volatile */
+ }
+ if (JSKW_AT(1) == 'u') {
+ JSKW_TEST_GUESS(10) /* function */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 9:
+ if (JSKW_AT(1) == 'n') {
+ JSKW_TEST_GUESS(43) /* interface */
+ }
+ if (JSKW_AT(1) == 'r') {
+ if (JSKW_AT(0) == 'p') {
+ JSKW_TEST_GUESS(48) /* protected */
+ }
+ if (JSKW_AT(0) == 't') {
+ JSKW_TEST_GUESS(55) /* transient */
+ }
+ JSKW_NO_MATCH()
+ }
+ JSKW_NO_MATCH()
+ case 10:
+ if (JSKW_AT(1) == 'n') {
+ JSKW_TEST_GUESS(29) /* instanceof */
+ }
+ if (JSKW_AT(1) == 'm') {
+ JSKW_TEST_GUESS(40) /* implements */
+ }
+ JSKW_NO_MATCH()
+ case 12:
+ JSKW_TEST_GUESS(53) /* synchronized */
+ }
+ JSKW_NO_MATCH()
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h
new file mode 100644
index 0000000..136defe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsautooplen.h
@@ -0,0 +1,237 @@
+/*
+ * Automatically generated header with JS opcode length constants.
+ *
+ * Do not edit it, alter jsopcode.tbl instead.
+ */
+#define JSOP_INTERRUPT_LENGTH 1
+#define JSOP_PUSH_LENGTH 1
+#define JSOP_POPV_LENGTH 1
+#define JSOP_ENTERWITH_LENGTH 1
+#define JSOP_LEAVEWITH_LENGTH 1
+#define JSOP_RETURN_LENGTH 1
+#define JSOP_GOTO_LENGTH 3
+#define JSOP_IFEQ_LENGTH 3
+#define JSOP_IFNE_LENGTH 3
+#define JSOP_ARGUMENTS_LENGTH 1
+#define JSOP_FORARG_LENGTH 3
+#define JSOP_FORLOCAL_LENGTH 3
+#define JSOP_DUP_LENGTH 1
+#define JSOP_DUP2_LENGTH 1
+#define JSOP_SETCONST_LENGTH 3
+#define JSOP_BITOR_LENGTH 1
+#define JSOP_BITXOR_LENGTH 1
+#define JSOP_BITAND_LENGTH 1
+#define JSOP_EQ_LENGTH 1
+#define JSOP_NE_LENGTH 1
+#define JSOP_LT_LENGTH 1
+#define JSOP_LE_LENGTH 1
+#define JSOP_GT_LENGTH 1
+#define JSOP_GE_LENGTH 1
+#define JSOP_LSH_LENGTH 1
+#define JSOP_RSH_LENGTH 1
+#define JSOP_URSH_LENGTH 1
+#define JSOP_ADD_LENGTH 1
+#define JSOP_SUB_LENGTH 1
+#define JSOP_MUL_LENGTH 1
+#define JSOP_DIV_LENGTH 1
+#define JSOP_MOD_LENGTH 1
+#define JSOP_NOT_LENGTH 1
+#define JSOP_BITNOT_LENGTH 1
+#define JSOP_NEG_LENGTH 1
+#define JSOP_NEW_LENGTH 3
+#define JSOP_DELNAME_LENGTH 3
+#define JSOP_DELPROP_LENGTH 3
+#define JSOP_DELELEM_LENGTH 1
+#define JSOP_TYPEOF_LENGTH 1
+#define JSOP_VOID_LENGTH 1
+#define JSOP_INCNAME_LENGTH 3
+#define JSOP_INCPROP_LENGTH 3
+#define JSOP_INCELEM_LENGTH 1
+#define JSOP_DECNAME_LENGTH 3
+#define JSOP_DECPROP_LENGTH 3
+#define JSOP_DECELEM_LENGTH 1
+#define JSOP_NAMEINC_LENGTH 3
+#define JSOP_PROPINC_LENGTH 3
+#define JSOP_ELEMINC_LENGTH 1
+#define JSOP_NAMEDEC_LENGTH 3
+#define JSOP_PROPDEC_LENGTH 3
+#define JSOP_ELEMDEC_LENGTH 1
+#define JSOP_GETPROP_LENGTH 3
+#define JSOP_SETPROP_LENGTH 3
+#define JSOP_GETELEM_LENGTH 1
+#define JSOP_SETELEM_LENGTH 1
+#define JSOP_CALLNAME_LENGTH 3
+#define JSOP_CALL_LENGTH 3
+#define JSOP_NAME_LENGTH 3
+#define JSOP_DOUBLE_LENGTH 3
+#define JSOP_STRING_LENGTH 3
+#define JSOP_ZERO_LENGTH 1
+#define JSOP_ONE_LENGTH 1
+#define JSOP_NULL_LENGTH 1
+#define JSOP_THIS_LENGTH 1
+#define JSOP_FALSE_LENGTH 1
+#define JSOP_TRUE_LENGTH 1
+#define JSOP_OR_LENGTH 3
+#define JSOP_AND_LENGTH 3
+#define JSOP_TABLESWITCH_LENGTH -1
+#define JSOP_LOOKUPSWITCH_LENGTH -1
+#define JSOP_STRICTEQ_LENGTH 1
+#define JSOP_STRICTNE_LENGTH 1
+#define JSOP_NULLTHIS_LENGTH 1
+#define JSOP_ITER_LENGTH 2
+#define JSOP_NEXTITER_LENGTH 1
+#define JSOP_ENDITER_LENGTH 1
+#define JSOP_APPLY_LENGTH 3
+#define JSOP_SWAP_LENGTH 1
+#define JSOP_OBJECT_LENGTH 3
+#define JSOP_POP_LENGTH 1
+#define JSOP_POS_LENGTH 1
+#define JSOP_TRAP_LENGTH 1
+#define JSOP_GETARG_LENGTH 3
+#define JSOP_SETARG_LENGTH 3
+#define JSOP_GETLOCAL_LENGTH 3
+#define JSOP_SETLOCAL_LENGTH 3
+#define JSOP_UINT16_LENGTH 3
+#define JSOP_NEWINIT_LENGTH 2
+#define JSOP_ENDINIT_LENGTH 1
+#define JSOP_INITPROP_LENGTH 3
+#define JSOP_INITELEM_LENGTH 1
+#define JSOP_DEFSHARP_LENGTH 3
+#define JSOP_USESHARP_LENGTH 3
+#define JSOP_INCARG_LENGTH 3
+#define JSOP_DECARG_LENGTH 3
+#define JSOP_ARGINC_LENGTH 3
+#define JSOP_ARGDEC_LENGTH 3
+#define JSOP_INCLOCAL_LENGTH 3
+#define JSOP_DECLOCAL_LENGTH 3
+#define JSOP_LOCALINC_LENGTH 3
+#define JSOP_LOCALDEC_LENGTH 3
+#define JSOP_IMACOP_LENGTH 1
+#define JSOP_FORNAME_LENGTH 3
+#define JSOP_FORPROP_LENGTH 3
+#define JSOP_FORELEM_LENGTH 1
+#define JSOP_POPN_LENGTH 3
+#define JSOP_BINDNAME_LENGTH 3
+#define JSOP_SETNAME_LENGTH 3
+#define JSOP_THROW_LENGTH 1
+#define JSOP_IN_LENGTH 1
+#define JSOP_INSTANCEOF_LENGTH 1
+#define JSOP_DEBUGGER_LENGTH 1
+#define JSOP_GOSUB_LENGTH 3
+#define JSOP_RETSUB_LENGTH 1
+#define JSOP_EXCEPTION_LENGTH 1
+#define JSOP_LINENO_LENGTH 3
+#define JSOP_CONDSWITCH_LENGTH 1
+#define JSOP_CASE_LENGTH 3
+#define JSOP_DEFAULT_LENGTH 3
+#define JSOP_EVAL_LENGTH 3
+#define JSOP_ENUMELEM_LENGTH 1
+#define JSOP_GETTER_LENGTH 1
+#define JSOP_SETTER_LENGTH 1
+#define JSOP_DEFFUN_LENGTH 3
+#define JSOP_DEFCONST_LENGTH 3
+#define JSOP_DEFVAR_LENGTH 3
+#define JSOP_ANONFUNOBJ_LENGTH 3
+#define JSOP_NAMEDFUNOBJ_LENGTH 3
+#define JSOP_SETLOCALPOP_LENGTH 3
+#define JSOP_UNUSED131_LENGTH 1
+#define JSOP_SETCALL_LENGTH 3
+#define JSOP_TRY_LENGTH 1
+#define JSOP_FINALLY_LENGTH 1
+#define JSOP_NOP_LENGTH 1
+#define JSOP_ARGSUB_LENGTH 3
+#define JSOP_ARGCNT_LENGTH 1
+#define JSOP_DEFLOCALFUN_LENGTH 5
+#define JSOP_GOTOX_LENGTH 5
+#define JSOP_IFEQX_LENGTH 5
+#define JSOP_IFNEX_LENGTH 5
+#define JSOP_ORX_LENGTH 5
+#define JSOP_ANDX_LENGTH 5
+#define JSOP_GOSUBX_LENGTH 5
+#define JSOP_CASEX_LENGTH 5
+#define JSOP_DEFAULTX_LENGTH 5
+#define JSOP_TABLESWITCHX_LENGTH -1
+#define JSOP_LOOKUPSWITCHX_LENGTH -1
+#define JSOP_BACKPATCH_LENGTH 3
+#define JSOP_BACKPATCH_POP_LENGTH 3
+#define JSOP_THROWING_LENGTH 1
+#define JSOP_SETRVAL_LENGTH 1
+#define JSOP_RETRVAL_LENGTH 1
+#define JSOP_GETGVAR_LENGTH 3
+#define JSOP_SETGVAR_LENGTH 3
+#define JSOP_INCGVAR_LENGTH 3
+#define JSOP_DECGVAR_LENGTH 3
+#define JSOP_GVARINC_LENGTH 3
+#define JSOP_GVARDEC_LENGTH 3
+#define JSOP_REGEXP_LENGTH 3
+#define JSOP_DEFXMLNS_LENGTH 1
+#define JSOP_ANYNAME_LENGTH 1
+#define JSOP_QNAMEPART_LENGTH 3
+#define JSOP_QNAMECONST_LENGTH 3
+#define JSOP_QNAME_LENGTH 1
+#define JSOP_TOATTRNAME_LENGTH 1
+#define JSOP_TOATTRVAL_LENGTH 1
+#define JSOP_ADDATTRNAME_LENGTH 1
+#define JSOP_ADDATTRVAL_LENGTH 1
+#define JSOP_BINDXMLNAME_LENGTH 1
+#define JSOP_SETXMLNAME_LENGTH 1
+#define JSOP_XMLNAME_LENGTH 1
+#define JSOP_DESCENDANTS_LENGTH 1
+#define JSOP_FILTER_LENGTH 3
+#define JSOP_ENDFILTER_LENGTH 3
+#define JSOP_TOXML_LENGTH 1
+#define JSOP_TOXMLLIST_LENGTH 1
+#define JSOP_XMLTAGEXPR_LENGTH 1
+#define JSOP_XMLELTEXPR_LENGTH 1
+#define JSOP_XMLOBJECT_LENGTH 3
+#define JSOP_XMLCDATA_LENGTH 3
+#define JSOP_XMLCOMMENT_LENGTH 3
+#define JSOP_XMLPI_LENGTH 3
+#define JSOP_CALLPROP_LENGTH 3
+#define JSOP_GETFUNNS_LENGTH 1
+#define JSOP_GETUPVAR_LENGTH 3
+#define JSOP_DELDESC_LENGTH 1
+#define JSOP_UINT24_LENGTH 4
+#define JSOP_INDEXBASE_LENGTH 2
+#define JSOP_RESETBASE_LENGTH 1
+#define JSOP_RESETBASE0_LENGTH 1
+#define JSOP_STARTXML_LENGTH 1
+#define JSOP_STARTXMLEXPR_LENGTH 1
+#define JSOP_CALLELEM_LENGTH 1
+#define JSOP_STOP_LENGTH 1
+#define JSOP_GETXPROP_LENGTH 3
+#define JSOP_CALLXMLNAME_LENGTH 1
+#define JSOP_TYPEOFEXPR_LENGTH 1
+#define JSOP_ENTERBLOCK_LENGTH 3
+#define JSOP_LEAVEBLOCK_LENGTH 3
+#define JSOP_UNUSED201_LENGTH 1
+#define JSOP_UNUSED202_LENGTH 1
+#define JSOP_UNUSED203_LENGTH 1
+#define JSOP_UNUSED204_LENGTH 1
+#define JSOP_UNUSED205_LENGTH 1
+#define JSOP_UNUSED206_LENGTH 1
+#define JSOP_UNUSED207_LENGTH 1
+#define JSOP_UNUSED208_LENGTH 1
+#define JSOP_UNUSED209_LENGTH 1
+#define JSOP_GENERATOR_LENGTH 1
+#define JSOP_YIELD_LENGTH 1
+#define JSOP_ARRAYPUSH_LENGTH 3
+#define JSOP_CALLUPVAR_LENGTH 3
+#define JSOP_ENUMCONSTELEM_LENGTH 1
+#define JSOP_LEAVEBLOCKEXPR_LENGTH 3
+#define JSOP_GETTHISPROP_LENGTH 3
+#define JSOP_GETARGPROP_LENGTH 5
+#define JSOP_GETLOCALPROP_LENGTH 5
+#define JSOP_UNUSED219_LENGTH 1
+#define JSOP_INDEXBASE1_LENGTH 1
+#define JSOP_INDEXBASE2_LENGTH 1
+#define JSOP_INDEXBASE3_LENGTH 1
+#define JSOP_CALLGVAR_LENGTH 3
+#define JSOP_CALLLOCAL_LENGTH 3
+#define JSOP_CALLARG_LENGTH 3
+#define JSOP_UNUSED226_LENGTH 1
+#define JSOP_INT8_LENGTH 2
+#define JSOP_INT32_LENGTH 5
+#define JSOP_LENGTH_LENGTH 1
+#define JSOP_NEWARRAY_LENGTH 4
+#define JSOP_HOLE_LENGTH 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d
new file mode 100644
index 0000000..94638dd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsbool.d
@@ -0,0 +1,6 @@
+obj/jsbool.o: jsbool.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h jslong.h \
+ jsproto.tbl jsversion.h jsatom.h jshash.h jsdhash.h jsprvtd.h jslock.h \
+ jsbool.h jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsnum.h jsprf.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d
new file mode 100644
index 0000000..e0b45c7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscntxt.d
@@ -0,0 +1,7 @@
+obj/jscntxt.o: jscntxt.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsclist.h jsprf.h \
+ jsatom.h jsversion.h jshash.h jsdhash.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsprvtd.h jslock.h jscntxt.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsdbgapi.h jsexn.h jsnum.h jsscan.h jskeyword.tbl \
+ jsscope.h jstracer.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg
new file mode 100755
index 0000000..cbcaa26
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d
new file mode 100644
index 0000000..428ec55
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jscpucfg.d
@@ -0,0 +1 @@
+obj/jscpucfg.o: jscpucfg.cpp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d
new file mode 100644
index 0000000..615e8c8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdate.d
@@ -0,0 +1,6 @@
+obj/jsdate.o: jsdate.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsprf.h prmjtime.h jslong.h jsutil.h jsapi.h obj/js-config.h jspubtd.h \
+ jscompat.h jsproto.tbl jsversion.h jsbuiltins.h builtins.tbl jscntxt.h \
+ jsarena.h jsclist.h jsatom.h jshash.h jsdhash.h jsprvtd.h jslock.h \
+ jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl \
+ jsscript.h jsregexp.h jsstr.h js.msg jsdate.h jsnum.h jsdtoa.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d
new file mode 100644
index 0000000..9d8f92b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdbgapi.d
@@ -0,0 +1,7 @@
+obj/jsdbgapi.o: jsdbgapi.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsclist.h jsapi.h obj/js-config.h jspubtd.h \
+ jscompat.h jslong.h jsproto.tbl jsversion.h jscntxt.h jsarena.h jsatom.h \
+ jshash.h jsdhash.h jsprvtd.h jslock.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdbgapi.h jsemit.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d
new file mode 100644
index 0000000..2ccc9e5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdhash.d
@@ -0,0 +1,2 @@
+obj/jsdhash.o: jsdhash.cpp jsbit.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsdhash.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d
new file mode 100644
index 0000000..a89c019
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsdtoa.d
@@ -0,0 +1,3 @@
+obj/jsdtoa.o: jsdtoa.cpp jsstddef.h jslibmath.h jsversion.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jsdtoa.h jscompat.h jslong.h jsprf.h jsutil.h \
+ jspubtd.h jsproto.tbl jsnum.h jsbit.h dtoa.c
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d
new file mode 100644
index 0000000..ae918e6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsemit.d
@@ -0,0 +1,7 @@
+obj/jsemit.o: jsemit.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsbit.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsatom.h jshash.h \
+ jsdhash.h jsprvtd.h jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsemit.h jsnum.h jsparse.h jsscan.h jskeyword.tbl \
+ jsscope.h obj/jsautooplen.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d
new file mode 100644
index 0000000..8f507d7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsexn.d
@@ -0,0 +1,6 @@
+obj/jsexn.o: jsexn.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsbit.h jsutil.h jsprf.h jsapi.h obj/js-config.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h jscntxt.h jsarena.h jsclist.h jsatom.h \
+ jshash.h jsdhash.h jsprvtd.h jslock.h jsgc.h jsinterp.h jsfun.h jsobj.h \
+ jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h \
+ jsexn.h jsnum.h jsscope.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d
new file mode 100644
index 0000000..6b70eac
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsfun.d
@@ -0,0 +1,7 @@
+obj/jsfun.o: jsfun.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsbit.h jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h jslong.h \
+ jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h \
+ jslock.h jsbuiltins.h builtins.tbl jscntxt.h jsarena.h jsclist.h jsgc.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsdbgapi.h jsemit.h jsnum.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h jsexn.h jsstaticcheck.h jsiter.h jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d
new file mode 100644
index 0000000..4d05348
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsgc.d
@@ -0,0 +1,7 @@
+obj/jsgc.o: jsgc.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jshash.h jscompat.h jslong.h jsbit.h jsclist.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsatom.h jsdhash.h \
+ jsprvtd.h jslock.h jscntxt.h jsarena.h jsgc.h jsinterp.h jsfun.h jsobj.h \
+ jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h \
+ jsexn.h jsiter.h jsnum.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ jstracer.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d
new file mode 100644
index 0000000..55d434e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jshash.d
@@ -0,0 +1,2 @@
+obj/jshash.o: jshash.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsbit.h jsutil.h jshash.h jscompat.h jslong.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d
new file mode 100644
index 0000000..0fc0a96
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinterp.d
@@ -0,0 +1,8 @@
+obj/jsinterp.o: jsinterp.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h \
+ jsatom.h jshash.h jsdhash.h jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h \
+ jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h \
+ jsregexp.h jsstr.h js.msg jsdbgapi.h jsiter.h jsnum.h jsscan.h \
+ jskeyword.tbl jsscope.h jsstaticcheck.h jstracer.h jsxml.h \
+ obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d
new file mode 100644
index 0000000..c8fe979
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsinvoke.d
@@ -0,0 +1,8 @@
+obj/jsinvoke.o: jsinvoke.cpp jsinterp.cpp jsstddef.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h \
+ jsprf.h jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h \
+ jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h jslock.h jsbool.h \
+ jscntxt.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h jsiter.h \
+ jsnum.h jsscan.h jskeyword.tbl jsscope.h jsstaticcheck.h jstracer.h \
+ jsxml.h obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d
new file mode 100644
index 0000000..d8a6eba
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsiter.d
@@ -0,0 +1,6 @@
+obj/jsiter.o: jsiter.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsarena.h jscompat.h jslong.h jsapi.h obj/js-config.h jspubtd.h \
+ jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h \
+ jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsexn.h jsiter.h jsnum.h jsscan.h jskeyword.tbl jsscope.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen
new file mode 100755
index 0000000..274c184
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d
new file mode 100644
index 0000000..c6c2cb4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jskwgen.d
@@ -0,0 +1 @@
+obj/jskwgen: jskwgen.cpp jsstddef.h jsversion.h jskeyword.tbl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d
new file mode 100644
index 0000000..2f0db29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslock.d
@@ -0,0 +1 @@
+obj/jslock.o: jslock.cpp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d
new file mode 100644
index 0000000..57c6194
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslog2.d
@@ -0,0 +1,2 @@
+obj/jslog2.o: jslog2.cpp jsstddef.h jsbit.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d
new file mode 100644
index 0000000..d6cdd4c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jslong.d
@@ -0,0 +1,2 @@
+obj/jslong.o: jslong.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jslong.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d
new file mode 100644
index 0000000..4eacf46
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsmath.d
@@ -0,0 +1,6 @@
+obj/jsmath.o: jsmath.cpp jsstddef.h jslibmath.h jsversion.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jslong.h prmjtime.h jsapi.h obj/js-config.h \
+ jspubtd.h jscompat.h jsproto.tbl jsutil.h jsatom.h jshash.h jsdhash.h \
+ jsprvtd.h jslock.h jsbuiltins.h builtins.tbl jscntxt.h jsarena.h \
+ jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsmath.h jsnum.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d
new file mode 100644
index 0000000..00442d3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsnum.d
@@ -0,0 +1,6 @@
+obj/jsnum.o: jsnum.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jsapi.h obj/js-config.h jspubtd.h jscompat.h jslong.h \
+ jsproto.tbl jsversion.h jsatom.h jshash.h jsdhash.h jsprvtd.h jslock.h \
+ jsbuiltins.h builtins.tbl jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsdtoa.h jsnum.h jsprf.h jsscope.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d
new file mode 100644
index 0000000..c6f20a6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsobj.d
@@ -0,0 +1,8 @@
+obj/jsobj.o: jsobj.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsbit.h jsutil.h jshash.h jsdhash.h \
+ jsprf.h jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h \
+ jsarray.h jsprvtd.h jsatom.h jslock.h jsbool.h jsbuiltins.h builtins.tbl \
+ jscntxt.h jsclist.h jsgc.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsemit.h jsnum.h \
+ jsparse.h jsscan.h jskeyword.tbl jsscope.h jsdbgapi.h jsstaticcheck.h \
+ jsiter.h jsxml.h jsxdrapi.h obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/json.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/json.d
new file mode 100644
index 0000000..ad64d0c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/json.d
@@ -0,0 +1,6 @@
+obj/json.o: json.cpp jsapi.h obj/js-config.h jspubtd.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jscompat.h jslong.h jsproto.tbl jsversion.h \
+ jsutil.h jsarena.h jsarray.h jsprvtd.h jsatom.h jshash.h jsdhash.h \
+ jslock.h jsbool.h jscntxt.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdtoa.h jsiter.h jsnum.h jsprf.h jsscan.h jskeyword.tbl json.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d
new file mode 100644
index 0000000..829d95c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsopcode.d
@@ -0,0 +1,8 @@
+obj/jsopcode.o: jsopcode.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsdtoa.h jsprf.h \
+ jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h \
+ jsprvtd.h jsatom.h jshash.h jsdhash.h jslock.h jscntxt.h jsclist.h \
+ jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl \
+ jsscript.h jsregexp.h jsstr.h js.msg jsdbgapi.h jsemit.h jsiter.h \
+ jsnum.h jsscan.h jskeyword.tbl jsscope.h jsstaticcheck.h jstracer.h \
+ obj/jsautooplen.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen
new file mode 100755
index 0000000..619a313
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d
new file mode 100644
index 0000000..6094d24
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsoplengen.d
@@ -0,0 +1 @@
+obj/jsoplengen: jsoplengen.cpp jsopcode.tbl
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d
new file mode 100644
index 0000000..ce7ca2b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsparse.d
@@ -0,0 +1,7 @@
+obj/jsparse.o: jsparse.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h \
+ jsatom.h jshash.h jsdhash.h jslock.h jscntxt.h jsclist.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsemit.h jsiter.h jsnum.h jsparse.h jsscan.h \
+ jskeyword.tbl jsscope.h jsstaticcheck.h jsxml.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d
new file mode 100644
index 0000000..9f45c2e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsprf.d
@@ -0,0 +1,3 @@
+obj/jsprf.o: jsprf.cpp jsstddef.h jsprf.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jslong.h jsutil.h jspubtd.h jscompat.h jsproto.tbl \
+ jsversion.h jsstr.h jsprvtd.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d
new file mode 100644
index 0000000..a5ee9eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsregexp.d
@@ -0,0 +1,7 @@
+obj/jsregexp.o: jsregexp.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsutil.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h \
+ jsatom.h jshash.h jsdhash.h jslock.h jsbuiltins.h builtins.tbl jscntxt.h \
+ jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsnum.h jsscan.h \
+ jskeyword.tbl jsscope.h jsreops.tbl jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d
new file mode 100644
index 0000000..d1e348d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscan.d
@@ -0,0 +1,7 @@
+obj/jsscan.o: jsscan.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsarena.h jscompat.h jslong.h jsutil.h jsdtoa.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jsproto.tbl jsversion.h jsatom.h jshash.h \
+ jsdhash.h jsprvtd.h jslock.h jscntxt.h jsclist.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsemit.h jsexn.h jsnum.h jsparse.h jsscan.h jskeyword.tbl \
+ jsstaticcheck.h jsxml.h obj/jsautokw.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d
new file mode 100644
index 0000000..ac99d20
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscope.d
@@ -0,0 +1,6 @@
+obj/jsscope.o: jsscope.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsarena.h jscompat.h jslong.h jsbit.h jsutil.h jsclist.h \
+ jsdhash.h jsapi.h obj/js-config.h jspubtd.h jsproto.tbl jsversion.h \
+ jsatom.h jshash.h jsprvtd.h jslock.h jscntxt.h jsgc.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdbgapi.h jsnum.h jsscope.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d
new file mode 100644
index 0000000..8d8ce7f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsscript.d
@@ -0,0 +1,7 @@
+obj/jsscript.o: jsscript.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsprf.h jsapi.h obj/js-config.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h jsatom.h jshash.h jsdhash.h jsprvtd.h \
+ jslock.h jscntxt.h jsarena.h jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h \
+ jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg \
+ jsdbgapi.h jsemit.h jsnum.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d
new file mode 100644
index 0000000..d9e0123
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsstr.d
@@ -0,0 +1,6 @@
+obj/jsstr.o: jsstr.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h jshash.h jscompat.h jslong.h jsprf.h jsapi.h obj/js-config.h \
+ jspubtd.h jsproto.tbl jsversion.h jsarray.h jsprvtd.h jsatom.h jsdhash.h \
+ jslock.h jsbool.h jsbuiltins.h builtins.tbl jscntxt.h jsarena.h \
+ jsclist.h jsgc.h jsbit.h jsinterp.h jsfun.h jsobj.h jsopcode.h \
+ jsopcode.tbl jsscript.h jsregexp.h jsstr.h js.msg jsnum.h jsscope.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d
new file mode 100644
index 0000000..8e006a2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsutil.d
@@ -0,0 +1,2 @@
+obj/jsutil.o: jsutil.cpp jsstddef.h jstypes.h obj/jsautocfg.h jsotypes.h \
+ jsutil.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d
new file mode 100644
index 0000000..c4b0c9b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxdrapi.d
@@ -0,0 +1,6 @@
+obj/jsxdrapi.o: jsxdrapi.cpp jsstddef.h jsversion.h jstypes.h \
+ obj/jsautocfg.h jsotypes.h jsutil.h jsdhash.h jsprf.h jsapi.h \
+ obj/js-config.h jspubtd.h jscompat.h jslong.h jsproto.tbl jscntxt.h \
+ jsarena.h jsclist.h jsatom.h jshash.h jsprvtd.h jslock.h jsgc.h jsbit.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsnum.h jsxdrapi.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d
new file mode 100644
index 0000000..aa039af
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/jsxml.d
@@ -0,0 +1,7 @@
+obj/jsxml.o: jsxml.cpp jsstddef.h jsversion.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsbit.h jsutil.h jsprf.h jsapi.h obj/js-config.h jspubtd.h \
+ jscompat.h jslong.h jsproto.tbl jsarray.h jsprvtd.h jsatom.h jshash.h \
+ jsdhash.h jslock.h jsbool.h jscntxt.h jsarena.h jsclist.h jsgc.h \
+ jsinterp.h jsfun.h jsobj.h jsopcode.h jsopcode.tbl jsscript.h jsregexp.h \
+ jsstr.h js.msg jsnum.h jsparse.h jsscan.h jskeyword.tbl jsscope.h \
+ jsxml.h jsstaticcheck.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.a b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.a
new file mode 100644
index 0000000..be68e4d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.a
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.so b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.so
new file mode 100755
index 0000000..31cc07a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/libjs.so
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d b/tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d
new file mode 100644
index 0000000..60dfae7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/obj/prmjtime.d
@@ -0,0 +1,3 @@
+obj/prmjtime.o: prmjtime.cpp jsstddef.h jstypes.h obj/jsautocfg.h \
+ jsotypes.h jsutil.h jsprf.h jslock.h jsprvtd.h jspubtd.h jscompat.h \
+ jslong.h jsproto.tbl jsversion.h prmjtime.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed b/tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed
new file mode 100644
index 0000000..6827485
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/plify_jsdhash.sed
@@ -0,0 +1,35 @@
+/ * Double hashing implementation./a\
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+/ * Double hashing, a la Knuth 6./a\
+ * GENERATED BY js/src/plify_jsdhash.sed -- DO NOT EDIT!!!
+s/jsdhash_h___/pldhash_h___/
+s/jsdhash\.bigdump/pldhash.bigdump/
+s/jstypes\.h/nscore.h/
+s/jsbit\.h/prbit.h/
+s/jsdhash\.h/pldhash.h/
+s/jsdhash\.c/pldhash.c/
+s/jsdhash:/pldhash:/
+s/jsutil\.h/nsDebug.h/
+s/JS_DHASH/PL_DHASH/g
+s/JS_DHash/PL_DHash/g
+s/JSDHash/PLDHash/g
+s/JSHash/PLHash/g
+s/uint32 /PRUint32/g
+s/\([^U]\)int32 /\1PRInt32/g
+s/uint16 /PRUint16/g
+s/\([^U]\)int16 /\1PRInt16/g
+s/uint32/PRUint32/g
+s/\([^U]\)int32/\1PRInt32/g
+s/uint16/PRUint16/g
+s/\([^U]\)int16/\1PRInt16/g
+s/JSBool/PRBool/g
+s/extern JS_PUBLIC_API(\([^()]*\))/NS_COM_GLUE \1/
+s/JS_PUBLIC_API(\([^()]*\))/\1/
+s/JS_NewDHashTable/PL_NewDHashTable/
+s/JS_ASSERT(0)/NS_NOTREACHED("0")/
+s/\( *\)JS_ASSERT(\(.*\));/\1NS_ASSERTION(\2,\n\1 "\2");/
+s/JSDHASH_ONELINE_ASSERT(\(.*\));/NS_ASSERTION(\1, "\1");/
+s/JS_UNLIKELY/NS_UNLIKELY/g
+s/JS_LIKELY/NS_LIKELY/g
+s/JS_/PR_/g
+s/fprintf(stderr,/printf_stderr(/
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp
new file mode 100644
index 0000000..881dd70
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.cpp
@@ -0,0 +1,846 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * PR time code.
+ */
+#include "jsstddef.h"
+#ifdef SOLARIS
+#define _REENTRANT 1
+#endif
+#include <string.h>
+#include <time.h>
+#include "jstypes.h"
+#include "jsutil.h"
+
+#include "jsprf.h"
+#include "jslock.h"
+#include "prmjtime.h"
+
+#define PRMJ_DO_MILLISECONDS 1
+
+#ifdef XP_OS2
+#include <sys/timeb.h>
+#endif
+#ifdef XP_WIN
+#include <windef.h>
+#include <winbase.h>
+#include <math.h> /* for fabs */
+#include <mmsystem.h> /* for timeBegin/EndPeriod */
+/* VC++ 8.0 or later, and not WINCE */
+#if _MSC_VER >= 1400 && !defined(WINCE)
+#define NS_HAVE_INVALID_PARAMETER_HANDLER 1
+#endif
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+#include <stdlib.h> /* for _set_invalid_parameter_handler */
+#include <crtdbg.h> /* for _CrtSetReportMode */
+#endif
+
+#ifdef JS_THREADSAFE
+#include <prinit.h>
+#endif
+
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+
+#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
+extern int gettimeofday(struct timeval *tv);
+#endif
+
+#include <sys/time.h>
+
+#endif /* XP_UNIX */
+
+#define PRMJ_YEAR_DAYS 365L
+#define PRMJ_FOUR_YEARS_DAYS (4 * PRMJ_YEAR_DAYS + 1)
+#define PRMJ_CENTURY_DAYS (25 * PRMJ_FOUR_YEARS_DAYS - 1)
+#define PRMJ_FOUR_CENTURIES_DAYS (4 * PRMJ_CENTURY_DAYS + 1)
+#define PRMJ_HOUR_SECONDS 3600L
+#define PRMJ_DAY_SECONDS (24L * PRMJ_HOUR_SECONDS)
+#define PRMJ_YEAR_SECONDS (PRMJ_DAY_SECONDS * PRMJ_YEAR_DAYS)
+#define PRMJ_MAX_UNIX_TIMET 2145859200L /*time_t value equiv. to 12/31/2037 */
+
+/* function prototypes */
+static void PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm);
+/*
+ * get the difference in seconds between this time zone and UTC (GMT)
+ */
+JSInt32
+PRMJ_LocalGMTDifference()
+{
+ struct tm ltime;
+
+ /* get the difference between this time zone and GMT */
+ memset((char *)&ltime,0,sizeof(ltime));
+ ltime.tm_mday = 2;
+ ltime.tm_year = 70;
+ return (JSInt32)mktime(&ltime) - (24L * 3600L);
+}
+
+/* Constants for GMT offset from 1970 */
+#define G1970GMTMICROHI 0x00dcdcad /* micro secs to 1970 hi */
+#define G1970GMTMICROLOW 0x8b3fa000 /* micro secs to 1970 low */
+
+#define G2037GMTMICROHI 0x00e45fab /* micro secs to 2037 high */
+#define G2037GMTMICROLOW 0x7a238000 /* micro secs to 2037 low */
+
+/* Convert from base time to extended time */
+static JSInt64
+PRMJ_ToExtendedTime(JSInt32 base_time)
+{
+ JSInt64 exttime;
+ JSInt64 g1970GMTMicroSeconds;
+ JSInt64 low;
+ JSInt32 diff;
+ JSInt64 tmp;
+ JSInt64 tmp1;
+
+ diff = PRMJ_LocalGMTDifference();
+ JSLL_UI2L(tmp, PRMJ_USEC_PER_SEC);
+ JSLL_I2L(tmp1,diff);
+ JSLL_MUL(tmp,tmp,tmp1);
+
+ JSLL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI);
+ JSLL_UI2L(low,G1970GMTMICROLOW);
+#ifndef JS_HAVE_LONG_LONG
+ JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
+ JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
+#else
+ JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32);
+#endif
+ JSLL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low);
+
+ JSLL_I2L(exttime,base_time);
+ JSLL_ADD(exttime,exttime,g1970GMTMicroSeconds);
+ JSLL_SUB(exttime,exttime,tmp);
+ return exttime;
+}
+
+#ifdef XP_WIN
+typedef struct CalibrationData
+{
+ long double freq; /* The performance counter frequency */
+ long double offset; /* The low res 'epoch' */
+ long double timer_offset; /* The high res 'epoch' */
+
+ /* The last high res time that we returned since recalibrating */
+ JSInt64 last;
+
+ JSBool calibrated;
+
+#ifdef JS_THREADSAFE
+ CRITICAL_SECTION data_lock;
+ CRITICAL_SECTION calibration_lock;
+#endif
+} CalibrationData;
+
+static const JSInt64 win2un = JSLL_INIT(0x19DB1DE, 0xD53E8000);
+
+static CalibrationData calibration = { 0 };
+
+#define FILETIME2INT64(ft) (((JSInt64)ft.dwHighDateTime) << 32LL | (JSInt64)ft.dwLowDateTime)
+
+static void
+NowCalibrate()
+{
+ FILETIME ft, ftStart;
+ LARGE_INTEGER liFreq, now;
+
+ if (calibration.freq == 0.0) {
+ if(!QueryPerformanceFrequency(&liFreq)) {
+ /* High-performance timer is unavailable */
+ calibration.freq = -1.0;
+ } else {
+ calibration.freq = (long double) liFreq.QuadPart;
+ }
+ }
+ if (calibration.freq > 0.0) {
+ JSInt64 calibrationDelta = 0;
+
+ /* By wrapping a timeBegin/EndPeriod pair of calls around this loop,
+ the loop seems to take much less time (1 ms vs 15ms) on Vista. */
+ timeBeginPeriod(1);
+ GetSystemTimeAsFileTime(&ftStart);
+ do {
+ GetSystemTimeAsFileTime(&ft);
+ } while (memcmp(&ftStart,&ft, sizeof(ft)) == 0);
+ timeEndPeriod(1);
+
+ /*
+ calibrationDelta = (FILETIME2INT64(ft) - FILETIME2INT64(ftStart))/10;
+ fprintf(stderr, "Calibration delta was %I64d us\n", calibrationDelta);
+ */
+
+ QueryPerformanceCounter(&now);
+
+ calibration.offset = (long double) FILETIME2INT64(ft);
+ calibration.timer_offset = (long double) now.QuadPart;
+
+ /* The windows epoch is around 1600. The unix epoch is around
+ 1970. win2un is the difference (in windows time units which
+ are 10 times more highres than the JS time unit) */
+ calibration.offset -= win2un;
+ calibration.offset *= 0.1;
+ calibration.last = 0;
+
+ calibration.calibrated = JS_TRUE;
+ }
+}
+
+#define CALIBRATIONLOCK_SPINCOUNT 0
+#define DATALOCK_SPINCOUNT 4096
+#define LASTLOCK_SPINCOUNT 4096
+
+#ifdef JS_THREADSAFE
+static PRStatus
+NowInit(void)
+{
+ memset(&calibration, 0, sizeof(calibration));
+ NowCalibrate();
+ InitializeCriticalSectionAndSpinCount(&calibration.calibration_lock, CALIBRATIONLOCK_SPINCOUNT);
+ InitializeCriticalSectionAndSpinCount(&calibration.data_lock, DATALOCK_SPINCOUNT);
+ return PR_SUCCESS;
+}
+
+void
+PRMJ_NowShutdown()
+{
+ DeleteCriticalSection(&calibration.calibration_lock);
+ DeleteCriticalSection(&calibration.data_lock);
+}
+
+#define MUTEX_LOCK(m) EnterCriticalSection(m)
+#define MUTEX_TRYLOCK(m) TryEnterCriticalSection(m)
+#define MUTEX_UNLOCK(m) LeaveCriticalSection(m)
+#define MUTEX_SETSPINCOUNT(m, c) SetCriticalSectionSpinCount((m),(c))
+
+static PRCallOnceType calibrationOnce = { 0 };
+
+#else
+
+#define MUTEX_LOCK(m)
+#define MUTEX_TRYLOCK(m) 1
+#define MUTEX_UNLOCK(m)
+#define MUTEX_SETSPINCOUNT(m, c)
+
+#endif
+
+
+#endif /* XP_WIN */
+
+/*
+
+Win32 python-esque pseudo code
+Please see bug 363258 for why the win32 timing code is so complex.
+
+calibration mutex : Win32CriticalSection(spincount=0)
+data mutex : Win32CriticalSection(spincount=4096)
+
+def NowInit():
+ init mutexes
+ PRMJ_NowCalibration()
+
+def NowCalibration():
+ expensive up-to-15ms call
+
+def PRMJ_Now():
+ returnedTime = 0
+ needCalibration = False
+ cachedOffset = 0.0
+ calibrated = False
+ PR_CallOnce(PRMJ_NowInit)
+ do
+ if not global.calibrated or needCalibration:
+ acquire calibration mutex
+ acquire data mutex
+
+ // Only recalibrate if someone didn't already
+ if cachedOffset == calibration.offset:
+ // Have all waiting threads immediately wait
+ set data mutex spin count = 0
+ PRMJ_NowCalibrate()
+ calibrated = 1
+
+ set data mutex spin count = default
+ release data mutex
+ release calibration mutex
+
+ calculate lowres time
+
+ if highres timer available:
+ acquire data mutex
+ calculate highres time
+ cachedOffset = calibration.offset
+ highres time = calibration.last = max(highres time, calibration.last)
+ release data mutex
+
+ get kernel tick interval
+
+ if abs(highres - lowres) < kernel tick:
+ returnedTime = highres time
+ needCalibration = False
+ else:
+ if calibrated:
+ returnedTime = lowres
+ needCalibration = False
+ else:
+ needCalibration = True
+ else:
+ returnedTime = lowres
+ while needCalibration
+
+*/
+
+JSInt64
+PRMJ_Now(void)
+{
+#ifdef XP_OS2
+ JSInt64 s, us, ms2us, s2us;
+ struct timeb b;
+#endif
+#ifdef XP_WIN
+ static int nCalls = 0;
+ long double lowresTime, highresTimerValue;
+ FILETIME ft;
+ LARGE_INTEGER now;
+ JSBool calibrated = JS_FALSE;
+ JSBool needsCalibration = JS_FALSE;
+ JSInt64 returnedTime;
+ long double cachedOffset = 0.0;
+#endif
+#if defined(XP_UNIX) || defined(XP_BEOS)
+ struct timeval tv;
+ JSInt64 s, us, s2us;
+#endif /* XP_UNIX */
+
+#ifdef XP_OS2
+ ftime(&b);
+ JSLL_UI2L(ms2us, PRMJ_USEC_PER_MSEC);
+ JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
+ JSLL_UI2L(s, b.time);
+ JSLL_UI2L(us, b.millitm);
+ JSLL_MUL(us, us, ms2us);
+ JSLL_MUL(s, s, s2us);
+ JSLL_ADD(s, s, us);
+ return s;
+#endif
+#ifdef XP_WIN
+
+ /* To avoid regressing startup time (where high resolution is likely
+ not needed), give the old behavior for the first few calls.
+ This does not appear to be needed on Vista as the timeBegin/timeEndPeriod
+ calls seem to immediately take effect. */
+ int thiscall = JS_ATOMIC_INCREMENT(&nCalls);
+ /* 10 seems to be the number of calls to load with a blank homepage */
+ if (thiscall <= 10) {
+ GetSystemTimeAsFileTime(&ft);
+ return (FILETIME2INT64(ft)-win2un)/10L;
+ }
+
+ /* For non threadsafe platforms, NowInit is not necessary */
+#ifdef JS_THREADSAFE
+ PR_CallOnce(&calibrationOnce, NowInit);
+#endif
+ do {
+ if (!calibration.calibrated || needsCalibration) {
+ MUTEX_LOCK(&calibration.calibration_lock);
+ MUTEX_LOCK(&calibration.data_lock);
+
+ /* Recalibrate only if no one else did before us */
+ if(calibration.offset == cachedOffset) {
+ /* Since calibration can take a while, make any other
+ threads immediately wait */
+ MUTEX_SETSPINCOUNT(&calibration.data_lock, 0);
+
+ NowCalibrate();
+
+ calibrated = JS_TRUE;
+
+ /* Restore spin count */
+ MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT);
+ }
+ MUTEX_UNLOCK(&calibration.data_lock);
+ MUTEX_UNLOCK(&calibration.calibration_lock);
+ }
+
+
+ /* Calculate a low resolution time */
+ GetSystemTimeAsFileTime(&ft);
+ lowresTime = 0.1*(long double)(FILETIME2INT64(ft) - win2un);
+
+ if (calibration.freq > 0.0) {
+ long double highresTime, diff;
+
+ DWORD timeAdjustment, timeIncrement;
+ BOOL timeAdjustmentDisabled;
+
+ /* Default to 15.625 ms if the syscall fails */
+ long double skewThreshold = 15625.25;
+ /* Grab high resolution time */
+ QueryPerformanceCounter(&now);
+ highresTimerValue = (long double)now.QuadPart;
+
+ MUTEX_LOCK(&calibration.data_lock);
+ highresTime = calibration.offset + PRMJ_USEC_PER_SEC*
+ (highresTimerValue-calibration.timer_offset)/calibration.freq;
+ cachedOffset = calibration.offset;
+
+ /* On some dual processor/core systems, we might get an earlier time
+ so we cache the last time that we returned */
+ calibration.last = max(calibration.last,(JSInt64)highresTime);
+ returnedTime = calibration.last;
+ MUTEX_UNLOCK(&calibration.data_lock);
+
+ /* Rather than assume the NT kernel ticks every 15.6ms, ask it */
+ if (GetSystemTimeAdjustment(&timeAdjustment,
+ &timeIncrement,
+ &timeAdjustmentDisabled)) {
+ if (timeAdjustmentDisabled) {
+ /* timeAdjustment is in units of 100ns */
+ skewThreshold = timeAdjustment/10.0;
+ } else {
+ /* timeIncrement is in units of 100ns */
+ skewThreshold = timeIncrement/10.0;
+ }
+ }
+
+ /* Check for clock skew */
+ diff = lowresTime - highresTime;
+
+ /* For some reason that I have not determined, the skew can be
+ up to twice a kernel tick. This does not seem to happen by
+ itself, but I have only seen it triggered by another program
+ doing some kind of file I/O. The symptoms are a negative diff
+ followed by an equally large positive diff. */
+ if (fabs(diff) > 2*skewThreshold) {
+ /*fprintf(stderr,"Clock skew detected (diff = %f)!\n", diff);*/
+
+ if (calibrated) {
+ /* If we already calibrated once this instance, and the
+ clock is still skewed, then either the processor(s) are
+ wildly changing clockspeed or the system is so busy that
+ we get switched out for long periods of time. In either
+ case, it would be infeasible to make use of high
+ resolution results for anything, so let's resort to old
+ behavior for this call. It's possible that in the
+ future, the user will want the high resolution timer, so
+ we don't disable it entirely. */
+ returnedTime = (JSInt64)lowresTime;
+ needsCalibration = JS_FALSE;
+ } else {
+ /* It is possible that when we recalibrate, we will return a
+ value less than what we have returned before; this is
+ unavoidable. We cannot tell the different between a
+ faulty QueryPerformanceCounter implementation and user
+ changes to the operating system time. Since we must
+ respect user changes to the operating system time, we
+ cannot maintain the invariant that Date.now() never
+ decreases; the old implementation has this behavior as
+ well. */
+ needsCalibration = JS_TRUE;
+ }
+ } else {
+ /* No detectable clock skew */
+ returnedTime = (JSInt64)highresTime;
+ needsCalibration = JS_FALSE;
+ }
+ } else {
+ /* No high resolution timer is available, so fall back */
+ returnedTime = (JSInt64)lowresTime;
+ }
+ } while (needsCalibration);
+
+ return returnedTime;
+#endif
+
+#if defined(XP_UNIX) || defined(XP_BEOS)
+#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
+ gettimeofday(&tv);
+#else
+ gettimeofday(&tv, 0);
+#endif /* _SVID_GETTOD */
+ JSLL_UI2L(s2us, PRMJ_USEC_PER_SEC);
+ JSLL_UI2L(s, tv.tv_sec);
+ JSLL_UI2L(us, tv.tv_usec);
+ JSLL_MUL(s, s, s2us);
+ JSLL_ADD(s, s, us);
+ return s;
+#endif /* XP_UNIX */
+}
+
+/* Get the DST timezone offset for the time passed in */
+JSInt64
+PRMJ_DSTOffset(JSInt64 local_time)
+{
+ JSInt64 us2s;
+ time_t local;
+ JSInt32 diff;
+ JSInt64 maxtimet;
+ struct tm tm;
+ PRMJTime prtm;
+#ifndef HAVE_LOCALTIME_R
+ struct tm *ptm;
+#endif
+
+
+ JSLL_UI2L(us2s, PRMJ_USEC_PER_SEC);
+ JSLL_DIV(local_time, local_time, us2s);
+
+ /* get the maximum of time_t value */
+ JSLL_UI2L(maxtimet,PRMJ_MAX_UNIX_TIMET);
+
+ if(JSLL_CMP(local_time,>,maxtimet)){
+ JSLL_UI2L(local_time,PRMJ_MAX_UNIX_TIMET);
+ } else if(!JSLL_GE_ZERO(local_time)){
+ /*go ahead a day to make localtime work (does not work with 0) */
+ JSLL_UI2L(local_time,PRMJ_DAY_SECONDS);
+ }
+ JSLL_L2UI(local,local_time);
+ PRMJ_basetime(local_time,&prtm);
+#ifndef HAVE_LOCALTIME_R
+ ptm = localtime(&local);
+ if(!ptm){
+ return 0;
+ }
+ tm = *ptm;
+#else
+ localtime_r(&local,&tm); /* get dst information */
+#endif
+
+ diff = ((tm.tm_hour - prtm.tm_hour) * PRMJ_HOUR_SECONDS) +
+ ((tm.tm_min - prtm.tm_min) * 60);
+
+ if(diff < 0){
+ diff += PRMJ_DAY_SECONDS;
+ }
+
+ JSLL_UI2L(local_time,diff);
+
+ JSLL_MUL(local_time,local_time,us2s);
+
+ return(local_time);
+}
+
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+static void
+PRMJ_InvalidParameterHandler(const wchar_t *expression,
+ const wchar_t *function,
+ const wchar_t *file,
+ unsigned int line,
+ uintptr_t pReserved)
+{
+ /* empty */
+}
+#endif
+
+/* Format a time value into a buffer. Same semantics as strftime() */
+size_t
+PRMJ_FormatTime(char *buf, int buflen, const char *fmt, PRMJTime *prtm)
+{
+ size_t result = 0;
+#if defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
+ struct tm a;
+ int fake_tm_year = 0;
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+ _invalid_parameter_handler oldHandler;
+ int oldReportMode;
+#endif
+
+ /* Zero out the tm struct. Linux, SunOS 4 struct tm has extra members int
+ * tm_gmtoff, char *tm_zone; when tm_zone is garbage, strftime gets
+ * confused and dumps core. NSPR20 prtime.c attempts to fill these in by
+ * calling mktime on the partially filled struct, but this doesn't seem to
+ * work as well; the result string has "can't get timezone" for ECMA-valid
+ * years. Might still make sense to use this, but find the range of years
+ * for which valid tz information exists, and map (per ECMA hint) from the
+ * given year into that range.
+
+ * N.B. This hasn't been tested with anything that actually _uses_
+ * tm_gmtoff; zero might be the wrong thing to set it to if you really need
+ * to format a time. This fix is for jsdate.c, which only uses
+ * JS_FormatTime to get a string representing the time zone. */
+ memset(&a, 0, sizeof(struct tm));
+
+ a.tm_sec = prtm->tm_sec;
+ a.tm_min = prtm->tm_min;
+ a.tm_hour = prtm->tm_hour;
+ a.tm_mday = prtm->tm_mday;
+ a.tm_mon = prtm->tm_mon;
+ a.tm_wday = prtm->tm_wday;
+
+ /*
+ * Years before 1900 and after 9999 cause strftime() to abort on Windows.
+ * To avoid that we replace it with FAKE_YEAR_BASE + year % 100 and then
+ * replace matching substrings in the strftime() result with the real year.
+ * Note that FAKE_YEAR_BASE should be a multiple of 100 to make 2-digit
+ * year formats (%y) work correctly (since we won't find the fake year
+ * in that case).
+ * e.g. new Date(1873, 0).toLocaleFormat('%Y %y') => "1873 73"
+ * See bug 327869.
+ */
+#define FAKE_YEAR_BASE 9900
+ if (prtm->tm_year < 1900 || prtm->tm_year > 9999) {
+ fake_tm_year = FAKE_YEAR_BASE + prtm->tm_year % 100;
+ a.tm_year = fake_tm_year - 1900;
+ }
+ else {
+ a.tm_year = prtm->tm_year - 1900;
+ }
+ a.tm_yday = prtm->tm_yday;
+ a.tm_isdst = prtm->tm_isdst;
+
+ /*
+ * Even with the above, SunOS 4 seems to detonate if tm_zone and tm_gmtoff
+ * are null. This doesn't quite work, though - the timezone is off by
+ * tzoff + dst. (And mktime seems to return -1 for the exact dst
+ * changeover time.)
+ */
+
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+ oldHandler = _set_invalid_parameter_handler(PRMJ_InvalidParameterHandler);
+ oldReportMode = _CrtSetReportMode(_CRT_ASSERT, 0);
+#endif
+
+ result = strftime(buf, buflen, fmt, &a);
+
+#ifdef NS_HAVE_INVALID_PARAMETER_HANDLER
+ _set_invalid_parameter_handler(oldHandler);
+ _CrtSetReportMode(_CRT_ASSERT, oldReportMode);
+#endif
+
+ if (fake_tm_year && result) {
+ char real_year[16];
+ char fake_year[16];
+ size_t real_year_len;
+ size_t fake_year_len;
+ char* p;
+
+ sprintf(real_year, "%d", prtm->tm_year);
+ real_year_len = strlen(real_year);
+ sprintf(fake_year, "%d", fake_tm_year);
+ fake_year_len = strlen(fake_year);
+
+ /* Replace the fake year in the result with the real year. */
+ for (p = buf; (p = strstr(p, fake_year)); p += real_year_len) {
+ size_t new_result = result + real_year_len - fake_year_len;
+ if ((int)new_result >= buflen) {
+ return 0;
+ }
+ memmove(p + real_year_len, p + fake_year_len, strlen(p + fake_year_len));
+ memcpy(p, real_year, real_year_len);
+ result = new_result;
+ *(buf + result) = '\0';
+ }
+ }
+#endif
+ return result;
+}
+
+/* table for number of days in a month */
+static int mtab[] = {
+ /* jan, feb,mar,apr,may,jun */
+ 31,28,31,30,31,30,
+ /* july,aug,sep,oct,nov,dec */
+ 31,31,30,31,30,31
+};
+
+/*
+ * basic time calculation functionality for localtime and gmtime
+ * setups up prtm argument with correct values based upon input number
+ * of seconds.
+ */
+static void
+PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm)
+{
+ /* convert tsecs back to year,month,day,hour,secs */
+ JSInt32 year = 0;
+ JSInt32 month = 0;
+ JSInt32 yday = 0;
+ JSInt32 mday = 0;
+ JSInt32 wday = 6; /* start on a Sunday */
+ JSInt32 days = 0;
+ JSInt32 seconds = 0;
+ JSInt32 minutes = 0;
+ JSInt32 hours = 0;
+ JSInt32 isleap = 0;
+
+ /* Temporaries used for various computations */
+ JSInt64 result;
+ JSInt64 result1;
+ JSInt64 result2;
+
+ JSInt64 base;
+
+ /* Some variables for intermediate result storage to make computing isleap
+ easier/faster */
+ JSInt32 fourCenturyBlocks;
+ JSInt32 centuriesLeft;
+ JSInt32 fourYearBlocksLeft;
+ JSInt32 yearsLeft;
+
+ /* Since leap years work by 400/100/4 year intervals, precompute the length
+ of those in seconds if they start at the beginning of year 1. */
+ JSInt64 fourYears;
+ JSInt64 century;
+ JSInt64 fourCenturies;
+
+ JSLL_UI2L(result, PRMJ_DAY_SECONDS);
+
+ JSLL_I2L(fourYears, PRMJ_FOUR_YEARS_DAYS);
+ JSLL_MUL(fourYears, fourYears, result);
+
+ JSLL_I2L(century, PRMJ_CENTURY_DAYS);
+ JSLL_MUL(century, century, result);
+
+ JSLL_I2L(fourCenturies, PRMJ_FOUR_CENTURIES_DAYS);
+ JSLL_MUL(fourCenturies, fourCenturies, result);
+
+ /* get the base time via UTC */
+ base = PRMJ_ToExtendedTime(0);
+ JSLL_UI2L(result, PRMJ_USEC_PER_SEC);
+ JSLL_DIV(base,base,result);
+ JSLL_ADD(tsecs,tsecs,base);
+
+ /* Compute our |year|, |isleap|, and part of |days|. When this part is
+ done, |year| should hold the year our date falls in (number of whole
+ years elapsed before our date), isleap should hold 1 if the year the
+ date falls in is a leap year and 0 otherwise. */
+
+ /* First do year 0; it's special and nonleap. */
+ JSLL_UI2L(result, PRMJ_YEAR_SECONDS);
+ if (!JSLL_CMP(tsecs,<,result)) {
+ days = PRMJ_YEAR_DAYS;
+ year = 1;
+ JSLL_SUB(tsecs, tsecs, result);
+ }
+
+ /* Now use those constants we computed above */
+ JSLL_UDIVMOD(&result1, &result2, tsecs, fourCenturies);
+ JSLL_L2I(fourCenturyBlocks, result1);
+ year += fourCenturyBlocks * 400;
+ days += fourCenturyBlocks * PRMJ_FOUR_CENTURIES_DAYS;
+ tsecs = result2;
+
+ JSLL_UDIVMOD(&result1, &result2, tsecs, century);
+ JSLL_L2I(centuriesLeft, result1);
+ year += centuriesLeft * 100;
+ days += centuriesLeft * PRMJ_CENTURY_DAYS;
+ tsecs = result2;
+
+ JSLL_UDIVMOD(&result1, &result2, tsecs, fourYears);
+ JSLL_L2I(fourYearBlocksLeft, result1);
+ year += fourYearBlocksLeft * 4;
+ days += fourYearBlocksLeft * PRMJ_FOUR_YEARS_DAYS;
+ tsecs = result2;
+
+ /* Recall that |result| holds PRMJ_YEAR_SECONDS */
+ JSLL_UDIVMOD(&result1, &result2, tsecs, result);
+ JSLL_L2I(yearsLeft, result1);
+ year += yearsLeft;
+ days += yearsLeft * PRMJ_YEAR_DAYS;
+ tsecs = result2;
+
+ /* now compute isleap. Note that we don't have to use %, since we've
+ already computed those remainders. Also note that they're all offset by
+ 1 because of the 1 for year 0. */
+ isleap =
+ (yearsLeft == 3) && (fourYearBlocksLeft != 24 || centuriesLeft == 3);
+ JS_ASSERT(isleap ==
+ ((year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)));
+
+ JSLL_UI2L(result1,PRMJ_DAY_SECONDS);
+
+ JSLL_DIV(result,tsecs,result1);
+ JSLL_L2I(mday,result);
+
+ /* let's find the month */
+ while(((month == 1 && isleap) ?
+ (mday >= mtab[month] + 1) :
+ (mday >= mtab[month]))){
+ yday += mtab[month];
+ days += mtab[month];
+
+ mday -= mtab[month];
+
+ /* it's a Feb, check if this is a leap year */
+ if(month == 1 && isleap != 0){
+ yday++;
+ days++;
+ mday--;
+ }
+ month++;
+ }
+
+ /* now adjust tsecs */
+ JSLL_MUL(result,result,result1);
+ JSLL_SUB(tsecs,tsecs,result);
+
+ mday++; /* day of month always start with 1 */
+ days += mday;
+ wday = (days + wday) % 7;
+
+ yday += mday;
+
+ /* get the hours */
+ JSLL_UI2L(result1,PRMJ_HOUR_SECONDS);
+ JSLL_DIV(result,tsecs,result1);
+ JSLL_L2I(hours,result);
+ JSLL_MUL(result,result,result1);
+ JSLL_SUB(tsecs,tsecs,result);
+
+ /* get minutes */
+ JSLL_UI2L(result1,60);
+ JSLL_DIV(result,tsecs,result1);
+ JSLL_L2I(minutes,result);
+ JSLL_MUL(result,result,result1);
+ JSLL_SUB(tsecs,tsecs,result);
+
+ JSLL_L2I(seconds,tsecs);
+
+ prtm->tm_usec = 0L;
+ prtm->tm_sec = (JSInt8)seconds;
+ prtm->tm_min = (JSInt8)minutes;
+ prtm->tm_hour = (JSInt8)hours;
+ prtm->tm_mday = (JSInt8)mday;
+ prtm->tm_mon = (JSInt8)month;
+ prtm->tm_wday = (JSInt8)wday;
+ prtm->tm_year = (JSInt16)year;
+ prtm->tm_yday = (JSInt16)yday;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h
new file mode 100644
index 0000000..e553945
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/prmjtime.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code, released
+ * March 31, 1998.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef prmjtime_h___
+#define prmjtime_h___
+/*
+ * PR date stuff for mocha and java. Placed here temporarily not to break
+ * Navigator and localize changes to mocha.
+ */
+#include <time.h>
+#include "jslong.h"
+#ifdef MOZILLA_CLIENT
+#include "jscompat.h"
+#endif
+
+JS_BEGIN_EXTERN_C
+
+typedef struct PRMJTime PRMJTime;
+
+/*
+ * Broken down form of 64 bit time value.
+ */
+struct PRMJTime {
+ JSInt32 tm_usec; /* microseconds of second (0-999999) */
+ JSInt8 tm_sec; /* seconds of minute (0-59) */
+ JSInt8 tm_min; /* minutes of hour (0-59) */
+ JSInt8 tm_hour; /* hour of day (0-23) */
+ JSInt8 tm_mday; /* day of month (1-31) */
+ JSInt8 tm_mon; /* month of year (0-11) */
+ JSInt8 tm_wday; /* 0=sunday, 1=monday, ... */
+ JSInt32 tm_year; /* absolute year, AD */
+ JSInt16 tm_yday; /* day of year (0 to 365) */
+ JSInt8 tm_isdst; /* non-zero if DST in effect */
+};
+
+/* Some handy constants */
+#define PRMJ_USEC_PER_SEC 1000000L
+#define PRMJ_USEC_PER_MSEC 1000L
+
+/* Return the current local time in micro-seconds */
+extern JSInt64
+PRMJ_Now(void);
+
+/* Release the resources associated with PRMJ_Now; don't call PRMJ_Now again */
+#if defined(JS_THREADSAFE) && defined(XP_WIN)
+extern void
+PRMJ_NowShutdown(void);
+#else
+#define PRMJ_NowShutdown()
+#endif
+
+/* get the difference between this time zone and gmt timezone in seconds */
+extern JSInt32
+PRMJ_LocalGMTDifference(void);
+
+/* Format a time value into a buffer. Same semantics as strftime() */
+extern size_t
+PRMJ_FormatTime(char *buf, int buflen, const char *fmt, PRMJTime *tm);
+
+/* Get the DST offset for the local time passed in */
+extern JSInt64
+PRMJ_DSTOffset(JSInt64 local_time);
+
+JS_END_EXTERN_C
+
+#endif /* prmjtime_h___ */
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk
new file mode 100644
index 0000000..09c7cb9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.1.mk
@@ -0,0 +1,65 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for AIX
+#
+
+CC = xlC_r
+CCC = xlC_r
+
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+ARCH := aix
+CPU_ARCH = rs6000
+GFX_ARCH = x
+INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
+
+OS_CFLAGS = -qarch=com -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R
+OS_LIBS = -lbsd -lsvld -lm
+#-lpthreads -lc_r
+
+MKSHLIB = $(LD) -bM:SRE -bh:4 -bnoentry -berok
+XLDFLAGS += -lc
+
+ifdef JS_THREADSAFE
+XLDFLAGS += -lsvld
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk
new file mode 100644
index 0000000..1e3f1f1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.2.mk
@@ -0,0 +1,64 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for AIX
+#
+
+CC = xlC_r
+CCC = xlC_r
+CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DHAVE_LOCALTIME_R
+
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+ARCH := aix
+CPU_ARCH = rs6000
+GFX_ARCH = x
+INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
+
+#-lpthreads -lc_r
+
+MKSHLIB = /usr/lpp/xlC/bin/makeC++SharedLib_r -p 0 -G -berok
+
+ifdef JS_THREADSAFE
+XLDFLAGS += -ldl
+endif
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk
new file mode 100644
index 0000000..df05d8c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/AIX4.3.mk
@@ -0,0 +1,65 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for AIX
+#
+
+CC = xlC_r
+CCC = xlC_r
+CFLAGS += -qarch=com -qnoansialias -qinline+$(INLINES) -DXP_UNIX -DAIX -DAIXV3 -DSYSV -DAIX4_3 -DHAVE_LOCALTIME_R
+
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+ARCH := aix
+CPU_ARCH = rs6000
+GFX_ARCH = x
+INLINES = js_compare_and_swap:js_fast_lock1:js_fast_unlock1:js_lock_get_slot:js_lock_set_slot:js_lock_scope1
+
+#-lpthreads -lc_r
+
+MKSHLIB_BIN = /usr/ibmcxx/bin/makeC++SharedLib_r
+MKSHLIB = $(MKSHLIB_BIN) -p 0 -G -berok -bM:UR
+
+ifdef JS_THREADSAFE
+XLDFLAGS += -ldl
+endif
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk
new file mode 100644
index 0000000..6319682
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Cygwin.mk
@@ -0,0 +1,14 @@
+CC = gcc
+CXX = g++
+LD = g++
+OS_CFLAGS_NO_ANSI = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R
+OS_CFLAGS = -ansi $(OS_CFLAGS_NO_ANSI)
+PROGRAM_CFLAGS = $(OPTIMIZER) $(OS_CFLAGS_NO_ANSI) $(DEFINES) $(INCLUDES) $(XCFLAGS)
+RANLIB = ranlib
+MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
+
+all:
+
+obj/js.o: js.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(PROGRAM_CFLAGS) js.cpp
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk
new file mode 100644
index 0000000..86c4b9d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin.mk
@@ -0,0 +1,85 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format -MMD
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = $(CCC) -dynamiclib $(XMKSHLIBOPTS) -framework System
+
+SO_SUFFIX = dylib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+OS_CFLAGS += -DAVMPLUS_IA32 -DAVMPLUS_UNIX
+NANOJIT_ARCH = i386
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk
new file mode 100644
index 0000000..05d3767
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.3.mk
@@ -0,0 +1,81 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DRHAPSODY
+
+RANLIB = ranlib
+MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk
new file mode 100644
index 0000000..f7b6af8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin1.4.mk
@@ -0,0 +1,41 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mike McCabe <mike+mozilla@meer.net>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+include $(DEPTH)/config/Darwin1.3.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk
new file mode 100644
index 0000000..9b9b6ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.2.mk
@@ -0,0 +1,81 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk
new file mode 100644
index 0000000..9b9b6ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin5.3.mk
@@ -0,0 +1,81 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = libtool $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk
new file mode 100644
index 0000000..db195b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Darwin64.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format -MMD
+OS_LDFLAGS += -m64
+OS_CFLAGS = -m64 -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DDARWIN
+
+RANLIB = ranlib
+MKSHLIB = $(CCC) -dynamiclib $(XMKSHLIBOPTS) -framework System
+
+SO_SUFFIX = dylib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86_64
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk
new file mode 100644
index 0000000..8cd9d20
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.10.mk
@@ -0,0 +1,77 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for HPUX
+#
+
+# CC = gcc
+# CCC = g++
+# CFLAGS += -Wall -Wno-format -fPIC
+
+CC = cc -Ae +Z
+CCC = CC -Ae +a1 +eh +Z
+
+RANLIB = echo
+MKSHLIB = $(LD) -b
+
+SO_SUFFIX = sl
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = hppa
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R
+OS_LIBS = -ldld
+
+ifeq ($(OS_RELEASE),B.10)
+PLATFORM_FLAGS += -DHPUX10 -Dhpux10
+PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
+ifeq ($(OS_VERSION),.10)
+PLATFORM_FLAGS += -DHPUX10_10
+endif
+ifeq ($(OS_VERSION),.20)
+PLATFORM_FLAGS += -DHPUX10_20
+endif
+ifeq ($(OS_VERSION),.30)
+PLATFORM_FLAGS += -DHPUX10_30
+endif
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk
new file mode 100644
index 0000000..8cd9d20
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.10.20.mk
@@ -0,0 +1,77 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for HPUX
+#
+
+# CC = gcc
+# CCC = g++
+# CFLAGS += -Wall -Wno-format -fPIC
+
+CC = cc -Ae +Z
+CCC = CC -Ae +a1 +eh +Z
+
+RANLIB = echo
+MKSHLIB = $(LD) -b
+
+SO_SUFFIX = sl
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = hppa
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -DHAVE_LOCALTIME_R
+OS_LIBS = -ldld
+
+ifeq ($(OS_RELEASE),B.10)
+PLATFORM_FLAGS += -DHPUX10 -Dhpux10
+PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
+ifeq ($(OS_VERSION),.10)
+PLATFORM_FLAGS += -DHPUX10_10
+endif
+ifeq ($(OS_VERSION),.20)
+PLATFORM_FLAGS += -DHPUX10_20
+endif
+ifeq ($(OS_VERSION),.30)
+PLATFORM_FLAGS += -DHPUX10_30
+endif
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk
new file mode 100644
index 0000000..239188d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/HP-UXB.11.00.mk
@@ -0,0 +1,80 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for HPUX
+#
+
+ifdef NS_USE_NATIVE
+ CC = cc +Z +DAportable +DS2.0 +u4
+# LD = aCC +Z -b -Wl,+s -Wl,-B,symbolic
+else
+ CC = gcc -Wall -Wno-format -fPIC
+ CCC = g++ -Wall -Wno-format -fPIC
+endif
+
+RANLIB = echo
+MKSHLIB = $(LD) -b
+
+SO_SUFFIX = sl
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = hppa
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DHPUX -DSYSV -D_HPUX -DNATIVE -D_POSIX_C_SOURCE=199506L -DHAVE_LOCALTIME_R
+OS_LIBS = -ldld
+
+XLDFLAGS = -lpthread
+
+ifeq ($(OS_RELEASE),B.10)
+PLATFORM_FLAGS += -DHPUX10 -Dhpux10
+PORT_FLAGS += -DRW_NO_OVERLOAD_SCHAR -DHAVE_MODEL_H
+ifeq ($(OS_VERSION),.10)
+PLATFORM_FLAGS += -DHPUX10_10
+endif
+ifeq ($(OS_VERSION),.20)
+PLATFORM_FLAGS += -DHPUX10_20
+endif
+ifeq ($(OS_VERSION),.30)
+PLATFORM_FLAGS += -DHPUX10_30
+endif
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk
new file mode 100644
index 0000000..88b162f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX.mk
@@ -0,0 +1,87 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX
+#
+
+CPU_ARCH = mips
+GFX_ARCH = x
+
+RANLIB = /bin/true
+
+#NS_USE_GCC = 1
+
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+AS = $(CC) -x assembler-with-cpp
+ODD_CFLAGS = -Wall -Wno-format
+ifdef BUILD_OPT
+OPTIMIZER = -O6
+endif
+else
+ifeq ($(OS_RELEASE),6.2)
+CC = cc -n32 -DIRIX6_2
+endif
+ifeq ($(OS_RELEASE),6.3)
+CC = cc -n32 -DIRIX6_3
+endif
+ifeq ($(OS_RELEASE),6.5)
+CC = cc -n32 -DIRIX6_5
+endif
+CCC = CC
+# LD = CC
+ODD_CFLAGS = -fullwarn -xansi
+ifdef BUILD_OPT
+OPTIMIZER += -Olimit 4000
+endif
+endif
+
+# For purify
+HAVE_PURIFY = 1
+PURE_OS_CFLAGS = $(ODD_CFLAGS) -DXP_UNIX -DSVR4 -DSW_THREADS -DIRIX -DHAVE_LOCALTIME_R
+
+OS_CFLAGS = $(PURE_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
+
+BSDECHO = echo
+MKSHLIB = $(LD) -n32 -shared
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk
new file mode 100644
index 0000000..f38cc94
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX5.3.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX5.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.1.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.2.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.3.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk
new file mode 100644
index 0000000..354f1d1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/IRIX6.5.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for IRIX6.3
+#
+
+include $(DEPTH)/config/IRIX.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk
new file mode 100644
index 0000000..6c289b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Linux_All.mk
@@ -0,0 +1,105 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for all versions of Linux
+#
+
+CC = gcc
+CCC = g++
+LD = g++
+CFLAGS += -Wall -Wno-format -MMD
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DLINUX
+
+RANLIB = echo
+MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+# don't filter in x86-64 architecture
+ifneq (x86_64,$(CPU_ARCH))
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS += -DX86_LINUX -DAVMPLUS_IA32 -DAVMPLUS_UNIX -DAVMPLUS_LINUX
+NANOJIT_ARCH = i386
+endif # 86
+endif # !x86_64
+
+#JIT disabled until x64 port is cleaned up
+#ifeq ($(CPU_ARCH),x86_64)
+#OS_CFLAGS += -DAVMPLUS_AMD64 -DAVMPLUS_64BIT -DAVMPLUS_UNIX -DAVMPLUS_LINUX
+#NANOJIT_ARCH = i386
+#endif
+
+ifeq ($(CPU_ARCH),arm)
+OS_CFLAGS += -DAVMPLUS_ARM -DAVMPLUS_UNIX -DAVMPLUS_LINUX
+NANOJIT_ARCH = ARM
+endif
+
+GFX_ARCH = x
+
+OS_LIBS = -lm -lc
+
+ASFLAGS += -x assembler-with-cpp
+
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+ifeq ($(CPU_ARCH),x86_64)
+# Use VA_COPY() standard macro on x86-64
+# FIXME: better use it everywhere
+OS_CFLAGS += -DHAVE_VA_COPY -DVA_COPY=va_copy
+endif
+
+ifeq ($(CPU_ARCH),x86_64)
+# We need PIC code for shared libraries
+# FIXME: better patch rules.mk & fdlibm/Makefile*
+OS_CFLAGS += -DPIC -fPIC
+endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk
new file mode 100644
index 0000000..61c3ab6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/MSYS.mk
@@ -0,0 +1,7 @@
+CC = gcc
+CXX = g++
+LD = g++
+OS_CFLAGS = -DXP_WIN -DEXPORT_JS_API=1
+RANLIB = ranlib
+MKSHLIB = $(LD) -shared $(XMKSHLIBOPTS)
+OTHER_LIBS = -lwinmm
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk
new file mode 100644
index 0000000..74ba151
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/Mac_OS10.0.mk
@@ -0,0 +1,82 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Steve Zellers (zellers@apple.com)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Mac OS X as of PR3
+# Just ripped from Linux config
+#
+
+CC = cc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE
+-DRHAPSODY
+
+RANLIB = ranlib
+MKSHLIB = libtool -dynamic $(XMKSHLIBOPTS) -framework System
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = $(shell uname -m)
+ifeq (86,$(findstring 86,$(CPU_ARCH)))
+CPU_ARCH = x86
+OS_CFLAGS+= -DX86_LINUX
+endif
+GFX_ARCH = x
+
+OS_LIBS = -lc -framework System
+
+ASFLAGS += -x assembler-with-cpp
+
+ifeq ($(CPU_ARCH),alpha)
+
+# Ask the C compiler on alpha linux to let us work with denormalized
+# double values, which are required by the ECMA spec.
+
+OS_CFLAGS += -mieee
+endif
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
+
+# Don't allow Makefile.ref to use libmath
+NO_LIBM = 1
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk
new file mode 100644
index 0000000..337ca74
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V4.0.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for Data General DG/UX
+#
+
+#
+# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
+#
+
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+CFLAGS += -mieee -Wall -Wno-format
+else
+CC = cc
+CCC = cxx
+CFLAGS += -ieee -std
+# LD = cxx
+endif
+
+RANLIB = echo
+MKSHLIB = $(LD) -shared -taso -all -expect_unresolved "*"
+
+#
+# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if
+# you're not using DG's compiler. It shouldn't hurt if you are.
+#
+# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
+# prtime.c
+#
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl
+
+NOSUCHFILE = /no-such-file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk
new file mode 100644
index 0000000..b65738c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/OSF1V5.0.mk
@@ -0,0 +1,69 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for Tru64 Unix 5.0
+#
+
+#
+# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
+#
+
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+CFLAGS += -mieee -Wall -Wno-format
+else
+CC = cc
+CCC = cxx
+CFLAGS += -ieee -std -pthread
+# LD = cxx
+endif
+
+RANLIB = echo
+MKSHLIB = $(LD) -shared -all -expect_unresolved "*"
+
+#
+# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
+# prtime.c
+#
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D_POSIX4A_DRAFT10_SOURCE -DOSF1 -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl
+
+NOSUCHFILE = /no-such-file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk
new file mode 100644
index 0000000..62f4815
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS4.1.4.mk
@@ -0,0 +1,101 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS4.1
+#
+
+CC = gcc
+CCC = g++
+RANLIB = ranlib
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+# A pile of -D's to build xfe on sunos
+MOZ_CFLAGS = -DSTRINGS_ALIGNED -DNO_REGEX -DNO_ISDIR -DUSE_RE_COMP \
+ -DNO_REGCOMP -DUSE_GETWD -DNO_MEMMOVE -DNO_ALLOCA \
+ -DBOGUS_MB_MAX -DNO_CONST
+
+# Purify doesn't like -MDupdate
+NOMD_OS_CFLAGS = -DXP_UNIX -Wall -Wno-format -DSW_THREADS -DSUNOS4 -DNEED_SYSCALL \
+ $(MOZ_CFLAGS)
+
+OS_CFLAGS = $(NOMD_OS_CFLAGS) -MDupdate $(DEPENDENCIES)
+OS_LIBS = -ldl -lm
+
+MKSHLIB = $(LD) -L$(MOTIF)/lib
+
+HAVE_PURIFY = 1
+MOTIF = /home/motif/usr
+MOTIFLIB = -L$(MOTIF)/lib -lXm
+INCLUDES += -I/usr/X11R5/include -I$(MOTIF)/include
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+LOCALE_MAP = $(DEPTH)/cmd/xfe/intl/sunos.lm
+
+EN_LOCALE = en_US
+DE_LOCALE = de
+FR_LOCALE = fr
+JP_LOCALE = ja
+SJIS_LOCALE = ja_JP.SJIS
+KR_LOCALE = ko
+CN_LOCALE = zh
+TW_LOCALE = zh_TW
+I2_LOCALE = i2
+IT_LOCALE = it
+SV_LOCALE = sv
+ES_LOCALE = es
+NL_LOCALE = nl
+PT_LOCALE = pt
+
+LOC_LIB_DIR = /usr/openwin/lib/locale
+
+BSDECHO = echo
+
+#
+# These defines are for building unix plugins
+#
+BUILD_UNIX_PLUGINS = 1
+DSO_LDOPTS =
+DSO_LDFLAGS =
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk
new file mode 100644
index 0000000..dc0b0a0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.10.mk
@@ -0,0 +1,50 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.10, using vendor gcc and NSPR
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
+
+INCLUDES += -I/usr/sfw/include/mozilla/nspr
+OTHER_LIBS += -L/usr/sfw/lib/mozilla -R/usr/sfw/lib/mozilla
+
+CC=gcc
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk
new file mode 100644
index 0000000..bd615de
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.3.mk
@@ -0,0 +1,91 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.3
+#
+
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+
+#CC = /opt/SUNWspro/SC3.0.1/bin/cc
+RANLIB = echo
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifndef JS_NO_ULTRA
+ULTRA_OPTIONS := -xarch=v8plus
+ULTRA_OPTIONSD := -DULTRA_SPARC
+else
+ULTRA_OPTIONS := -xarch=v8
+ULTRA_OPTIONSD :=
+endif
+
+ifeq ($(OS_CPUARCH),sun4u)
+DEFINES += $(ULTRA_OPTIONSD)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD)
+else
+ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD)
+endif
+endif
+
+ifeq ($(OS_CPUARCH),sun4m)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,-xarch=v8
+else
+ASFLAGS += -xarch=v8
+endif
+endif
+
+MKSHLIB = $(LD) -G
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk
new file mode 100644
index 0000000..de01924
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.4.mk
@@ -0,0 +1,92 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.4
+#
+
+ifdef NS_USE_NATIVE
+CC = cc
+CCC = CC
+else
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+endif
+
+RANLIB = echo
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -D__svr4 -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifndef JS_NO_ULTRA
+ULTRA_OPTIONS := -xarch=v8plus
+ULTRA_OPTIONSD := -DULTRA_SPARC
+else
+ULTRA_OPTIONS := -xarch=v8
+ULTRA_OPTIONSD :=
+endif
+
+ifeq ($(OS_CPUARCH),sun4u)
+DEFINES += $(ULTRA_OPTIONSD)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,$(ULTRA_OPTIONS),$(ULTRA_OPTIONSD)
+else
+ASFLAGS += $(ULTRA_OPTIONS) $(ULTRA_OPTIONSD)
+endif
+endif
+
+ifeq ($(OS_CPUARCH),sun4m)
+ifeq ($(findstring gcc,$(CC)),gcc)
+DEFINES += -Wa,-xarch=v8
+else
+ASFLAGS += -xarch=v8
+endif
+endif
+
+MKSHLIB = $(LD) -G
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk
new file mode 100644
index 0000000..648f72f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.1.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.5.1
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk
new file mode 100644
index 0000000..e26b3a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.5.mk
@@ -0,0 +1,87 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.5
+#
+
+AS = /usr/ccs/bin/as
+ifndef NS_USE_NATIVE
+CC = gcc
+CCC = g++
+CFLAGS += -Wall -Wno-format
+else
+CC = cc
+CCC = CC
+endif
+
+RANLIB = echo
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifeq ($(OS_CPUARCH),sun4u) # ultra sparc?
+ifeq ($(CC),gcc) # using gcc?
+ifndef JS_NO_ULTRA # do we want ultra?
+ifdef JS_THREADSAFE # only in thread-safe mode
+DEFINES += -DULTRA_SPARC
+DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC
+else
+ASFLAGS += -xarch=v8plus -DULTRA_SPARC
+endif
+endif
+endif
+endif
+
+MKSHLIB = $(LD) -G
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk
new file mode 100644
index 0000000..efe1152
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.6.mk
@@ -0,0 +1,89 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.5
+#
+
+AS = /usr/ccs/bin/as
+ifndef NS_USE_NATIVE
+ CC = gcc
+ CCC = g++
+ CFLAGS += -Wall -Wno-format
+else
+ CC = cc
+ CCC = CC
+ CFLAGS += -mt -KPIC
+# LD = CC
+endif
+
+RANLIB = echo
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = sparc
+GFX_ARCH = x
+
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DSOLARIS -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl -ldl
+
+ASFLAGS += -P -L -K PIC -D_ASM -D__STDC__=0
+
+HAVE_PURIFY = 1
+
+NOSUCHFILE = /solaris-rm-f-sucks
+
+ifeq ($(OS_CPUARCH),sun4u) # ultra sparc?
+ifeq ($(CC),gcc) # using gcc?
+ifndef JS_NO_ULTRA # do we want ultra?
+ifdef JS_THREADSAFE # only in thread-safe mode
+DEFINES += -DULTRA_SPARC
+DEFINES += -Wa,-xarch=v8plus,-DULTRA_SPARC
+else
+ASFLAGS += -xarch=v8plus -DULTRA_SPARC
+endif
+endif
+endif
+endif
+
+MKSHLIB = $(LD) -G
+
+# Use the editline library to provide line-editing support.
+JS_EDITLINE = 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk
new file mode 100644
index 0000000..2cb02f2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.7.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.7
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk
new file mode 100644
index 0000000..dd8a32d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.8.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.8
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk
new file mode 100644
index 0000000..b01ec9c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/SunOS5.9.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for SunOS5.9
+#
+
+include $(DEPTH)/config/SunOS5.5.mk
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk
new file mode 100644
index 0000000..1d36f91
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT4.0.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk
new file mode 100644
index 0000000..7681e01
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.0.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk
new file mode 100644
index 0000000..7681e01
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.1.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk
new file mode 100644
index 0000000..5fbcbfe
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT5.2.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS) -DAVMPLUS_WIN32 -DAVMPLUS_IA32
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk
new file mode 100644
index 0000000..7681e01
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/WINNT6.0.mk
@@ -0,0 +1,118 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config for Windows NT using MS Visual C++ (version?)
+#
+
+CC = cl
+CXX = cl
+
+RANLIB = echo
+
+PDBFILE = $(basename $(@F)).pdb
+
+#.c.o:
+# $(CC) -c -MD $*.d $(CFLAGS) $<
+
+CPU_ARCH = x86 # XXX fixme
+GFX_ARCH = win32
+
+# MSVC compiler options for both debug/optimize
+# -nologo - suppress copyright message
+# -W3 - Warning level 3
+# -Gm - enable minimal rebuild
+# -Z7 - put debug info into the executable, not in .pdb file
+# -Zi - put debug info into .pdb file
+# -YX - automatic precompiled headers
+# -GX - enable C++ exception support
+WIN_CFLAGS = -nologo -W3
+
+# MSVC compiler options for debug builds linked to MSVCRTD.DLL
+# -MDd - link with MSVCRTD.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_IDG_CFLAGS = -MDd -Od -Z7
+
+# MSVC compiler options for debug builds linked to MSVCRT.DLL
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, debug C-runtime)
+# -Od - minimal optimization
+WIN_DEBUG_CFLAGS = -MD -Od -Zi -Fd$(OBJDIR)/$(PDBFILE)
+
+# MSVC compiler options for release (optimized) builds
+# -MD - link with MSVCRT.LIB (Dynamically-linked, multi-threaded, C-runtime)
+# -O2 - Optimize for speed
+# -G5 - Optimize for Pentium
+WIN_OPT_CFLAGS = -MD -O2
+
+ifdef BUILD_OPT
+OPTIMIZER = $(WIN_OPT_CFLAGS)
+else
+ifdef BUILD_IDG
+OPTIMIZER = $(WIN_IDG_CFLAGS)
+else
+OPTIMIZER = $(WIN_DEBUG_CFLAGS)
+endif
+endif
+
+OS_CFLAGS = -D_X86_=1 -DXP_WIN -DXP_WIN32 -DWIN32 -D_WINDOWS -D_WIN32 -DWINVER=0x500 -D_WIN32_WINNT=0x500 $(WIN_CFLAGS)
+JSDLL_CFLAGS = -DEXPORT_JS_API
+OS_LIBS = -lm -lc
+
+PREBUILT_CPUCFG = 1
+USE_MSVC = 1
+
+LIB_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib \
+ winmm.lib \
+ -nologo\
+ -subsystem:windows -dll -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+EXE_LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib oldnames.lib -nologo\
+ -subsystem:console -debug -pdb:$(OBJDIR)/$(PDBFILE)\
+ -machine:I386\
+ -opt:ref -opt:noicf
+
+# CAFEDIR = t:/cafe
+# JCLASSPATH = $(CAFEDIR)/Java/Lib/classes.zip
+# JAVAC = $(CAFEDIR)/Bin/sj.exe
+# JAVAH = $(CAFEDIR)/Java/Bin/javah.exe
+# JCFLAGS = -I$(CAFEDIR)/Java/Include -I$(CAFEDIR)/Java/Include/win32
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk
new file mode 100644
index 0000000..3b5967e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/ref-config/dgux.mk
@@ -0,0 +1,64 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# Config stuff for Data General DG/UX
+#
+
+#
+# Initial DG/UX port by Marc Fraioli (fraioli@dg-rtp.dg.com)
+#
+
+AS = as
+CC = gcc
+CCC = g++
+
+RANLIB = echo
+
+#
+# _DGUX_SOURCE is needed to turn on a lot of stuff in the headers if
+# you're not using DG's compiler. It shouldn't hurt if you are.
+#
+# _POSIX4A_DRAFT10_SOURCE is needed to pick up localtime_r, used in
+# prtime.c
+#
+OS_CFLAGS = -DXP_UNIX -DSVR4 -DSYSV -DDGUX -D_DGUX_SOURCE -D_POSIX4A_DRAFT10_SOURCE -DHAVE_LOCALTIME_R
+OS_LIBS = -lsocket -lnsl
+
+NOSUCHFILE = /no-such-file
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/resource.h b/tools/node_modules/expresso/deps/jscoverage/js/resource.h
new file mode 100644
index 0000000..9301810
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by js3240.rc
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/rules.mk b/tools/node_modules/expresso/deps/jscoverage/js/rules.mk
new file mode 100644
index 0000000..5a1e053
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/rules.mk
@@ -0,0 +1,206 @@
+# -*- Mode: makefile -*-
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Mozilla Communicator client code, released
+# March 31, 1998.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998-1999
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Michael Ang <mang@subcarrier.org>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+#
+# JSRef GNUmake makefile rules
+#
+
+ifdef USE_MSVC
+LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CPPFILES:.cpp=.obj))
+PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CPPFILES:.cpp=.obj))
+else
+LIB_OBJS = $(addprefix $(OBJDIR)/, $(LIB_CPPFILES:.cpp=.o))
+LIB_OBJS += $(addprefix $(OBJDIR)/, $(LIB_ASFILES:.s=.o))
+PROG_OBJS = $(addprefix $(OBJDIR)/, $(PROG_CPPFILES:.cpp=.o))
+endif
+
+CPPFILES = $(LIB_CPPFILES) $(PROG_CPPFILES)
+OBJS = $(LIB_OBJS) $(PROG_OBJS)
+
+ifdef USE_MSVC
+# TARGETS = $(LIBRARY) # $(PROGRAM) not supported for MSVC yet
+TARGETS += $(SHARED_LIBRARY) $(PROGRAM) # it is now
+else
+TARGETS += $(LIBRARY) $(SHARED_LIBRARY) $(PROGRAM)
+endif
+
+all:
+ +$(LOOP_OVER_PREDIRS)
+ifneq "$(strip $(TARGETS))" ""
+ $(MAKE) -f Makefile.ref $(TARGETS)
+endif
+ +$(LOOP_OVER_DIRS)
+
+$(OBJDIR)/%: %.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ $(CFLAGS) $(OPTIMIZER) $< $(LDFLAGS)
+
+# This rule must come before the rule with no dep on header
+$(OBJDIR)/%.o: %.cpp %.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/jsinterp.o: jsinterp.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(INTERP_OPTIMIZER) jsinterp.cpp
+
+$(OBJDIR)/jsbuiltins.o: jsbuiltins.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(BUILTINS_OPTIMIZER) jsbuiltins.cpp
+
+$(OBJDIR)/%.o: %.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -o $@ -c $(CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/%.o: %.s
+ @$(MAKE_OBJDIR)
+ $(AS) -o $@ $(ASFLAGS) $<
+
+# This rule must come before rule with no dep on header
+$(OBJDIR)/%.obj: %.cpp %.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/jsinterp.obj: jsinterp.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(INTERP_OPTIMIZER) jsinterp.cpp
+
+$(OBJDIR)/jsbuiltins.obj: jsbuiltins.cpp jsinterp.h
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(BUILTINS_OPTIMIZER) jsbuiltins.cpp
+
+$(OBJDIR)/%.obj: %.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(JSDLL_CFLAGS) $(OPTIMIZER) $<
+
+$(OBJDIR)/js.obj: js.cpp
+ @$(MAKE_OBJDIR)
+ $(CXX) -Fo$(OBJDIR)/ -c $(CFLAGS) $(OPTIMIZER) $<
+
+ifeq ($(OS_ARCH),OS2)
+$(LIBRARY): $(LIB_OBJS)
+ $(AR) $@ $? $(AR_OS2_SUFFIX)
+ $(RANLIB) $@
+else
+ifdef USE_MSVC
+$(SHARED_LIBRARY): $(LIB_OBJS)
+ link.exe $(LIB_LINK_FLAGS) /base:0x61000000 $(OTHER_LIBS) \
+ /out:"$@" /pdb:none\
+ /implib:"$(OBJDIR)/$(@F:.dll=.lib)" $^
+else
+$(LIBRARY): $(LIB_OBJS)
+ $(AR) rv $@ $?
+ $(RANLIB) $@
+
+$(SHARED_LIBRARY): $(LIB_OBJS)
+ $(MKSHLIB) -o $@ $(LIB_OBJS) $(LDFLAGS) $(OTHER_LIBS)
+endif
+endif
+
+# Java stuff
+$(CLASSDIR)/$(OBJDIR)/$(JARPATH)/%.class: %.java
+ mkdir -p $(@D)
+ $(JAVAC) $(JAVAC_FLAGS) $<
+
+define MAKE_OBJDIR
+if test ! -d $(@D); then rm -rf $(@D); mkdir -p $(@D); fi
+endef
+
+ifdef DIRS
+LOOP_OVER_DIRS = \
+ @for d in $(DIRS); do \
+ if test -d $$d; then \
+ set -e; \
+ echo "cd $$d; $(MAKE) -f Makefile.ref $@"; \
+ cd $$d; $(MAKE) -f Makefile.ref $@; cd ..; \
+ set +e; \
+ else \
+ echo "Skipping non-directory $$d..."; \
+ fi; \
+ done
+endif
+
+ifdef PREDIRS
+LOOP_OVER_PREDIRS = \
+ @for d in $(PREDIRS); do \
+ if test -d $$d; then \
+ set -e; \
+ echo "cd $$d; $(MAKE) -f Makefile.ref $@"; \
+ cd $$d; $(MAKE) -f Makefile.ref $@; cd ..; \
+ set +e; \
+ else \
+ echo "Skipping non-directory $$d..."; \
+ fi; \
+ done
+endif
+
+export:
+ +$(LOOP_OVER_PREDIRS)
+ mkdir -p $(DIST)/include $(DIST)/$(LIBDIR) $(DIST)/bin
+ifneq "$(strip $(HFILES))" ""
+ $(CP) $(HFILES) $(DIST)/include
+endif
+ifneq "$(strip $(LIBRARY))" ""
+ $(CP) $(LIBRARY) $(DIST)/$(LIBDIR)
+endif
+ifneq "$(strip $(JARS))" ""
+ $(CP) $(JARS) $(DIST)/$(LIBDIR)
+endif
+ifneq "$(strip $(SHARED_LIBRARY))" ""
+ $(CP) $(SHARED_LIBRARY) $(DIST)/$(LIBDIR)
+endif
+ifneq "$(strip $(PROGRAM))" ""
+ $(CP) $(PROGRAM) $(DIST)/bin
+endif
+ +$(LOOP_OVER_DIRS)
+
+clean:
+ +$(LOOP_OVER_PREDIRS)
+ rm -rf $(OBJS) $(GARBAGE)
+
+clobber:
+ +$(LOOP_OVER_PREDIRS)
+ rm -rf $(OBJS) $(TARGETS) $(DEPENDENCIES) $(GARBAGE)
+ if test -d $(OBJDIR); then rmdir $(OBJDIR); fi
+
+tar:
+ tar cvf $(TARNAME) $(TARFILES)
+ gzip $(TARNAME)
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/time.sh b/tools/node_modules/expresso/deps/jscoverage/js/time.sh
new file mode 100755
index 0000000..05b3499
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/time.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+echo -n interp:' '
+for i in 1 2 3 4 5; do
+ INTERP=`Darwin_OPT.OBJ/js -e 'var d = Date.now(); load("'$1'"); print(Date.now() - d);'`
+ echo -n $INTERP' '
+done
+echo -ne '\njit: '
+for i in 1 2 3 4 5; do
+ JIT=`Darwin_OPT.OBJ/js -j -e 'var d = Date.now(); load("'$1'"); print(Date.now() - d);'`
+ echo -n $JIT' '
+done
+echo -ne '\njit factor: '
+(echo scale=2; echo $INTERP / $JIT ) | bc
diff --git a/tools/node_modules/expresso/deps/jscoverage/js/win32.order b/tools/node_modules/expresso/deps/jscoverage/js/win32.order
new file mode 100644
index 0000000..069403d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/js/win32.order
@@ -0,0 +1,384 @@
+js_MarkGCThing ; 5893956
+JS_GetPrivate ; 2090130
+JS_HashTableRawLookup ; 1709984
+js_Mark ; 1547496
+js_GetToken ; 1406677
+js_UngetToken ; 1154416
+js_MarkAtom ; 992874
+js_MatchToken ; 980277
+js_CompareStrings ; 662772
+js_Lock ; 628184
+js_Unlock ; 628184
+js_HashString ; 611102
+js_DropScopeProperty ; 546476
+JS_malloc ; 484350
+js_InflateStringToBuffer ; 460739
+js_HoldScopeProperty ; 442612
+JS_free ; 382991
+js_MarkScript ; 376942
+js_HashId ; 365238
+JS_CompareValues ; 352366
+js_IdToValue ; 337594
+JS_GetClass ; 325296
+js_LookupProperty ; 324680
+js_GetAtom ; 244669
+js_DropProperty ; 223217
+JS_GetParent ; 209680
+js_LiveContext ; 205767
+js_PeekToken ; 200646
+js_GetSlotThreadSafe ; 198839
+JS_GetStringChars ; 190862
+JS_HashTableRawAdd ; 179156
+js_FoldConstants ; 162626
+js_EmitTree ; 145634
+JS_EnumerateStub ; 140640
+js_NewSrcNote ; 136983
+js_GetProperty ; 135639
+js_NewScopeProperty ; 135057
+js_MutateScope ; 135057
+js_GetMutableScope ; 135057
+js_AllocSlot ; 132401
+JS_GetRuntime ; 127316
+JS_FrameIterator ; 121963
+JS_GetFrameFunctionObject ; 120567
+js_AllocGCThing ; 119828
+js_DestroyScopeProperty ; 115989
+js_Emit3 ; 109135
+JS_HashTableLookup ; 107154
+JS_InstanceOf ; 103905
+js_DefineProperty ; 99514
+js_strncpy ; 88276
+js_PeekTokenSameLine ; 87197
+js_HoldObjectMap ; 79084
+js_DropObjectMap ; 77824
+js_NewObject ; 72421
+js_ValueToString ; 72143
+js_GetClassPrototype ; 66235
+js_UnlockRuntime ; 64699
+js_LockRuntime ; 64699
+js_ContextIterator ; 64586
+JS_ClearWatchPointsForObject ; 64155
+js_FinalizeObject ; 63925
+js_IndexAtom ; 63789
+JS_SetPrivate ; 63702
+JS_GetGlobalObject ; 63546
+js_Emit1 ; 63012
+JS_ContextIterator ; 57847
+JS_GetInstancePrivate ; 57817
+JS_HashTableRawRemove ; 57057
+js_Invoke ; 53568
+js_FindProperty ; 53150
+JS_GetFrameScript ; 51395
+js_LinkFunctionObject ; 50651
+js_SetSrcNoteOffset ; 47735
+js_InWithStatement ; 47346
+js_NewFunction ; 47074
+js_NewSrcNote2 ; 46165
+JS_HashTableAdd ; 45503
+JS_HashTableRemove ; 45213
+js_InCatchBlock ; 42198
+js_AddRootRT ; 40587
+js_AddRoot ; 40587
+js_SetProperty ; 40558
+JS_AddNamedRoot ; 40462
+js_RemoveRoot ; 40384
+JS_RemoveRootRT ; 38129
+js_NewString ; 37471
+js_DefineFunction ; 36629
+JS_GetContextThread ; 36498
+JS_LookupProperty ; 35137
+JS_ValueToString ; 34072
+JS_realloc ; 33776
+JS_DefineFunction ; 33268
+JS_SetErrorReporter ; 32851
+js_FinalizeString ; 30311
+js_FinalizeStringRT ; 30311
+JS_ArenaAllocate ; 30099
+JS_BeginRequest ; 29323
+JS_EndRequest ; 29323
+JS_GetContextPrivate ; 29189
+JS_CompactArenaPool ; 28874
+js_ValueToStringAtom ; 27934
+JS_ValueToId ; 26517
+js_ValueToBoolean ; 25908
+JS_InternString ; 25467
+js_PopStatement ; 24364
+js_PushStatement ; 24364
+js_NewStringCopyN ; 23911
+js_FlushPropertyCacheByProp ; 23883
+js_GetStringBytes ; 23421
+JS_ArenaRelease ; 23267
+JS_GetStringBytes ; 23106
+js_FreeStack ; 22399
+js_AllocStack ; 22399
+JS_SetProperty ; 21240
+js_InitObjectMap ; 19991
+js_NewScope ; 19991
+js_strlen ; 19070
+JS_GetScriptPrincipals ; 18063
+js_SrcNoteLength ; 17369
+js_DestroyObjectMap ; 17198
+js_DestroyScope ; 17198
+JS_GetStringLength ; 16306
+js_PopStatementCG ; 15418
+JS_GetFrameAnnotation ; 14949
+js_Interpret ; 14032
+js_TransferScopeLock ; 13899
+JS_ResolveStandardClass ; 13645
+JS_ResumeRequest ; 12837
+JS_SuspendRequest ; 12837
+JS_GetProperty ; 12488
+JS_NewObject ; 11660
+js_AllocTryNotes ; 11418
+js_NewNumberValue ; 10859
+js_InternalInvoke ; 10051
+js_NewDouble ; 9936
+js_SetJumpOffset ; 9886
+js_SkipWhiteSpace ; 9299
+js_NewDoubleValue ; 7474
+JS_GetPendingException ; 7404
+js_NewObjectMap ; 7236
+JS_ClearPendingException ; 7092
+JS_strtod ; 7053
+js_strtod ; 7053
+js_InflateString ; 7004
+JS_GetFunctionName ; 6808
+JS_NewHashTable ; 6794
+JS_NewFunction ; 6575
+js_FreeSlot ; 6476
+js_LockScope ; 6332
+JS_HashTableEnumerateEntries ; 6285
+js_GetLengthProperty ; 6162
+js_LockObj ; 6149
+JS_NewUCStringCopyN ; 5994
+JS_NewNumberValue ; 5904
+js_NewStringCopyZ ; 5809
+JS_NewUCStringCopyZ ; 5809
+js_DeflateString ; 5612
+js_ValueToNumber ; 5456
+JS_SetOptions ; 5322
+js_NewScript ; 4941
+js_InitCodeGenerator ; 4810
+js_FinishTakingSrcNotes ; 4810
+js_NewScriptFromParams ; 4810
+js_FinishTakingTryNotes ; 4810
+js_NewScriptFromCG ; 4810
+js_FinishCodeGenerator ; 4810
+JS_strdup ; 4534
+JS_HashTableDestroy ; 4119
+js_CheckRedeclaration ; 3965
+JS_DefineFunctions ; 3808
+js_EmitFunctionBody ; 3739
+js_TryMethod ; 3685
+js_DefaultValue ; 3610
+js_CloneFunctionObject ; 3577
+JS_InitClass ; 3546
+js_SetClassPrototype ; 3377
+JS_GetPrototype ; 3268
+JS_DefineProperties ; 3115
+js_FindVariable ; 3093
+js_DestroyScript ; 3041
+JS_ClearScriptTraps ; 3041
+js_FreeAtomMap ; 3041
+JS_NewStringCopyZ ; 2953
+js_AtomizeObject ; 2709
+JS_ValueToBoolean ; 2643
+js_SetLengthProperty ; 2637
+JS_GetOptions ; 2593
+js_ValueToObject ; 2522
+js_ValueToNonNullObject ; 2510
+js_StringToObject ; 2482
+JS_SetElement ; 2448
+js_NumberToString ; 2407
+JS_TypeOfValue ; 2275
+js_NewBufferTokenStream ; 2253
+js_NewTokenStream ; 2253
+js_CloseTokenStream ; 2253
+JS_RemoveRoot ; 2148
+JS_NewDouble ; 2129
+JS_vsnprintf ; 1937
+JS_snprintf ; 1937
+JS_CallFunctionValue ; 1844
+JS_DHashVoidPtrKeyStub ; 1840
+JS_DHashTableOperate ; 1840
+js_SetProtoOrParent ; 1758
+js_DoubleToInteger ; 1729
+JS_SetVersion ; 1531
+js_ValueToFunction ; 1476
+JS_SetPrototype ; 1408
+JS_CeilingLog2 ; 1317
+js_Execute ; 1199
+js_CompileFunctionBody ; 1182
+JS_CompileUCFunctionForPrincipals ; 1182
+js_GetSrcNoteOffset ; 1139
+JS_DHashMatchEntryStub ; 1094
+JS_VersionToString ; 1090
+JS_CompileUCScriptForPrincipals ; 1071
+js_CompileTokenStream ; 1071
+js_CurrentThreadId ; 1058
+JS_IdToValue ; 1046
+js_ConstructObject ; 974
+JS_DestroyScript ; 967
+js_PCToLineNumber ; 967
+JS_DefineProperty ; 930
+JS_GetScriptFilename ; 924
+JS_GetFramePC ; 899
+JS_EvaluateUCScriptForPrincipals ; 892
+JS_PCToLineNumber ; 848
+JS_StringToVersion ; 761
+js_ExecuteRegExp ; 755
+JS_MaybeGC ; 717
+JS_ValueToNumber ; 698
+JS_GetVersion ; 698
+JS_AliasProperty ; 693
+js_AtomizeValue ; 664
+js_BooleanToString ; 664
+js_SetSlotThreadSafe ; 596
+JS_DHashClearEntryStub ; 584
+JS_DHashTableRawRemove ; 584
+JS_DefineObject ; 557
+js_PutCallObject ; 516
+js_GetCallObject ; 516
+js_strchr ; 511
+JS_DefineUCProperty ; 480
+JS_dtostr ; 475
+JS_ValueToInt32 ; 464
+js_ValueToInt32 ; 464
+JS_FinishArenaPool ; 453
+js_NewTryNote ; 441
+js_strtointeger ; 437
+JS_vsmprintf ; 428
+JS_DHashTableInit ; 423
+JS_DHashAllocTable ; 423
+JS_DHashGetStubOps ; 423
+JS_NewDHashTable ; 423
+JS_DHashTableDestroy ; 423
+JS_DHashFreeTable ; 423
+JS_DHashTableFinish ; 423
+js_EmitBreak ; 412
+js_GetAttributes ; 412
+JS_DefineConstDoubles ; 407
+JS_ArenaGrow ; 374
+js_AtomizeInt ; 372
+JS_SetParent ; 345
+JS_CloneFunctionObject ; 343
+JS_IsNativeFrame ; 343
+JS_ReportErrorNumber ; 340
+js_ErrorToException ; 340
+js_ReportErrorNumberVA ; 340
+js_GetErrorMessage ; 340
+js_ExpandErrorArguments ; 340
+js_ReportUncaughtException ; 315
+JS_IsExceptionPending ; 315
+js_ReportErrorAgain ; 315
+js_ErrorFromException ; 315
+JS_LookupUCProperty ; 307
+JS_InitArenaPool ; 293
+PRMJ_Now ; 262
+DllMain@12 ; 235
+JS_ExecuteScript ; 232
+JS_GetFrameFunction ; 226
+PRMJ_LocalGMTDifference ; 175
+JS_GetConstructor ; 175
+JS_SetGlobalObject ; 164
+js_LockGCThing ; 155
+js_NewRegExpObject ; 152
+js_NewRegExp ; 152
+js_InitObjectClass ; 131
+js_InitFunctionClass ; 131
+js_EmitN ; 128
+JS_ArenaFinish ; 124
+js_GC ; 124
+js_SweepAtomState ; 124
+js_MarkAtomState ; 124
+JS_ArenaRealloc ; 124
+js_ForceGC ; 124
+js_FlushPropertyCache ; 122
+js_InitNumberClass ; 114
+JS_smprintf ; 112
+js_DoubleToECMAInt32 ; 112
+js_ValueToECMAInt32 ; 111
+JS_ValueToECMAInt32 ; 111
+JS_SetContextPrivate ; 109
+PRMJ_DSTOffset ; 108
+js_Clear ; 105
+JS_ClearScope ; 105
+JS_NewScriptObject ; 104
+JS_smprintf_free ; 104
+JS_ConvertValue ; 99
+js_GetSrcNote ; 98
+JS_ValueToECMAUint32 ; 93
+js_ValueToECMAUint32 ; 93
+js_printf ; 93
+js_DoubleToECMAUint32 ; 93
+js_DestroyRegExp ; 89
+js_UnlockGCThing ; 89
+js_TryValueOf ; 87
+js_NewSrcNote3 ; 86
+JS_ConvertStub ; 81
+JS_SetPendingException ; 80
+js_InitStringClass ; 79
+JS_GC ; 78
+js_InitArrayClass ; 74
+js_InitDateClass ; 67
+JS_NewContext ; 64
+JS_AddArgumentFormatter ; 64
+js_InitContextForLocking ; 64
+js_NewContext ; 64
+JS_SetBranchCallback ; 64
+JS_ClearRegExpStatics ; 64
+js_InitRegExpStatics ; 64
+js_InitCallClass ; 63
+js_InitRegExpClass ; 61
+js_Enumerate ; 58
+JS_DestroyContext ; 46
+js_DestroyContext ; 46
+js_FreeRegExpStatics ; 46
+js_InitScanner ; 39
+js_NewPrinter ; 36
+js_DestroyPrinter ; 36
+js_GetPrinterOutput ; 36
+JS_FreeArenaPool ; 36
+js_DecompileCode ; 34
+js_EmitContinue ; 33
+js_CheckAccess ; 30
+js_DecompileValueGenerator ; 28
+js_InitMathClass ; 27
+js_InitExceptionClasses ; 25
+js_NewArrayObject ; 24
+js_InitArgumentsClass ; 21
+js_puts ; 20
+js_InitBooleanClass ; 19
+JS_InitStandardClasses ; 19
+js_InitScriptClass ; 19
+js_obj_toString ; 15
+js_GetArgsValue ; 14
+js_GetArgsObject ; 14
+JS_DestroyIdArray ; 11
+js_NewIdArray ; 11
+JS_GetElement ; 11
+JS_EvaluateScript ; 9
+JS_EvaluateUCScript ; 9
+JS_DecompileFunction ; 8
+js_DecompileFunction ; 8
+JS_NewString ; 8
+js_SetStringBytes ; 8
+JS_GetArrayLength ; 7
+JS_NewArrayObject ; 7
+JS_IsArrayObject ; 7
+JS_ValueToObject ; 7
+JS_DefineElement ; 6
+js_DecompileScript ; 6
+JS_PushArguments ; 4
+JS_PopArguments ; 4
+JS_PushArgumentsVA ; 4
+js_PutArgsObject ; 2
+JS_SetGCCallbackRT ; 2
+JS_Init ; 1
+js_SetupLocks ; 1
+js_InitRuntimeNumberState ; 1
+js_InitRuntimeStringState ; 1
+js_InitLock ; 1
+js_InitGC ; 1
+js_InitAtomState ; 1
+js_InitStringGlobals ; 1
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt b/tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt
new file mode 100644
index 0000000..e20938b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-help.txt
@@ -0,0 +1,12 @@
+Usage: jscoverage SOURCE-DIRECTORY DESTINATION-DIRECTORY
+Instrument JavaScript with code coverage information.
+
+Options:
+ --encoding=ENCODING assume .js files use the given character encoding
+ --exclude=PATH do not copy PATH
+ --js-version=VERSION use the specified JavaScript version
+ --no-highlight do not perform syntax highlighting
+ --no-instrument=PATH copy but do not instrument PATH
+ -v, --verbose explain what is being done
+ -h, --help display this help and exit
+ -V, --version display version information and exit
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css b/tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css
new file mode 100644
index 0000000..31a4695
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-highlight.css
@@ -0,0 +1,38 @@
+/*
+ jscoverage-highlight.css - JSCoverage syntax highlighting style sheet
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* keyword, type, symbol, cbracket */
+#sourceTable .k {
+ font-weight: bold;
+}
+
+/* string, regexp, number */
+#sourceTable .s {
+ color: #006400;
+}
+
+/* specialchar */
+#sourceTable .t {
+ color: #2e8b57;
+}
+
+/* comment */
+#sourceTable .c {
+ font-style: italic;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css b/tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css
new file mode 100644
index 0000000..afb2b80
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-ie.css
@@ -0,0 +1,89 @@
+#headingDiv {
+ position: static;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 0.5em;
+}
+
+#tabs {
+ clear: all;
+ position: static;
+ top: auto;
+ left: auto;
+ right: auto;
+ height: auto;
+ margin-left: 10px;
+ margin-right: 10px;
+}
+
+#tabs div {
+ position: relative;
+ height: auto;
+ line-height: normal;
+ padding-top: 5px;
+ padding-bottom: 5px;
+}
+
+#tabs div.selected {
+ padding-bottom: 6px;
+ z-index: 2;
+}
+
+.TabPage {
+ position: relative;
+ top: -1px;
+ left: auto;
+ right: auto;
+ bottom: auto;
+ clear: left;
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 10px;
+ z-index: 1;
+}
+
+#locationDiv {
+ margin-bottom: 10px;
+}
+
+#iframeDiv {
+ position: static;
+ width: 100%;
+}
+
+#summaryDiv {
+ position: static;
+ width: 100%;
+}
+
+#fileDiv {
+ margin-bottom: 10px;
+}
+
+#sourceDiv {
+ position: static;
+ width: 100%;
+}
+
+#storeDiv {
+ position: static;
+ width: 100%;
+}
+
+/* some defaults */
+
+.TabPage {
+ height: 650px;
+}
+
+#iframeDiv {
+ height: 600px;
+}
+
+#summaryDiv {
+ height: 600px;
+}
+
+#sourceDiv {
+ height: 600px;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js b/tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js
new file mode 100644
index 0000000..35e6181
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-overlay.js
@@ -0,0 +1,211 @@
+/*
+ jscoverage-overlay.js - script for XUL overlay
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+Components.utils.import('resource://gre/modules/jscoverage.jsm');
+
+// https://developer.mozilla.org/en/Code_snippets/Tabbed_browser
+function openAndReuseOneTabPerURL(url) {
+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator);
+ var browserEnumerator = wm.getEnumerator("navigator:browser");
+
+ // Check each browser instance for our URL
+ var found = false;
+ while (!found && browserEnumerator.hasMoreElements()) {
+ var browserWin = browserEnumerator.getNext();
+ var tabbrowser = browserWin.getBrowser();
+
+ // Check each tab of this browser instance
+ var numTabs = tabbrowser.browsers.length;
+ for(var index=0; index<numTabs; index++) {
+ var currentBrowser = tabbrowser.getBrowserAtIndex(index);
+ if (url == currentBrowser.currentURI.spec) {
+
+ // The URL is already opened. Select this tab.
+ tabbrowser.selectedTab = tabbrowser.mTabs[index];
+
+ // Focus *this* browser-window
+ browserWin.focus();
+
+ found = true;
+ break;
+ }
+ }
+ }
+
+ // Our URL isn't open. Open it now.
+ if (!found) {
+ var recentWindow = wm.getMostRecentWindow("navigator:browser");
+ if (recentWindow) {
+ // Use an existing browser window
+ recentWindow.delayedOpenTab(url, null, null, null, null);
+ }
+ else {
+ // No browser windows are open, so open a new one.
+ window.open(url);
+ }
+ }
+}
+
+function jscoverage_view() {
+ openAndReuseOneTabPerURL('chrome://jscoverage/content/jscoverage.html');
+}
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ case '\v':
+ return '\\v';
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_store() {
+ try {
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+
+ var directoryService = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties);
+ var reportDirectory = directoryService.get('CurWorkD', Ci.nsILocalFile);
+ reportDirectory.appendRelativePath('jscoverage-report');
+ if (! reportDirectory.exists()) {
+ reportDirectory.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
+ }
+
+ var ioService = Cc['@mozilla.org/network/io-service;1'].getService(Ci.nsIIOService);
+ var copyChrome = function(filename) {
+ var channel = ioService.newChannel('chrome://jscoverage/content/' + filename, null, null);
+ var binaryInputStream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
+ try {
+ binaryInputStream.setInputStream(channel.open());
+
+ var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
+ file.initWithFile(reportDirectory);
+ file.appendRelativePath(filename);
+ var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
+ fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
+ var binaryOutputStream = Cc['@mozilla.org/binaryoutputstream;1'].createInstance(Ci.nsIBinaryOutputStream);
+ try {
+ binaryOutputStream.setOutputStream(fileOutputStream);
+
+ for (;;) {
+ var available = binaryInputStream.available();
+ if (available === 0) {
+ break;
+ }
+ var bytes = binaryInputStream.readBytes(available);
+ binaryOutputStream.writeBytes(bytes, bytes.length);
+ }
+
+ if (filename === 'jscoverage.js') {
+ var s = 'jscoverage_isReport = true;\n';
+ binaryOutputStream.write(s, s.length);
+ }
+ }
+ finally {
+ binaryOutputStream.close();
+ }
+ }
+ finally {
+ binaryInputStream.close();
+ }
+ };
+ copyChrome('jscoverage.html');
+ copyChrome('jscoverage.js');
+ copyChrome('jscoverage.css');
+ copyChrome('jscoverage-throbber.gif');
+ copyChrome('jscoverage-highlight.css');
+
+ // write the coverage data
+ var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsILocalFile);
+ file.initWithFile(reportDirectory);
+ file.appendRelativePath('jscoverage.json');
+ var fileOutputStream = Cc['@mozilla.org/network/file-output-stream;1'].createInstance(Ci.nsIFileOutputStream);
+ try {
+ fileOutputStream.init(file, 0x02 | 0x08 | 0x20, 0644, 0);
+ function write(s) {
+ fileOutputStream.write(s, s.length);
+ }
+ write('{');
+ var first = true;
+ for (var file in _$jscoverage) {
+ if (first) {
+ first = false;
+ }
+ else {
+ write(',');
+ }
+ write(jscoverage_quote(file));
+ write(':{"coverage":[');
+ var coverage = _$jscoverage[file];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ if (line > 0) {
+ write(',');
+ }
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ write(value.toString());
+ }
+ write('],"source":[');
+ var source = coverage.source;
+ length = source.length;
+ for (line = 0; line < length; line++) {
+ if (line > 0) {
+ write(',');
+ }
+ write(jscoverage_quote(source[line]));
+ }
+ write(']}');
+ }
+ write('}');
+ alert('Coverage data stored.');
+ }
+ finally {
+ fileOutputStream.close();
+ }
+ }
+ catch (e) {
+ alert(e);
+ dump(e);
+ dump('\n');
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server
new file mode 100755
index 0000000..fabccc7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt
new file mode 100644
index 0000000..98415b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server-help.txt
@@ -0,0 +1,17 @@
+Usage: jscoverage-server [OPTION]...
+Run a server for instrumenting JavaScript with code coverage information.
+
+Options:
+ --document-root=DIR serve content from DIR (default: current directory)
+ --encoding=ENCODING assume .js files use the given character encoding
+ --ip-address=ADDRESS bind to ADDRESS (default: 127.0.0.1)
+ --js-version=VERSION use the specified JavaScript version
+ --no-highlight do not perform syntax highlighting
+ --no-instrument=URL do not instrument URL
+ --port=PORT use PORT for TCP port (default: 8080)
+ --proxy run as a proxy
+ --report-dir=DIR store report to DIR (default: `jscoverage-report')
+ --shutdown stop a running server
+ -v, --verbose explain what is being done
+ -h, --help display this help and exit
+ -V, --version display version information and exit
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.1 b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.1
new file mode 100644
index 0000000..cfb4b09
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.1
@@ -0,0 +1,79 @@
+.TH jscoverage-server 1 local
+.SH NAME
+jscoverage-server \- Run a server for instrumenting JavaScript with code coverage information
+
+.SH SYNOPSIS
+jscoverage-server [OPTION]...
+
+.SH DESCRIPTION
+
+jscoverage-server is a simple web server that instruments JavaScript code as it is served.
+
+.SH OPTIONS
+
+.TP
+.B --document-root=DIR
+serve content from
+.B DIR
+(default: current directory).
+
+.TP
+.B --encoding=ENCODING
+assume .js files use the given character encoding.
+
+.TP
+.B --ip-address=ADDRESS
+bind to
+.B ADDRESS
+(default: 127.0.0.1).
+
+.TP
+.B --js-version=VERSION
+use the specified JavaScript version; valid values for
+.B VERSION
+are 1.0, 1.1, 1.2, ..., 1.8, or ECMAv3 (the default).
+
+.TP
+.B --no-highlight
+do not perform syntax highlighting.
+
+.TP
+.B --no-instrument=URL
+do not instrument
+.B URL.
+
+.TP
+.B --port=PORT
+use
+.B PORT
+for TCP port (default: 8080).
+
+.TP
+.B --proxy
+run as a proxy.
+
+.TP
+.B --report-dir=DIR
+store report to
+.B DIR
+(default: jscoverage-report).
+
+.TP
+.B --shutdown
+stop a running server.
+
+.TP
+.B -v, --verbose
+explain what is being done.
+
+.TP
+.B -h, --help
+display this help and exit.
+
+.TP
+.B -V, --version
+display version information and exit.
+.
+.SH AUTHORS
+
+siliconforks.com
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c
new file mode 100644
index 0000000..7fc02bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-server.c
@@ -0,0 +1,1307 @@
+/*
+ jscoverage-server.c - JSCoverage server main routine
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <dirent.h>
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#include "encoding.h"
+#include "global.h"
+#include "http-server.h"
+#include "instrument-js.h"
+#include "resource-manager.h"
+#include "stream.h"
+#include "util.h"
+
+static const char * specified_encoding = NULL;
+const char * jscoverage_encoding = "ISO-8859-1";
+bool jscoverage_highlight = true;
+
+typedef struct SourceCache {
+ char * url;
+ uint16_t * characters;
+ size_t num_characters;
+ struct SourceCache * next;
+} SourceCache;
+
+static SourceCache * source_cache = NULL;
+
+static const struct {
+ const char * extension;
+ const char * mime_type;
+} mime_types[] = {
+ {".gif", "image/gif"},
+ {".jpg", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".png", "image/png"},
+ {".css", "text/css"},
+ {".html", "text/html"},
+ {".htm", "text/html"},
+ {".js", "text/javascript"},
+ {".txt", "text/plain"},
+ {".xml", "application/xml"},
+};
+
+static bool verbose = false;
+static const char * report_directory = "jscoverage-report";
+static const char * document_root = ".";
+static bool proxy = false;
+static const char ** no_instrument;
+static size_t num_no_instrument = 0;
+
+#ifdef __MINGW32__
+CRITICAL_SECTION javascript_mutex;
+CRITICAL_SECTION source_cache_mutex;
+#define LOCK EnterCriticalSection
+#define UNLOCK LeaveCriticalSection
+#else
+pthread_mutex_t javascript_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t source_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define LOCK pthread_mutex_lock
+#define UNLOCK pthread_mutex_unlock
+#endif
+
+static const SourceCache * find_cached_source(const char * url) {
+ SourceCache * result = NULL;
+ LOCK(&source_cache_mutex);
+ for (SourceCache * p = source_cache; p != NULL; p = p->next) {
+ if (strcmp(url, p->url) == 0) {
+ result = p;
+ break;
+ }
+ }
+ UNLOCK(&source_cache_mutex);
+ return result;
+}
+
+static void add_cached_source(const char * url, uint16_t * characters, size_t num_characters) {
+ SourceCache * new_source_cache = xmalloc(sizeof(SourceCache));
+ new_source_cache->url = xstrdup(url);
+ new_source_cache->characters = characters;
+ new_source_cache->num_characters = num_characters;
+ LOCK(&source_cache_mutex);
+ new_source_cache->next = source_cache;
+ source_cache = new_source_cache;
+ UNLOCK(&source_cache_mutex);
+}
+
+static int get(const char * url, uint16_t ** characters, size_t * num_characters) __attribute__((warn_unused_result));
+
+static int get(const char * url, uint16_t ** characters, size_t * num_characters) {
+ char * host = NULL;
+ uint16_t port;
+ char * abs_path = NULL;
+ char * query = NULL;
+ HTTPConnection * connection = NULL;
+ HTTPExchange * exchange = NULL;
+ Stream * stream = NULL;
+
+ int result = URL_parse(url, &host, &port, &abs_path, &query);
+ if (result != 0) {
+ goto done;
+ }
+
+ connection = HTTPConnection_new_client(host, port);
+ if (connection == NULL) {
+ result = -1;
+ goto done;
+ }
+
+ exchange = HTTPExchange_new(connection);
+ HTTPExchange_set_request_uri(exchange, url);
+ result = HTTPExchange_write_request_headers(exchange);
+ if (result != 0) {
+ goto done;
+ }
+
+ result = HTTPExchange_read_response_headers(exchange);
+ if (result != 0) {
+ goto done;
+ }
+
+ stream = Stream_new(0);
+ result = HTTPExchange_read_entire_response_entity_body(exchange, stream);
+ if (result != 0) {
+ goto done;
+ }
+ char * encoding = HTTPMessage_get_charset(HTTPExchange_get_response_message(exchange));
+ if (encoding == NULL) {
+ encoding = xstrdup(jscoverage_encoding);
+ }
+ result = jscoverage_bytes_to_characters(encoding, stream->data, stream->length, characters, num_characters);
+ free(encoding);
+ if (result != 0) {
+ goto done;
+ }
+
+ result = 0;
+
+done:
+ if (stream != NULL) {
+ Stream_delete(stream);
+ }
+ if (exchange != NULL) {
+ HTTPExchange_delete(exchange);
+ }
+ if (connection != NULL) {
+ if (HTTPConnection_delete(connection) != 0) {
+ HTTPServer_log_err("Warning: error closing connection after retrieving URL: %s\n", url);
+ }
+ }
+ free(host);
+ free(abs_path);
+ free(query);
+ return result;
+}
+
+static void send_response(HTTPExchange * exchange, uint16_t status_code, const char * html) {
+ HTTPExchange_set_status_code(exchange, status_code);
+ if (HTTPExchange_write_response(exchange, html, strlen(html)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+}
+
+/*
+RFC 2396, Appendix A: we are checking for `pchar'
+*/
+static bool is_escaped(char c) {
+ /* `pchar' */
+ if (strchr(":@&=+$,", c) != NULL) {
+ return false;
+ }
+
+ if (isalnum((unsigned char) c)) {
+ return false;
+ }
+
+ /* `mark' */
+ if (strchr("-_.!~*'()", c) != NULL) {
+ return false;
+ }
+
+ return true;
+}
+
+static char * encode_uri_component(const char * s) {
+ size_t length = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ if (is_escaped(*p)) {
+ length = addst(length, 3);
+ }
+ else {
+ length = addst(length, 1);
+ }
+ }
+
+ length = addst(length, 1);
+ char * result = xmalloc(length);
+ size_t i = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ if (is_escaped(*p)) {
+ result[i] = '%';
+ i++;
+ snprintf(result + i, 3, "%02X", *p);
+ i += 2;
+ }
+ else {
+ result[i] = *p;
+ i++;
+ }
+ }
+ result[i] = '\0';
+
+ return result;
+}
+
+static unsigned int hex_value(char c) {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ }
+ else if ('A' <= c && c <= 'F') {
+ return c - 'A' + 10;
+ }
+ else if ('a' <= c && c <= 'f') {
+ return c - 'a' + 10;
+ }
+ else {
+ return 0;
+ }
+}
+
+static char * decode_uri_component(const char * s) {
+ size_t length = strlen(s);
+ char * result = xmalloc(length + 1);
+ char * p = result;
+ while (*s != '\0') {
+ if (*s == '%') {
+ if (s[1] == '\0' || s[2] == '\0') {
+ *p = '\0';
+ return result;
+ }
+ *p = hex_value(s[1]) * 16 + hex_value(s[2]);
+ s += 2;
+ }
+ else {
+ *p = *s;
+ }
+ p++;
+ s++;
+ }
+ *p = '\0';
+ return result;
+}
+
+static const char * get_entity(char c) {
+ switch(c) {
+ case '<':
+ return "&lt;";
+ case '>':
+ return "&gt;";
+ case '&':
+ return "&amp;";
+ case '\'':
+ return "&apos;";
+ case '"':
+ return "&quot;";
+ default:
+ return NULL;
+ }
+}
+
+static char * encode_html(const char * s) {
+ size_t length = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ const char * entity = get_entity(*p);
+ if (entity == NULL) {
+ length = addst(length, 1);
+ }
+ else {
+ length = addst(length, strlen(entity));
+ }
+ }
+
+ length = addst(length, 1);
+ char * result = xmalloc(length);
+ size_t i = 0;
+ for (const char * p = s; *p != '\0'; p++) {
+ const char * entity = get_entity(*p);
+ if (entity == NULL) {
+ result[i] = *p;
+ i++;
+ }
+ else {
+ strcpy(result + i, entity);
+ i += strlen(entity);
+ }
+ }
+ result[i] = '\0';
+
+ return result;
+}
+
+static const char * get_content_type(const char * path) {
+ char * last_dot = strrchr(path, '.');
+ if (last_dot == NULL) {
+ return "application/octet-stream";
+ }
+ for (size_t i = 0; i < sizeof(mime_types) / sizeof(mime_types[0]); i++) {
+ if (strcmp(last_dot, mime_types[i].extension) == 0) {
+ return mime_types[i].mime_type;
+ }
+ }
+ return "application/octet-stream";
+}
+
+/**
+Checks whether a URI is on the no-instrument list.
+@param uri the HTTP "Request-URI"; must not be NULL, and must not be a zero-length string
+@return true if the URI is on the no-instrument list, false otherwise
+*/
+static bool is_no_instrument(const char * uri) {
+ assert(*uri != '\0');
+
+ for (size_t i = 0; i < num_no_instrument; i++) {
+ if (str_starts_with(uri, no_instrument[i])) {
+ return true;
+ }
+
+ /*
+ For a local URL, accept "/foo/bar" and "foo/bar" on the no-instrument list.
+ */
+ if (! proxy && str_starts_with(uri + 1, no_instrument[i])) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool is_javascript(HTTPExchange * exchange) {
+ const char * header = HTTPExchange_find_response_header(exchange, HTTP_CONTENT_TYPE);
+ if (header == NULL) {
+ /* guess based on extension */
+ return str_ends_with(HTTPExchange_get_request_uri(exchange), ".js");
+ }
+ else {
+ char * semicolon = strchr(header, ';');
+ char * content_type;
+ if (semicolon == NULL) {
+ content_type = xstrdup(header);
+ }
+ else {
+ content_type = xstrndup(header, semicolon - header);
+ }
+ /* RFC 4329 */
+ bool result = strcmp(content_type, "text/javascript") == 0 ||
+ strcmp(content_type, "text/ecmascript") == 0 ||
+ strcmp(content_type, "text/javascript1.0") == 0 ||
+ strcmp(content_type, "text/javascript1.1") == 0 ||
+ strcmp(content_type, "text/javascript1.2") == 0 ||
+ strcmp(content_type, "text/javascript1.3") == 0 ||
+ strcmp(content_type, "text/javascript1.4") == 0 ||
+ strcmp(content_type, "text/javascript1.5") == 0 ||
+ strcmp(content_type, "text/jscript") == 0 ||
+ strcmp(content_type, "text/livescript") == 0 ||
+ strcmp(content_type, "text/x-javascript") == 0 ||
+ strcmp(content_type, "text/x-ecmascript") == 0 ||
+ strcmp(content_type, "application/x-javascript") == 0 ||
+ strcmp(content_type, "application/x-ecmascript") == 0 ||
+ strcmp(content_type, "application/javascript") == 0 ||
+ strcmp(content_type, "application/ecmascript") == 0;
+ free(content_type);
+ return result;
+ }
+}
+
+static bool should_instrument_request(HTTPExchange * exchange) {
+ if (! is_javascript(exchange)) {
+ return false;
+ }
+
+ if (is_no_instrument(HTTPExchange_get_request_uri(exchange))) {
+ return false;
+ }
+
+ return true;
+}
+
+static int merge(Coverage * coverage, FILE * f) __attribute__((warn_unused_result));
+
+static int merge(Coverage * coverage, FILE * f) {
+ Stream * stream = Stream_new(0);
+ Stream_write_file_contents(stream, f);
+
+ LOCK(&javascript_mutex);
+ int result = jscoverage_parse_json(coverage, stream->data, stream->length);
+ UNLOCK(&javascript_mutex);
+
+ Stream_delete(stream);
+ return result;
+}
+
+static void write_js_quoted_string(FILE * f, char * data, size_t length) {
+ putc('"', f);
+ for (size_t i = 0; i < length; i++) {
+ char c = data[i];
+ switch (c) {
+ case '\b':
+ fputs("\\b", f);
+ break;
+ case '\f':
+ fputs("\\f", f);
+ break;
+ case '\n':
+ fputs("\\n", f);
+ break;
+ case '\r':
+ fputs("\\r", f);
+ break;
+ case '\t':
+ fputs("\\t", f);
+ break;
+ /* IE doesn't support this */
+ /*
+ case '\v':
+ fputs("\\v", f);
+ break;
+ */
+ case '"':
+ fputs("\\\"", f);
+ break;
+ case '\\':
+ fputs("\\\\", f);
+ break;
+ default:
+ putc(c, f);
+ break;
+ }
+ }
+ putc('"', f);
+}
+
+static void write_source(const char * id, const uint16_t * characters, size_t num_characters, FILE * f) {
+ Stream * output = Stream_new(num_characters);
+ jscoverage_write_source(id, characters, num_characters, output);
+ fwrite(output->data, 1, output->length, f);
+ Stream_delete(output);
+}
+
+static void write_json_for_file(const FileCoverage * file_coverage, int i, void * p) {
+ FILE * f = p;
+
+ if (i > 0) {
+ putc(',', f);
+ }
+
+ write_js_quoted_string(f, file_coverage->id, strlen(file_coverage->id));
+
+ fputs(":{\"coverage\":[", f);
+ for (uint32_t i = 0; i < file_coverage->num_coverage_lines; i++) {
+ if (i > 0) {
+ putc(',', f);
+ }
+ int timesExecuted = file_coverage->coverage_lines[i];
+ if (timesExecuted < 0) {
+ fputs("null", f);
+ }
+ else {
+ fprintf(f, "%d", timesExecuted);
+ }
+ }
+ fputs("],\"source\":", f);
+ if (file_coverage->source_lines == NULL) {
+ if (proxy) {
+ const SourceCache * cached = find_cached_source(file_coverage->id);
+ if (cached == NULL) {
+ uint16_t * characters;
+ size_t num_characters;
+ if (get(file_coverage->id, &characters, &num_characters) == 0) {
+ write_source(file_coverage->id, characters, num_characters, f);
+ add_cached_source(file_coverage->id, characters, num_characters);
+ }
+ else {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: cannot retrieve URL: %s\n", file_coverage->id);
+ }
+ }
+ else {
+ write_source(file_coverage->id, cached->characters, cached->num_characters, f);
+ }
+ }
+ else {
+ /* check that the path begins with / */
+ if (file_coverage->id[0] == '/') {
+ char * source_path = make_path(document_root, file_coverage->id + 1);
+ FILE * source_file = fopen(source_path, "rb");
+ free(source_path);
+ if (source_file == NULL) {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: cannot open file: %s\n", file_coverage->id);
+ }
+ else {
+ Stream * stream = Stream_new(0);
+ Stream_write_file_contents(stream, source_file);
+ fclose(source_file);
+ uint16_t * characters;
+ size_t num_characters;
+ int result = jscoverage_bytes_to_characters(jscoverage_encoding, stream->data, stream->length, &characters, &num_characters);
+ Stream_delete(stream);
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: encoding %s not supported\n", jscoverage_encoding);
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: error decoding %s in file %s\n", jscoverage_encoding, file_coverage->id);
+ }
+ else {
+ write_source(file_coverage->id, characters, num_characters, f);
+ free(characters);
+ }
+ }
+ }
+ else {
+ /* path does not begin with / */
+ fputs("[]", f);
+ HTTPServer_log_err("Warning: invalid source path: %s\n", file_coverage->id);
+ }
+ }
+ }
+ else {
+ fputc('[', f);
+ for (uint32_t i = 0; i < file_coverage->num_source_lines; i++) {
+ if (i > 0) {
+ fputc(',', f);
+ }
+ char * source_line = file_coverage->source_lines[i];
+ write_js_quoted_string(f, source_line, strlen(source_line));
+ }
+ fputc(']', f);
+ }
+ fputc('}', f);
+}
+
+static int write_json(Coverage * coverage, const char * path) __attribute__((warn_unused_result));
+
+static int write_json(Coverage * coverage, const char * path) {
+ /* write the JSON */
+ FILE * f = fopen(path, "wb");
+ if (f == NULL) {
+ return -1;
+ }
+ putc('{', f);
+ Coverage_foreach_file(coverage, write_json_for_file, f);
+ putc('}', f);
+ if (fclose(f) == EOF) {
+ return -1;
+ }
+ return 0;
+}
+
+static void handle_jscoverage_request(HTTPExchange * exchange) {
+ /* set the `Server' response-header (RFC 2616 14.38, 3.8) */
+ HTTPExchange_set_response_header(exchange, HTTP_SERVER, "jscoverage-server/" VERSION);
+
+ const char * abs_path = HTTPExchange_get_abs_path(exchange);
+ assert(*abs_path != '\0');
+ if (str_starts_with(abs_path, "/jscoverage-store")) {
+ if (strcmp(HTTPExchange_get_method(exchange), "POST") != 0) {
+ HTTPExchange_set_response_header(exchange, HTTP_ALLOW, "POST");
+ send_response(exchange, 405, "Method not allowed\n");
+ return;
+ }
+
+ Stream * json = Stream_new(0);
+
+ /* read the POST body */
+ if (HTTPExchange_read_entire_request_entity_body(exchange, json) != 0) {
+ Stream_delete(json);
+ send_response(exchange, 400, "Could not read request body\n");
+ return;
+ }
+
+ Coverage * coverage = Coverage_new();
+ LOCK(&javascript_mutex);
+ int result = jscoverage_parse_json(coverage, json->data, json->length);
+ UNLOCK(&javascript_mutex);
+ Stream_delete(json);
+
+ if (result != 0) {
+ Coverage_delete(coverage);
+ send_response(exchange, 400, "Could not parse coverage data\n");
+ return;
+ }
+
+ mkdir_if_necessary(report_directory);
+ char * current_report_directory;
+ if (str_starts_with(abs_path, "/jscoverage-store/") && abs_path[18] != '\0') {
+ char * dir = decode_uri_component(abs_path + 18);
+ current_report_directory = make_path(report_directory, dir);
+ free(dir);
+ }
+ else {
+ current_report_directory = xstrdup(report_directory);
+ }
+ mkdir_if_necessary(current_report_directory);
+ char * path = make_path(current_report_directory, "jscoverage.json");
+
+ /* check if the JSON file exists */
+ struct stat buf;
+ if (stat(path, &buf) == 0) {
+ /* it exists: merge */
+ FILE * f = fopen(path, "rb");
+ if (f == NULL) {
+ result = 1;
+ }
+ else {
+ result = merge(coverage, f);
+ if (fclose(f) == EOF) {
+ result = 1;
+ }
+ }
+ if (result != 0) {
+ free(current_report_directory);
+ free(path);
+ Coverage_delete(coverage);
+ send_response(exchange, 500, "Could not merge with existing coverage data\n");
+ return;
+ }
+ }
+
+ result = write_json(coverage, path);
+ free(path);
+ Coverage_delete(coverage);
+ if (result != 0) {
+ free(current_report_directory);
+ send_response(exchange, 500, "Could not write coverage data\n");
+ return;
+ }
+
+ /* copy other files */
+ jscoverage_copy_resources(current_report_directory);
+ path = make_path(current_report_directory, "jscoverage.js");
+ free(current_report_directory);
+ FILE * f = fopen(path, "ab");
+ free(path);
+ if (f == NULL) {
+ send_response(exchange, 500, "Could not write to file: jscoverage.js\n");
+ return;
+ }
+ fputs("jscoverage_isReport = true;\r\n", f);
+ if (fclose(f) == EOF) {
+ send_response(exchange, 500, "Could not write to file: jscoverage.js\n");
+ return;
+ }
+
+ send_response(exchange, 200, "Coverage data stored\n");
+ }
+ else if (str_starts_with(abs_path, "/jscoverage-shutdown")) {
+ if (strcmp(HTTPExchange_get_method(exchange), "POST") != 0) {
+ HTTPExchange_set_response_header(exchange, HTTP_ALLOW, "POST");
+ send_response(exchange, 405, "Method not allowed\n");
+ return;
+ }
+
+ /* allow only from localhost */
+ struct sockaddr_in client;
+ if (HTTPExchange_get_peer(exchange, &client) != 0) {
+ send_response(exchange, 500, "Cannot get client address\n");
+ return;
+ }
+ if (client.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
+ send_response(exchange, 403, "This operation can be performed only by localhost\n");
+ return;
+ }
+
+ send_response(exchange, 200, "The server will now shut down\n");
+ HTTPServer_shutdown();
+ }
+ else {
+ const char * path = abs_path + 1;
+ const struct Resource * resource = get_resource(path);
+ if (resource == NULL) {
+ send_response(exchange, 404, "Not found\n");
+ return;
+ }
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, get_content_type(path));
+ if (HTTPExchange_write_response(exchange, resource->data, resource->length) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ return;
+ }
+ if (strcmp(abs_path, "/jscoverage.js") == 0) {
+ const char * s = "jscoverage_isServer = true;\r\n";
+ if (HTTPExchange_write_response(exchange, s, strlen(s)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ }
+ }
+}
+
+static void instrument_js(const char * id, const uint16_t * characters, size_t num_characters, Stream * output_stream) {
+ const struct Resource * resource = get_resource("report.js");
+ Stream_write(output_stream, resource->data, resource->length);
+
+ LOCK(&javascript_mutex);
+ jscoverage_instrument_js(id, characters, num_characters, output_stream);
+ UNLOCK(&javascript_mutex);
+}
+
+static bool is_hop_by_hop_header(const char * h) {
+ /* hop-by-hop headers (RFC 2616 13.5.1) */
+ return strcasecmp(h, HTTP_CONNECTION) == 0 ||
+ strcasecmp(h, "Keep-Alive") == 0 ||
+ strcasecmp(h, HTTP_PROXY_AUTHENTICATE) == 0 ||
+ strcasecmp(h, HTTP_PROXY_AUTHORIZATION) == 0 ||
+ strcasecmp(h, HTTP_TE) == 0 ||
+ strcasecmp(h, HTTP_TRAILER) == 0 ||
+ strcasecmp(h, HTTP_TRANSFER_ENCODING) == 0 ||
+ strcasecmp(h, HTTP_UPGRADE) == 0;
+}
+
+static void add_via_header(HTTPMessage * message, const char * version) {
+ char * value;
+ xasprintf(&value, "%s jscoverage-server", version);
+ HTTPMessage_add_header(message, HTTP_VIA, value);
+ free(value);
+}
+
+static int copy_http_message_body(HTTPMessage * from, HTTPMessage * to) __attribute__((warn_unused_result));
+
+static int copy_http_message_body(HTTPMessage * from, HTTPMessage * to) {
+ uint8_t * buffer[8192];
+ for (;;) {
+ size_t bytes_read;
+ int result = HTTPMessage_read_message_body(from, buffer, 8192, &bytes_read);
+ if (result != 0) {
+ return result;
+ }
+ if (bytes_read == 0) {
+ return 0;
+ }
+ result = HTTPMessage_write(to, buffer, bytes_read);
+ if (result != 0) {
+ return result;
+ }
+ }
+}
+
+static void handle_proxy_request(HTTPExchange * client_exchange) {
+ HTTPConnection * server_connection = NULL;
+ HTTPExchange * server_exchange = NULL;
+
+ const char * abs_path = HTTPExchange_get_abs_path(client_exchange);
+ if (str_starts_with(abs_path, "/jscoverage")) {
+ handle_jscoverage_request(client_exchange);
+ return;
+ }
+
+ const char * host = HTTPExchange_get_host(client_exchange);
+ uint16_t port = HTTPExchange_get_port(client_exchange);
+
+ /* create a new connection */
+ server_connection = HTTPConnection_new_client(host, port);
+ if (server_connection == NULL) {
+ send_response(client_exchange, 504, "Could not connect to server\n");
+ goto done;
+ }
+
+ /* create a new exchange */
+ server_exchange = HTTPExchange_new(server_connection);
+ HTTPExchange_set_method(server_exchange, HTTPExchange_get_method(client_exchange));
+ HTTPExchange_set_request_uri(server_exchange, HTTPExchange_get_request_uri(client_exchange));
+ for (const HTTPHeader * h = HTTPExchange_get_request_headers(client_exchange); h != NULL; h = h->next) {
+ if (strcasecmp(h->name, HTTP_TRAILER) == 0 || strcasecmp(h->name, HTTP_TRANSFER_ENCODING) == 0) {
+ /* do nothing: we want to keep this header */
+ }
+ else if (is_hop_by_hop_header(h->name) ||
+ strcasecmp(h->name, HTTP_ACCEPT_ENCODING) == 0 ||
+ strcasecmp(h->name, HTTP_RANGE) == 0) {
+ continue;
+ }
+ HTTPExchange_add_request_header(server_exchange, h->name, h->value);
+ }
+ add_via_header(HTTPExchange_get_request_message(server_exchange), HTTPExchange_get_request_http_version(client_exchange));
+
+ /* send the request */
+ if (HTTPExchange_write_request_headers(server_exchange) != 0) {
+ send_response(client_exchange, 502, "Could not write to server\n");
+ goto done;
+ }
+
+ /* handle POST or PUT */
+ if (HTTPExchange_request_has_body(client_exchange)) {
+ HTTPMessage * client_request = HTTPExchange_get_request_message(client_exchange);
+ HTTPMessage * server_request = HTTPExchange_get_request_message(server_exchange);
+ if (copy_http_message_body(client_request, server_request) != 0) {
+ send_response(client_exchange, 400, "Error copying request body from client to server\n");
+ goto done;
+ }
+ }
+
+ if (HTTPExchange_flush_request(server_exchange) != 0) {
+ send_response(client_exchange, 502, "Could not write to server\n");
+ goto done;
+ }
+
+ /* receive the response */
+ if (HTTPExchange_read_response_headers(server_exchange) != 0) {
+ send_response(client_exchange, 502, "Could not read headers from server\n");
+ goto done;
+ }
+
+ HTTPExchange_set_status_code(client_exchange, HTTPExchange_get_status_code(server_exchange));
+
+ if (HTTPExchange_response_has_body(server_exchange) && should_instrument_request(server_exchange)) {
+ /* needs instrumentation */
+ Stream * input_stream = Stream_new(0);
+ if (HTTPExchange_read_entire_response_entity_body(server_exchange, input_stream) != 0) {
+ Stream_delete(input_stream);
+ send_response(client_exchange, 502, "Could not read body from server\n");
+ goto done;
+ }
+
+ const char * request_uri = HTTPExchange_get_request_uri(client_exchange);
+ char * encoding = HTTPMessage_get_charset(HTTPExchange_get_response_message(server_exchange));
+ if (encoding == NULL) {
+ encoding = xstrdup(jscoverage_encoding);
+ }
+ uint16_t * characters;
+ size_t num_characters;
+ int result = jscoverage_bytes_to_characters(encoding, input_stream->data, input_stream->length, &characters, &num_characters);
+ free(encoding);
+ Stream_delete(input_stream);
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ send_response(client_exchange, 500, "Encoding not supported\n");
+ goto done;
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ send_response(client_exchange, 502, "Error decoding response\n");
+ goto done;
+ }
+
+ Stream * output_stream = Stream_new(0);
+ instrument_js(request_uri, characters, num_characters, output_stream);
+
+ /* send the headers to the client */
+ for (const HTTPHeader * h = HTTPExchange_get_response_headers(server_exchange); h != NULL; h = h->next) {
+ if (is_hop_by_hop_header(h->name) || strcasecmp(h->name, HTTP_CONTENT_LENGTH) == 0) {
+ continue;
+ }
+ else if (strcasecmp(h->name, HTTP_CONTENT_TYPE) == 0) {
+ HTTPExchange_add_response_header(client_exchange, HTTP_CONTENT_TYPE, "text/javascript; charset=ISO-8859-1");
+ continue;
+ }
+ HTTPExchange_add_response_header(client_exchange, h->name, h->value);
+ }
+ add_via_header(HTTPExchange_get_response_message(client_exchange), HTTPExchange_get_response_http_version(server_exchange));
+ HTTPExchange_set_response_content_length(client_exchange, output_stream->length);
+
+ /* send the instrumented code to the client */
+ if (HTTPExchange_write_response(client_exchange, output_stream->data, output_stream->length) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+
+ /* characters go on the cache */
+ /*
+ free(characters);
+ */
+ Stream_delete(output_stream);
+ add_cached_source(request_uri, characters, num_characters);
+ }
+ else {
+ /* does not need instrumentation */
+
+ /* send the headers to the client */
+ for (const HTTPHeader * h = HTTPExchange_get_response_headers(server_exchange); h != NULL; h = h->next) {
+ if (strcasecmp(h->name, HTTP_TRAILER) == 0 || strcasecmp(h->name, HTTP_TRANSFER_ENCODING) == 0) {
+ /* do nothing: we want to keep this header */
+ }
+ else if (is_hop_by_hop_header(h->name)) {
+ continue;
+ }
+ HTTPExchange_add_response_header(client_exchange, h->name, h->value);
+ }
+ add_via_header(HTTPExchange_get_response_message(client_exchange), HTTPExchange_get_response_http_version(server_exchange));
+
+ if (HTTPExchange_write_response_headers(client_exchange) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ goto done;
+ }
+
+ if (HTTPExchange_response_has_body(server_exchange)) {
+ /* read the body from the server and send it to the client */
+ HTTPMessage * client_response = HTTPExchange_get_response_message(client_exchange);
+ HTTPMessage * server_response = HTTPExchange_get_response_message(server_exchange);
+ if (copy_http_message_body(server_response, client_response) != 0) {
+ HTTPServer_log_err("Warning: error copying response body from server to client\n");
+ goto done;
+ }
+ }
+ }
+
+done:
+ if (server_exchange != NULL) {
+ HTTPExchange_delete(server_exchange);
+ }
+ if (server_connection != NULL) {
+ if (HTTPConnection_delete(server_connection) != 0) {
+ HTTPServer_log_err("Warning: error closing connection to server\n");
+ }
+ }
+}
+
+static void handle_local_request(HTTPExchange * exchange) {
+ /* add the `Server' response-header (RFC 2616 14.38, 3.8) */
+ HTTPExchange_add_response_header(exchange, HTTP_SERVER, "jscoverage-server/" VERSION);
+
+ char * decoded_path = NULL;
+ char * filesystem_path = NULL;
+
+ const char * abs_path = HTTPExchange_get_abs_path(exchange);
+ assert(*abs_path != '\0');
+
+ decoded_path = decode_uri_component(abs_path);
+
+ if (str_starts_with(decoded_path, "/jscoverage")) {
+ handle_jscoverage_request(exchange);
+ goto done;
+ }
+
+ if (strstr(decoded_path, "..") != NULL) {
+ send_response(exchange, 403, "Forbidden\n");
+ goto done;
+ }
+
+ filesystem_path = make_path(document_root, decoded_path + 1);
+ size_t filesystem_path_length = strlen(filesystem_path);
+ if (filesystem_path_length > 0 && filesystem_path[filesystem_path_length - 1] == '/') {
+ /* stat on Windows doesn't work with trailing slash */
+ filesystem_path[filesystem_path_length - 1] = '\0';
+ }
+
+ struct stat buf;
+ if (stat(filesystem_path, &buf) == -1) {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+ if (S_ISDIR(buf.st_mode)) {
+ if (abs_path[strlen(abs_path) - 1] != '/') {
+ const char * request_uri = HTTPExchange_get_request_uri(exchange);
+ char * uri = xmalloc(strlen(request_uri) + 2);
+ strcpy(uri, request_uri);
+ strcat(uri, "/");
+ HTTPExchange_add_response_header(exchange, "Location", uri);
+ free(uri);
+ send_response(exchange, 301, "Moved permanently\n");
+ goto done;
+ }
+
+ DIR * d = opendir(filesystem_path);
+ if (d == NULL) {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+ struct dirent * entry;
+ while ((entry = readdir(d)) != NULL) {
+ char * href = encode_uri_component(entry->d_name);
+ char * html_href = encode_html(href);
+ char * link = encode_html(entry->d_name);
+ char * directory_entry;
+ xasprintf(&directory_entry, "<a href=\"%s\">%s</a><br>\n", html_href, link);
+ if (HTTPExchange_write_response(exchange, directory_entry, strlen(directory_entry)) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ free(directory_entry);
+ free(href);
+ free(html_href);
+ free(link);
+ }
+ closedir(d);
+ }
+ else if (S_ISREG(buf.st_mode)) {
+ FILE * f = fopen(filesystem_path, "rb");
+ if (f == NULL) {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+ /*
+ When do we send a charset with Content-Type?
+ if Content-Type is "text" or "application"
+ if instrumented JavaScript
+ use Content-Type: application/javascript; charset=ISO-8859-1
+ else if --encoding is given
+ use that encoding
+ else
+ send no charset
+ else
+ send no charset
+ */
+ const char * content_type = get_content_type(filesystem_path);
+ if (strcmp(content_type, "text/javascript") == 0 && ! is_no_instrument(abs_path)) {
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, "text/javascript; charset=ISO-8859-1");
+
+ Stream * input_stream = Stream_new(0);
+ Stream_write_file_contents(input_stream, f);
+
+ uint16_t * characters;
+ size_t num_characters;
+ int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
+ Stream_delete(input_stream);
+
+ if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
+ send_response(exchange, 500, "Encoding not supported\n");
+ goto done;
+ }
+ else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
+ send_response(exchange, 500, "Error decoding JavaScript file\n");
+ goto done;
+ }
+
+ Stream * output_stream = Stream_new(0);
+ instrument_js(abs_path, characters, num_characters, output_stream);
+ free(characters);
+
+ if (HTTPExchange_write_response(exchange, output_stream->data, output_stream->length) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ Stream_delete(output_stream);
+ }
+ else {
+ /* send the Content-Type with charset if necessary */
+ if (specified_encoding != NULL && (str_starts_with(content_type, "text/") || str_starts_with(content_type, "application/"))) {
+ char * content_type_with_charset = NULL;
+ xasprintf(&content_type_with_charset, "%s; charset=%s", content_type, specified_encoding);
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, content_type_with_charset);
+ free(content_type_with_charset);
+ }
+ else {
+ HTTPExchange_set_response_header(exchange, HTTP_CONTENT_TYPE, content_type);
+ }
+
+ char buffer[8192];
+ size_t bytes_read;
+ while ((bytes_read = fread(buffer, 1, 8192, f)) > 0) {
+ if (HTTPExchange_write_response(exchange, buffer, bytes_read) != 0) {
+ HTTPServer_log_err("Warning: error writing to client\n");
+ }
+ }
+ }
+ fclose(f);
+ }
+ else {
+ send_response(exchange, 404, "Not found\n");
+ goto done;
+ }
+
+done:
+ free(filesystem_path);
+ free(decoded_path);
+}
+
+static void handler(HTTPExchange * exchange) {
+ if (verbose) {
+ HTTPServer_log_out("%s", HTTPExchange_get_request_line(exchange));
+ }
+
+ if (proxy) {
+ handle_proxy_request(exchange);
+ }
+ else {
+ handle_local_request(exchange);
+ }
+}
+
+int main(int argc, char ** argv) {
+ program = "jscoverage-server";
+
+ const char * ip_address = "127.0.0.1";
+ const char * port = "8080";
+ int shutdown = 0;
+
+ no_instrument = xnew(const char *, argc - 1);
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+ copy_resource_to_stream("jscoverage-server-help.txt", stdout);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
+ version();
+ }
+ else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose = 1;
+ }
+
+ else if (strcmp(argv[i], "--report-dir") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--report-dir: option requires an argument");
+ }
+ report_directory = argv[i];
+ }
+ else if (strncmp(argv[i], "--report-dir=", 13) == 0) {
+ report_directory = argv[i] + 13;
+ }
+
+ else if (strcmp(argv[i], "--document-root") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--document-root: option requires an argument");
+ }
+ document_root = argv[i];
+ }
+ else if (strncmp(argv[i], "--document-root=", 16) == 0) {
+ document_root = argv[i] + 16;
+ }
+
+ else if (strcmp(argv[i], "--encoding") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--encoding: option requires an argument");
+ }
+ jscoverage_encoding = argv[i];
+ specified_encoding = jscoverage_encoding;
+ }
+ else if (strncmp(argv[i], "--encoding=", 11) == 0) {
+ jscoverage_encoding = argv[i] + 11;
+ specified_encoding = jscoverage_encoding;
+ }
+
+ else if (strcmp(argv[i], "--ip-address") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--ip-address: option requires an argument");
+ }
+ ip_address = argv[i];
+ }
+ else if (strncmp(argv[i], "--ip-address=", 13) == 0) {
+ ip_address = argv[i] + 13;
+ }
+
+ else if (strcmp(argv[i], "--js-version") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--js-version: option requires an argument");
+ }
+ jscoverage_set_js_version(argv[i]);
+ }
+ else if (strncmp(argv[i], "--js-version=", 13) == 0) {
+ jscoverage_set_js_version(argv[i] + 13);
+ }
+
+ else if (strcmp(argv[i], "--no-highlight") == 0) {
+ jscoverage_highlight = false;
+ }
+
+ else if (strcmp(argv[i], "--no-instrument") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--no-instrument: option requires an argument");
+ }
+ no_instrument[num_no_instrument] = argv[i];
+ num_no_instrument++;
+ }
+ else if (strncmp(argv[i], "--no-instrument=", 16) == 0) {
+ no_instrument[num_no_instrument] = argv[i] + 16;
+ num_no_instrument++;
+ }
+
+ else if (strcmp(argv[i], "--port") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--port: option requires an argument");
+ }
+ port = argv[i];
+ }
+ else if (strncmp(argv[i], "--port=", 7) == 0) {
+ port = argv[i] + 7;
+ }
+
+ else if (strcmp(argv[i], "--proxy") == 0) {
+ proxy = 1;
+ }
+
+ else if (strcmp(argv[i], "--shutdown") == 0) {
+ shutdown = 1;
+ }
+
+ else if (strncmp(argv[i], "-", 1) == 0) {
+ fatal_command_line("unrecognized option `%s'", argv[i]);
+ }
+ else {
+ fatal_command_line("too many arguments");
+ }
+ }
+
+ /* check the port */
+ char * end;
+ unsigned long numeric_port = strtoul(port, &end, 10);
+ if (*end != '\0') {
+ fatal_command_line("--port: option must be an integer");
+ }
+ if (numeric_port > UINT16_MAX) {
+ fatal_command_line("--port: option must be 16 bits");
+ }
+
+ /* is this a shutdown? */
+ if (shutdown) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ fatal("could not start Winsock");
+ }
+#endif
+
+ /* INADDR_LOOPBACK */
+ HTTPConnection * connection = HTTPConnection_new_client("127.0.0.1", numeric_port);
+ if (connection == NULL) {
+ fatal("could not connect to server");
+ }
+ HTTPExchange * exchange = HTTPExchange_new(connection);
+ HTTPExchange_set_method(exchange, "POST");
+ HTTPExchange_set_request_uri(exchange, "/jscoverage-shutdown");
+ if (HTTPExchange_write_request_headers(exchange) != 0) {
+ fatal("could not write request headers to server");
+ }
+ if (HTTPExchange_read_response_headers(exchange) != 0) {
+ fatal("could not read response headers from server");
+ }
+ Stream * stream = Stream_new(0);
+ if (HTTPExchange_read_entire_response_entity_body(exchange, stream) != 0) {
+ fatal("could not read response body from server");
+ }
+ fwrite(stream->data, 1, stream->length, stdout);
+ Stream_delete(stream);
+ HTTPExchange_delete(exchange);
+ if (HTTPConnection_delete(connection) != 0) {
+ fatal("could not close connection with server");
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ jscoverage_init();
+
+#ifndef __MINGW32__
+ /* handle broken pipe */
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+#ifdef __MINGW32__
+InitializeCriticalSection(&javascript_mutex);
+InitializeCriticalSection(&source_cache_mutex);
+#endif
+
+ if (verbose) {
+ printf("Starting HTTP server on %s:%lu\n", ip_address, numeric_port);
+ fflush(stdout);
+ }
+ HTTPServer_run(ip_address, (uint16_t) numeric_port, handler);
+ if (verbose) {
+ printf("Stopping HTTP server\n");
+ fflush(stdout);
+ }
+
+ jscoverage_cleanup();
+
+ free(no_instrument);
+
+ LOCK(&source_cache_mutex);
+ while (source_cache != NULL) {
+ SourceCache * p = source_cache;
+ source_cache = source_cache->next;
+ free(p->url);
+ free(p->characters);
+ free(p);
+ }
+ UNLOCK(&source_cache_mutex);
+
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gif b/tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gif
new file mode 100644
index 0000000..f13c0b4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage-throbber.gif
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.1 b/tools/node_modules/expresso/deps/jscoverage/jscoverage.1
new file mode 100644
index 0000000..bedc5a7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.1
@@ -0,0 +1,52 @@
+.TH jscoverage 1 local
+.SH NAME
+jscoverage \- Instrument JavaScript with code coverage information
+
+.SH SYNOPSIS
+jscoverage [OPTION] SOURCE-DIRECTORY DESTINATION-DIRECTORY
+
+.SH DESCRIPTION
+
+Copy JavaScript code from SOURCE-DIRECTORY to DESTINATION-DIRECTORY and add code instrumentation.
+
+.SH OPTIONS
+
+.TP
+.B --encoding=ENCODING
+assume .js files use the given character encoding.
+
+.TP
+.B --exclude=PATH
+do not copy
+.B PATH.
+
+.TP
+.B --js-version=VERSION
+use the specified JavaScript version; valid values for
+.B VERSION
+are 1.0, 1.1, 1.2, ..., 1.8, or ECMAv3 (the default).
+
+.TP
+.B --no-highlight
+do not perform syntax highlighting.
+
+.TP
+.B --no-instrument=PATH
+copy but do not instrument
+.B PATH.
+
+.TP
+.B -v, --verbose
+explain what is being done.
+
+.TP
+.B -h, --help
+display this help and exit.
+
+.TP
+.B -V, --version
+display version information and exit.
+.
+.SH AUTHORS
+
+siliconforks.com
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.c b/tools/node_modules/expresso/deps/jscoverage/jscoverage.c
new file mode 100644
index 0000000..f011148
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.c
@@ -0,0 +1,142 @@
+/*
+ jscoverage.c - main routine for `jscoverage' program
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "global.h"
+#include "instrument.h"
+#include "instrument-js.h"
+#include "resource-manager.h"
+#include "util.h"
+
+const char * jscoverage_encoding = "ISO-8859-1";
+bool jscoverage_highlight = true;
+
+int main(int argc, char ** argv) {
+ int verbose = 0;
+
+ // program = argv[0];
+ program = "jscoverage";
+
+ char * source = NULL;
+ char * destination = NULL;
+
+ char ** no_instrument = xnew(char *, argc - 1);
+ int num_no_instrument = 0;
+
+ char ** exclude = xnew(char *, argc - 1);
+ int num_exclude = 0;
+
+ jscoverage_highlight = false;
+
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
+ copy_resource_to_stream("jscoverage-help.txt", stdout);
+ exit(EXIT_SUCCESS);
+ }
+ else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "--version") == 0) {
+ version();
+ }
+ else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
+ verbose = 1;
+ }
+ else if (strcmp(argv[i], "--mozilla") == 0) {
+ jscoverage_mozilla = true;
+ jscoverage_set_js_version("180");
+ }
+ else if (strcmp(argv[i], "--no-instrument") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--no-instrument: option requires an argument");
+ }
+ no_instrument[num_no_instrument] = argv[i];
+ num_no_instrument++;
+ }
+ else if (strncmp(argv[i], "--no-instrument=", 16) == 0) {
+ no_instrument[num_no_instrument] = argv[i] + 16;
+ num_no_instrument++;
+ }
+ else if (strcmp(argv[i], "--exclude") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--exclude: option requires an argument");
+ }
+ exclude[num_exclude] = argv[i];
+ num_exclude++;
+ }
+ else if (strncmp(argv[i], "--exclude=", 10) == 0) {
+ exclude[num_exclude] = argv[i] + 10;
+ num_exclude++;
+ }
+ else if (strcmp(argv[i], "--encoding") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--encoding: option requires an argument");
+ }
+ jscoverage_encoding = argv[i];
+ }
+ else if (strncmp(argv[i], "--encoding=", 11) == 0) {
+ jscoverage_encoding = argv[i] + 11;
+ }
+ else if (strcmp(argv[i], "--js-version") == 0) {
+ i++;
+ if (i == argc) {
+ fatal_command_line("--js-version: option requires an argument");
+ }
+ jscoverage_set_js_version(argv[i]);
+ }
+ else if (strncmp(argv[i], "--js-version=", 13) == 0) {
+ jscoverage_set_js_version(argv[i] + 13);
+ }
+ else if (strncmp(argv[i], "-", 1) == 0) {
+ fatal_command_line("unrecognized option `%s'", argv[i]);
+ }
+ else if (source == NULL) {
+ source = argv[i];
+ }
+ else if (destination == NULL) {
+ destination = argv[i];
+ }
+ else {
+ fatal_command_line("too many arguments");
+ }
+ }
+
+ if (source == NULL || destination == NULL) {
+ fatal_command_line("missing argument");
+ }
+
+ source = make_canonical_path(source);
+ destination = make_canonical_path(destination);
+
+ jscoverage_init();
+ jscoverage_instrument(source, destination, verbose, exclude, num_exclude, no_instrument, num_no_instrument);
+ jscoverage_cleanup();
+
+ free(source);
+ free(destination);
+ free(exclude);
+ free(no_instrument);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.css b/tools/node_modules/expresso/deps/jscoverage/jscoverage.css
new file mode 100644
index 0000000..98af69b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.css
@@ -0,0 +1,328 @@
+/*
+ jscoverage.css - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+body {
+ background-color: #bfffbf;
+ font-family: sans-serif;
+ font-size: 100%;
+ margin: 0;
+}
+
+#mainDiv {
+ font-size: 0.8125em;
+}
+
+#headingDiv {
+ position: absolute;
+ top: 0.5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 0;
+ line-height: 1.5em;
+}
+
+h1 {
+ float: left;
+ margin: 0;
+ padding-bottom: 0.5em;
+ font-size: 1.3em;
+}
+
+.ProgressBar {
+ float: left;
+ visibility: hidden;
+}
+
+.ProgressPercentage {
+ display: block;
+ float: left;
+ width: 5em;
+ text-align: right;
+}
+
+.ProgressGraph {
+ float: left;
+ width: 100px;
+ height: 10px;
+ border: 1px solid black;
+ margin-top: 0.3em;
+ background-color: #d4d0c8;
+ overflow: hidden;
+}
+
+.ProgressCovered {
+ /* windows system color ActiveCaption or Highlight */
+ background-color: #0a246a;
+ width: 0;
+ height: 10px;
+ overflow: hidden;
+}
+
+#progressLabel {
+ display: block;
+ float: left;
+ padding-left: 0.3em;
+}
+
+/*******************************************************************************
+browser tab
+*/
+
+input#location, button {
+ border: 1px solid black;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+#iframeDiv {
+ position: absolute;
+ top: 3.5em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+}
+
+iframe {
+ width: 100%;
+ height: 100%;
+}
+
+/*******************************************************************************
+summary tab
+*/
+
+#summaryDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#summaryTable {
+ width: 100%;
+ margin-left: 0px;
+ margin-right: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+table#summaryTable th, table#summaryTable td {
+ border-left: 1px solid #d9d9d9;
+}
+
+table#summaryTable th.leftColumn, table#summaryTable td.leftColumn {
+ border-left-width: 0px;
+}
+
+table#summaryTable th, table#summaryTable td {
+ padding: 2px;
+}
+
+th {
+ background-color: #e6ffe6;
+}
+
+td.numeric {
+ text-align: right;
+}
+
+abbr {
+ cursor: help;
+}
+
+tr#summaryTotals td.leftColumn span {
+ float: right;
+}
+tr#summaryTotals td.leftColumn span.title {
+ float: left;
+ font-weight: bold;
+}
+tr#summaryTotals td {
+ background-color: #ffd;
+}
+td.coverage {
+ width: 150px;
+}
+td.coverage span {
+ float: right;
+ margin-right: 5px;
+}
+.pctGraph {
+ width: 100px;
+ height: 10px;
+ float: right;
+ border: 1px solid #000;
+ background-color: #e00000;
+ overflow: hidden;
+ margin-top: 4px;
+}
+.pctGraph .covered {
+ background-color: #00f000;
+ width: 0;
+ height: 10px;
+}
+.pctGraph .skipped {
+ background-color: #d4d0c8;
+ width: 100px;
+ height: 10px;
+}
+tbody#summaryTbody tr.even td {
+ background-color: #e6ffe6;
+}
+
+/*******************************************************************************
+source tab
+*/
+
+#fileDiv {
+ font-size: large;
+ font-weight: bold;
+}
+
+#sourceDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+table#sourceTable {
+ border: 0px;
+ border-collapse: collapse;
+ font-size: small;
+}
+
+/*
+IE default behavior is to make <pre> smaller than surrounding text. Because
+the table already has font-size small, this would make the font-size within the
+<pre> x-small. So we don't rely on the default.
+*/
+table#sourceTable pre {
+ font-size: medium;
+}
+
+table#sourceTable td {
+ border: 0px;
+ padding-top: 0px;
+ padding-bottom: 0px;
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+table#sourceTable pre {
+ border: 0px;
+ margin: 0px;
+}
+
+.g {
+ background-color: #bfffbf;
+}
+
+.y {
+ background-color: #ffffbf;
+}
+
+.r {
+ background-color: #ffbfbf;
+}
+
+/*******************************************************************************
+store tab
+*/
+
+#storeDiv {
+ position: absolute;
+ top: 3em;
+ left: 1em;
+ right: 1em;
+ bottom: 1em;
+ overflow: auto;
+}
+
+/*******************************************************************************
+about tab
+*/
+
+p {
+ margin-top: 0;
+}
+
+/*******************************************************************************
+tabs
+*/
+
+#tabs {
+ position: absolute;
+ top: 3em;
+ left: 1.5em;
+ right: 1.5em;
+ height: 2em;
+}
+
+#tabs div {
+ background-color: white;
+ position: relative;
+ float: left;
+ border: 1px solid black;
+ border-bottom-width: 0;
+ cursor: pointer;
+ margin-left: 0.5em;
+ margin-right: 0.5em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ height: 2em;
+ z-index: 1;
+ line-height: 1.8em;
+}
+
+#tabs div.selected {
+ z-index: 3;
+ cursor: default;
+}
+
+#tabs div.disabled {
+ /* windows system color GrayText */
+ color: #808080;
+ cursor: default;
+}
+
+.TabPage {
+ background-color: white;
+ border: 1px solid black;
+ position: absolute;
+ top: 5em;
+ left: 1.5em;
+ right: 1.5em;
+ bottom: 1.5em;
+ z-index: 2;
+ padding: 1em;
+ display: none;
+}
+
+#tabPages div.selected {
+ display: block;
+}
+
+img {
+ visibility: hidden;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.html b/tools/node_modules/expresso/deps/jscoverage/jscoverage.html
new file mode 100644
index 0000000..601f62a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<!--
+ jscoverage.html - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<html>
+<head>
+<title>JSCoverage</title>
+<link rel="stylesheet" type="text/css" href="jscoverage-highlight.css">
+<link rel="stylesheet" type="text/css" href="jscoverage.css">
+<!--[if IE]>
+<link rel="stylesheet" type="text/css" href="jscoverage-ie.css">
+<![endif]-->
+<script type="text/javascript" src="jscoverage.js"></script>
+</head>
+
+<body onload="jscoverage_body_load();" onresize="jscoverage_body_resize();">
+<div id="mainDiv">
+<div id="headingDiv">
+<h1>JSCoverage</h1>
+<div class="ProgressBar" id="progressBar"><span class="ProgressPercentage"></span><div class="ProgressGraph"><div class="ProgressCovered"></div></div></div>
+<span id="progressLabel"></span>
+</div>
+
+<div id="tabs" class="Tabs">
+ <div id="browserTab"><img src="jscoverage-throbber.gif" alt=""> Browser <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="summaryTab"><img id="summaryThrobber" src="jscoverage-throbber.gif" alt=""> Summary <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="sourceTab" class="disabled"><img src="jscoverage-throbber.gif" alt=""> Source <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="storeTab"><img id="storeThrobber" src="jscoverage-throbber.gif" alt=""> Store <img src="jscoverage-throbber.gif" alt=""></div>
+ <div id="aboutTab"><img src="jscoverage-throbber.gif" alt=""> About <img src="jscoverage-throbber.gif" alt=""></div>
+</div>
+<div id="tabPages" class="TabPages">
+ <div class="TabPage" id="browserTabPage">
+ <div id="locationDiv">
+ URL: <input id="location" type="text" size="70" onkeypress="jscoverage_input_keypress(event)">
+ <button onclick="jscoverage_button_click();">Go</button>
+ </div>
+ <div id="iframeDiv">
+ <iframe id="browserIframe" onload="jscoverage_browser_load();"></iframe>
+ </div>
+ </div>
+ <div class="TabPage">
+ <input type="checkbox" id="checkbox" onclick="return jscoverage_checkbox_click();"> <label for="checkbox">Show missing statements column</label>
+ <div id="summaryDiv">
+ <div id="summaryErrorDiv"></div>
+ <table id="summaryTable">
+ <thead>
+ <tr id="headerRow">
+ <th class="leftColumn">File</th>
+ <th><abbr title="The total number of executable statements">Statements</abbr></th>
+ <th><abbr title="The number of statements actually executed">Executed</abbr></th>
+ <th><abbr title="Number of executed statements as a percentage of total number of statements">Coverage</abbr></th>
+ </tr>
+ <tr id="summaryTotals">
+ <td class="leftColumn">
+ <span class="title">Total:</span>
+ <span>0</span>
+ </td>
+ <td class="numeric">0</td>
+ <td class="numeric">0</td>
+ <td class="coverage">
+ <div class="pctGraph">
+ <div class="covered"></div>
+ </div>
+ <span class="pct">0%</span>
+ </td>
+ </tr>
+
+ </thead>
+ <tbody id="summaryTbody">
+
+ <!--
+ <tr>
+ <td>0</td>
+ <td>0</td>
+ <td>0</td>
+ <td>0%</td>
+ <td>0</td>
+ </tr>
+ -->
+
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="TabPage">
+ <div id="fileDiv"></div>
+ <div id="sourceDiv"></div>
+ </div>
+ <div class="TabPage" id="storeTabPage">
+ <button id="storeButton" onclick="jscoverage_storeButton_click();">Store Report</button>
+ <img id="storeImg" src="jscoverage-throbber.gif" alt="loading...">
+ <div id="storeDiv"></div>
+ </div>
+ <div class="TabPage">
+ <p>
+ This is version 0.4 of JSCoverage, a program that calculates code
+ coverage statistics for JavaScript.
+ </p>
+ <p>
+ See <a href="http://siliconforks.com/jscoverage/">http://siliconforks.com/jscoverage/</a> for more information.
+ </p>
+ <p>
+ Copyright &copy; 2007, 2008 siliconforks.com
+ </p>
+ </div>
+</div>
+</div>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.js b/tools/node_modules/expresso/deps/jscoverage/jscoverage.js
new file mode 100644
index 0000000..9e2ea5b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.js
@@ -0,0 +1,1024 @@
+/*
+ jscoverage.js - code coverage for JavaScript
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/**
+Initializes the _$jscoverage object in a window. This should be the first
+function called in the page.
+@param w this should always be the global window object
+*/
+function jscoverage_init(w) {
+ try {
+ // in Safari, "import" is a syntax error
+ Components.utils['import']('resource://gre/modules/jscoverage.jsm');
+ jscoverage_isInvertedMode = true;
+ return;
+ }
+ catch (e) {}
+
+ if (w.opener && w.opener.top._$jscoverage) {
+ // we are in inverted mode
+ jscoverage_isInvertedMode = true;
+ if (! w._$jscoverage) {
+ w._$jscoverage = w.opener.top._$jscoverage;
+ }
+ }
+ else {
+ // we are not in inverted mode
+ jscoverage_isInvertedMode = false;
+ if (! w._$jscoverage) {
+ w._$jscoverage = {};
+ }
+ }
+}
+
+var jscoverage_currentFile = null;
+var jscoverage_currentLine = null;
+
+var jscoverage_inLengthyOperation = false;
+
+/*
+Possible states:
+ isInvertedMode isServer isReport tabs
+normal false false false Browser
+inverted true false false
+server, normal false true false Browser, Store
+server, inverted true true false Store
+report false false true
+*/
+var jscoverage_isInvertedMode = false;
+var jscoverage_isServer = false;
+var jscoverage_isReport = false;
+
+jscoverage_init(window);
+
+function jscoverage_createRequest() {
+ // Note that the IE7 XMLHttpRequest does not support file URL's.
+ // http://xhab.blogspot.com/2006/11/ie7-support-for-xmlhttprequest.html
+ // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ else {
+ return new XMLHttpRequest();
+ }
+}
+
+// http://www.quirksmode.org/js/findpos.html
+function jscoverage_findPos(obj) {
+ var result = 0;
+ do {
+ result += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ while (obj);
+ return result;
+}
+
+// http://www.quirksmode.org/viewport/compatibility.html
+function jscoverage_getViewportHeight() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ if (self.innerHeight) {
+ // all except Explorer
+ return self.innerHeight;
+ }
+ else if (document.documentElement && document.documentElement.clientHeight) {
+ // Explorer 6 Strict Mode
+ return document.documentElement.clientHeight;
+ }
+ else if (document.body) {
+ // other Explorers
+ return document.body.clientHeight;
+ }
+ else {
+ throw "Couldn't calculate viewport height";
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Indicates visually that a lengthy operation has begun. The progress bar is
+displayed, and the cursor is changed to busy (on browsers which support this).
+*/
+function jscoverage_beginLengthyOperation() {
+ jscoverage_inLengthyOperation = true;
+
+ var progressBar = document.getElementById('progressBar');
+ progressBar.style.visibility = 'visible';
+ ProgressBar.setPercentage(progressBar, 0);
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'visible';
+
+ /* blacklist buggy browsers */
+//#JSCOVERAGE_IF
+ if (! /Opera|WebKit/.test(navigator.userAgent)) {
+ /*
+ Change the cursor style of each element. Note that changing the class of the
+ element (to one with a busy cursor) is buggy in IE.
+ */
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = 'wait';
+ }
+ }
+}
+
+/**
+Removes the progress bar and busy cursor.
+*/
+function jscoverage_endLengthyOperation() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 100);
+ setTimeout(function() {
+ jscoverage_inLengthyOperation = false;
+ progressBar.style.visibility = 'hidden';
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.style.visibility = 'hidden';
+ progressLabel.innerHTML = '';
+
+ var tabs = document.getElementById('tabs').getElementsByTagName('div');
+ var i;
+ for (i = 0; i < tabs.length; i++) {
+ tabs.item(i).style.cursor = '';
+ }
+ }, 50);
+}
+
+function jscoverage_setSize() {
+//#JSCOVERAGE_IF /MSIE/.test(navigator.userAgent)
+ var viewportHeight = jscoverage_getViewportHeight();
+
+ /*
+ border-top-width: 1px
+ padding-top: 10px
+ padding-bottom: 10px
+ border-bottom-width: 1px
+ margin-bottom: 10px
+ ----
+ 32px
+ */
+ var tabPages = document.getElementById('tabPages');
+ var tabPageHeight = (viewportHeight - jscoverage_findPos(tabPages) - 32) + 'px';
+ var nodeList = tabPages.childNodes;
+ var length = nodeList.length;
+ for (var i = 0; i < length; i++) {
+ var node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+ node.style.height = tabPageHeight;
+ }
+
+ var iframeDiv = document.getElementById('iframeDiv');
+ // may not exist if we have removed the first tab
+ if (iframeDiv) {
+ iframeDiv.style.height = (viewportHeight - jscoverage_findPos(iframeDiv) - 21) + 'px';
+ }
+
+ var summaryDiv = document.getElementById('summaryDiv');
+ summaryDiv.style.height = (viewportHeight - jscoverage_findPos(summaryDiv) - 21) + 'px';
+
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.style.height = (viewportHeight - jscoverage_findPos(sourceDiv) - 21) + 'px';
+
+ var storeDiv = document.getElementById('storeDiv');
+ if (storeDiv) {
+ storeDiv.style.height = (viewportHeight - jscoverage_findPos(storeDiv) - 21) + 'px';
+ }
+//#JSCOVERAGE_ENDIF
+}
+
+/**
+Returns the boolean value of a string. Values 'false', 'f', 'no', 'n', 'off',
+and '0' (upper or lower case) are false.
+@param s the string
+@return a boolean value
+*/
+function jscoverage_getBooleanValue(s) {
+ s = s.toLowerCase();
+ if (s === 'false' || s === 'f' || s === 'no' || s === 'n' || s === 'off' || s === '0') {
+ return false;
+ }
+ return true;
+}
+
+function jscoverage_removeTab(id) {
+ var tab = document.getElementById(id + 'Tab');
+ tab.parentNode.removeChild(tab);
+ var tabPage = document.getElementById(id + 'TabPage');
+ tabPage.parentNode.removeChild(tabPage);
+}
+
+/**
+Initializes the contents of the tabs. This sets the initial values of the
+input field and iframe in the "Browser" tab and the checkbox in the "Summary"
+tab.
+@param queryString this should always be location.search
+*/
+function jscoverage_initTabContents(queryString) {
+ var showMissingColumn = false;
+ var parameters, parameter, i, index, url, name, value;
+ if (queryString.length > 0) {
+ // chop off the question mark
+ queryString = queryString.substring(1);
+ parameters = queryString.split(/&|;/);
+ for (i = 0; i < parameters.length; i++) {
+ parameter = parameters[i];
+ index = parameter.indexOf('=');
+ if (index === -1) {
+ // still works with old syntax
+ url = parameter;
+ }
+ else {
+ name = parameter.substr(0, index);
+ value = parameter.substr(index + 1);
+ if (name === 'missing' || name === 'm') {
+ showMissingColumn = jscoverage_getBooleanValue(value);
+ }
+ else if (name === 'url' || name === 'u') {
+ url = value;
+ }
+ }
+ }
+ }
+
+ var checkbox = document.getElementById('checkbox');
+ checkbox.checked = showMissingColumn;
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+
+ // this will automatically propagate to the input field
+ if (url) {
+ frames[0].location = url;
+ }
+
+ // if the browser tab is absent, we have to initialize the summary tab
+ if (! document.getElementById('browserTab')) {
+ jscoverage_recalculateSummaryTab();
+ }
+}
+
+function jscoverage_body_load() {
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.init(progressBar);
+
+ function reportError(e) {
+ jscoverage_endLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'hidden';
+ var div = document.getElementById('summaryErrorDiv');
+ div.innerHTML = 'Error: ' + e;
+ }
+
+ if (jscoverage_isReport) {
+ jscoverage_beginLengthyOperation();
+ var summaryThrobber = document.getElementById('summaryThrobber');
+ summaryThrobber.style.visibility = 'visible';
+ var request = jscoverage_createRequest();
+ try {
+ request.open('GET', 'jscoverage.json', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ try {
+ if (request.status !== 0 && request.status !== 200) {
+ throw request.status;
+ }
+ var response = request.responseText;
+ if (response === '') {
+ throw 404;
+ }
+ var json = eval('(' + response + ')');
+ var file;
+ for (file in json) {
+ var fileCoverage = json[file];
+ _$jscoverage[file] = fileCoverage.coverage;
+ _$jscoverage[file].source = fileCoverage.source;
+ }
+ jscoverage_recalculateSummaryTab();
+ summaryThrobber.style.visibility = 'hidden';
+ }
+ catch (e) {
+ reportError(e);
+ }
+ }
+ };
+ request.send(null);
+ }
+ catch (e) {
+ reportError(e);
+ }
+
+ jscoverage_removeTab('browser');
+ jscoverage_removeTab('store');
+ }
+ else {
+ if (jscoverage_isInvertedMode) {
+ jscoverage_removeTab('browser');
+ }
+
+ if (! jscoverage_isServer) {
+ jscoverage_removeTab('store');
+ }
+ }
+
+ jscoverage_initTabControl();
+
+ jscoverage_initTabContents(location.search);
+}
+
+function jscoverage_body_resize() {
+ if (/MSIE/.test(navigator.userAgent)) {
+ jscoverage_setSize();
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 1
+
+function jscoverage_updateBrowser() {
+ var input = document.getElementById("location");
+ frames[0].location = input.value;
+}
+
+function jscoverage_input_keypress(e) {
+ if (e.keyCode === 13) {
+ jscoverage_updateBrowser();
+ }
+}
+
+function jscoverage_button_click() {
+ jscoverage_updateBrowser();
+}
+
+function jscoverage_browser_load() {
+ /* update the input box */
+ var input = document.getElementById("location");
+
+ /* sometimes IE seems to fire this after the tab has been removed */
+ if (input) {
+ input.value = frames[0].location;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// tab 2
+
+function jscoverage_createLink(file, line) {
+ var link = document.createElement("a");
+
+ var url;
+ var call;
+ var text;
+ if (line) {
+ url = file + ".jscoverage.html?" + line;
+ call = "jscoverage_get('" + file + "', " + line + ");";
+ text = line.toString();
+ }
+ else {
+ url = file + ".jscoverage.html";
+ call = "jscoverage_get('" + file + "');";
+ text = file;
+ }
+
+ link.setAttribute('href', 'javascript:' + call);
+ link.appendChild(document.createTextNode(text));
+
+ return link;
+}
+
+function jscoverage_recalculateSummaryTab(cc) {
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+
+ if (! cc) {
+ cc = window._$jscoverage;
+ }
+ if (! cc) {
+//#JSCOVERAGE_IF 0
+ throw "No coverage information found.";
+//#JSCOVERAGE_ENDIF
+ }
+
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+
+ var totals = { files:0, statements:0, executed:0, coverage:0, skipped:0 };
+
+ var file;
+ var files = [];
+ for (file in cc) {
+ files.push(file);
+ }
+ files.sort();
+
+ var rowCounter = 0;
+ for (var f = 0; f < files.length; f++) {
+ file = files[f];
+ var lineNumber;
+ var num_statements = 0;
+ var num_executed = 0;
+ var missing = [];
+ var fileCC = cc[file];
+ var length = fileCC.length;
+ var currentConditionalEnd = 0;
+ var conditionals = null;
+ if (fileCC.conditionals) {
+ conditionals = fileCC.conditionals;
+ }
+ for (lineNumber = 0; lineNumber < length; lineNumber++) {
+ var n = fileCC[lineNumber];
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && conditionals && conditionals[lineNumber]) {
+ currentConditionalEnd = conditionals[lineNumber];
+ }
+
+ if (currentConditionalEnd !== 0) {
+ continue;
+ }
+
+ if (n === undefined || n === null) {
+ continue;
+ }
+
+ if (n === 0) {
+ missing.push(lineNumber);
+ }
+ else {
+ num_executed++;
+ }
+ num_statements++;
+ }
+
+ var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
+
+ var row = document.createElement("tr");
+ row.className = ( rowCounter++ % 2 == 0 ? "odd" : "even" );
+
+ var cell = document.createElement("td");
+ cell.className = 'leftColumn';
+ var link = jscoverage_createLink(file);
+ cell.appendChild(link);
+
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_statements));
+ row.appendChild(cell);
+
+ cell = document.createElement("td");
+ cell.className = 'numeric';
+ cell.appendChild(document.createTextNode(num_executed));
+ row.appendChild(cell);
+
+ // new coverage td containing a bar graph
+ cell = document.createElement("td");
+ cell.className = 'coverage';
+ var pctGraph = document.createElement("div"),
+ covered = document.createElement("div"),
+ pct = document.createElement("span");
+ pctGraph.className = "pctGraph";
+ if( num_statements === 0 ) {
+ covered.className = "skipped";
+ pct.appendChild(document.createTextNode("N/A"));
+ } else {
+ covered.className = "covered";
+ covered.style.width = percentage + "px";
+ pct.appendChild(document.createTextNode(percentage + '%'));
+ }
+ pct.className = "pct";
+ pctGraph.appendChild(covered);
+ cell.appendChild(pctGraph);
+ cell.appendChild(pct);
+ row.appendChild(cell);
+
+ if (showMissingColumn) {
+ cell = document.createElement("td");
+ for (var i = 0; i < missing.length; i++) {
+ if (i !== 0) {
+ cell.appendChild(document.createTextNode(", "));
+ }
+ link = jscoverage_createLink(file, missing[i]);
+ cell.appendChild(link);
+ }
+ row.appendChild(cell);
+ }
+
+ tbody.appendChild(row);
+
+ totals['files'] ++;
+ totals['statements'] += num_statements;
+ totals['executed'] += num_executed;
+ totals['coverage'] += percentage;
+ if( num_statements === 0 ) {
+ totals['skipped']++;
+ }
+
+ // write totals data into summaryTotals row
+ var tr = document.getElementById("summaryTotals");
+ if (tr) {
+ var tds = tr.getElementsByTagName("td");
+ tds[0].getElementsByTagName("span")[1].firstChild.nodeValue = totals['files'];
+ tds[1].firstChild.nodeValue = totals['statements'];
+ tds[2].firstChild.nodeValue = totals['executed'];
+
+ var coverage = parseInt(totals['coverage'] / ( totals['files'] - totals['skipped'] ) );
+ if( isNaN( coverage ) ) {
+ coverage = 0;
+ }
+ tds[3].getElementsByTagName("span")[0].firstChild.nodeValue = coverage + '%';
+ tds[3].getElementsByTagName("div")[1].style.width = coverage + 'px';
+ }
+
+ }
+ jscoverage_endLengthyOperation();
+}
+
+function jscoverage_appendMissingColumn() {
+ var headerRow = document.getElementById('headerRow');
+ var missingHeader = document.createElement('th');
+ missingHeader.id = 'missingHeader';
+ missingHeader.innerHTML = '<abbr title="List of statements missed during execution">Missing</abbr>';
+ headerRow.appendChild(missingHeader);
+ var summaryTotals = document.getElementById('summaryTotals');
+ var empty = document.createElement('td');
+ empty.id = 'missingCell';
+ summaryTotals.appendChild(empty);
+}
+
+function jscoverage_removeMissingColumn() {
+ var missingNode;
+ missingNode = document.getElementById('missingHeader');
+ missingNode.parentNode.removeChild(missingNode);
+ missingNode = document.getElementById('missingCell');
+ missingNode.parentNode.removeChild(missingNode);
+}
+
+function jscoverage_checkbox_click() {
+ if (jscoverage_inLengthyOperation) {
+ return false;
+ }
+ jscoverage_beginLengthyOperation();
+ var checkbox = document.getElementById('checkbox');
+ var showMissingColumn = checkbox.checked;
+ setTimeout(function() {
+ if (showMissingColumn) {
+ jscoverage_appendMissingColumn();
+ }
+ else {
+ jscoverage_removeMissingColumn();
+ }
+ jscoverage_recalculateSummaryTab();
+ }, 50);
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+// tab 3
+
+function jscoverage_makeTable() {
+ var coverage = _$jscoverage[jscoverage_currentFile];
+ var lines = coverage.source;
+
+ // this can happen if there is an error in the original JavaScript file
+ if (! lines) {
+ lines = [];
+ }
+
+ var rows = ['<table id="sourceTable">'];
+ var i = 0;
+ var progressBar = document.getElementById('progressBar');
+ var tableHTML;
+ var currentConditionalEnd = 0;
+
+ function joinTableRows() {
+ tableHTML = rows.join('');
+ ProgressBar.setPercentage(progressBar, 60);
+ /*
+ This may be a long delay, so set a timeout of 100 ms to make sure the
+ display is updated.
+ */
+ setTimeout(appendTable, 100);
+ }
+
+ function appendTable() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = tableHTML;
+ ProgressBar.setPercentage(progressBar, 80);
+ setTimeout(jscoverage_scrollToLine, 0);
+ }
+
+ while (i < lines.length) {
+ var lineNumber = i + 1;
+
+ if (lineNumber === currentConditionalEnd) {
+ currentConditionalEnd = 0;
+ }
+ else if (currentConditionalEnd === 0 && coverage.conditionals && coverage.conditionals[lineNumber]) {
+ currentConditionalEnd = coverage.conditionals[lineNumber];
+ }
+
+ var row = '<tr>';
+ row += '<td class="numeric">' + lineNumber + '</td>';
+ var timesExecuted = coverage[lineNumber];
+ if (timesExecuted !== undefined && timesExecuted !== null) {
+ if (currentConditionalEnd !== 0) {
+ row += '<td class="y numeric">';
+ }
+ else if (timesExecuted === 0) {
+ row += '<td class="r numeric" id="line-' + lineNumber + '">';
+ }
+ else {
+ row += '<td class="g numeric">';
+ }
+ row += timesExecuted;
+ row += '</td>';
+ }
+ else {
+ row += '<td></td>';
+ }
+ row += '<td><pre>' + lines[i] + '</pre></td>';
+ row += '</tr>';
+ row += '\n';
+ rows[lineNumber] = row;
+ i++;
+ }
+ rows[i + 1] = '</table>';
+ ProgressBar.setPercentage(progressBar, 40);
+ setTimeout(joinTableRows, 0);
+}
+
+function jscoverage_scrollToLine() {
+ jscoverage_selectTab('sourceTab');
+ if (! window.jscoverage_currentLine) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var div = document.getElementById('sourceDiv');
+ if (jscoverage_currentLine === 1) {
+ div.scrollTop = 0;
+ }
+ else {
+ var cell = document.getElementById('line-' + jscoverage_currentLine);
+
+ // this might not be there if there is an error in the original JavaScript
+ if (cell) {
+ var divOffset = jscoverage_findPos(div);
+ var cellOffset = jscoverage_findPos(cell);
+ div.scrollTop = cellOffset - divOffset;
+ }
+ }
+ jscoverage_currentLine = 0;
+ jscoverage_endLengthyOperation();
+}
+
+/**
+Loads the given file (and optional line) in the source tab.
+*/
+function jscoverage_get(file, line) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ jscoverage_selectTab('sourceTab');
+ if (file === jscoverage_currentFile) {
+ jscoverage_currentLine = line;
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ if (jscoverage_currentFile === null) {
+ var tab = document.getElementById('sourceTab');
+ tab.className = '';
+ tab.onclick = jscoverage_tab_click;
+ }
+ jscoverage_currentFile = file;
+ jscoverage_currentLine = line || 1; // when changing the source, always scroll to top
+ var fileDiv = document.getElementById('fileDiv');
+ fileDiv.innerHTML = jscoverage_currentFile;
+ jscoverage_recalculateSourceTab();
+ return;
+ }
+ }, 50);
+}
+
+/**
+Calculates coverage statistics for the current source file.
+*/
+function jscoverage_recalculateSourceTab() {
+ if (! jscoverage_currentFile) {
+ jscoverage_endLengthyOperation();
+ return;
+ }
+ var progressLabel = document.getElementById('progressLabel');
+ progressLabel.innerHTML = 'Calculating coverage ...';
+ var progressBar = document.getElementById('progressBar');
+ ProgressBar.setPercentage(progressBar, 20);
+ setTimeout(jscoverage_makeTable, 0);
+}
+
+// -----------------------------------------------------------------------------
+// tabs
+
+/**
+Initializes the tab control. This function must be called when the document is
+loaded.
+*/
+function jscoverage_initTabControl() {
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child.className !== 'disabled') {
+ child.onclick = jscoverage_tab_click;
+ }
+ tabNum++;
+ }
+ }
+ jscoverage_selectTab(0);
+}
+
+/**
+Selects a tab.
+@param tab the integer index of the tab (0, 1, 2, or 3)
+ OR
+ the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_selectTab(tab) {
+ if (typeof tab !== 'number') {
+ tab = jscoverage_tabIndexOf(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var tabPages = document.getElementById('tabPages');
+ var nodeList;
+ var tabNum;
+ var i;
+ var node;
+
+ nodeList = tabs.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (node.className !== 'disabled') {
+ if (tabNum === tab) {
+ node.className = 'selected';
+ }
+ else {
+ node.className = '';
+ }
+ }
+ tabNum++;
+ }
+
+ nodeList = tabPages.childNodes;
+ tabNum = 0;
+ for (i = 0; i < nodeList.length; i++) {
+ node = nodeList.item(i);
+ if (node.nodeType !== 1) {
+ continue;
+ }
+
+ if (tabNum === tab) {
+ node.className = 'selected TabPage';
+ }
+ else {
+ node.className = 'TabPage';
+ }
+ tabNum++;
+ }
+}
+
+/**
+Returns an integer (0, 1, 2, or 3) representing the index of a given tab.
+@param tab the ID of the tab element
+ OR
+ the tab element itself
+*/
+function jscoverage_tabIndexOf(tab) {
+ if (typeof tab === 'string') {
+ tab = document.getElementById(tab);
+ }
+ var tabs = document.getElementById('tabs');
+ var i;
+ var child;
+ var tabNum = 0;
+ for (i = 0; i < tabs.childNodes.length; i++) {
+ child = tabs.childNodes.item(i);
+ if (child.nodeType === 1) {
+ if (child === tab) {
+ return tabNum;
+ }
+ tabNum++;
+ }
+ }
+//#JSCOVERAGE_IF 0
+ throw "Tab not found";
+//#JSCOVERAGE_ENDIF
+}
+
+function jscoverage_tab_click(e) {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+ var target;
+//#JSCOVERAGE_IF
+ if (e) {
+ target = e.target;
+ }
+ else if (window.event) {
+ // IE
+ target = window.event.srcElement;
+ }
+ if (target.className === 'selected') {
+ return;
+ }
+ jscoverage_beginLengthyOperation();
+ setTimeout(function() {
+ if (target.id === 'summaryTab') {
+ var tbody = document.getElementById("summaryTbody");
+ while (tbody.hasChildNodes()) {
+ tbody.removeChild(tbody.firstChild);
+ }
+ }
+ else if (target.id === 'sourceTab') {
+ var sourceDiv = document.getElementById('sourceDiv');
+ sourceDiv.innerHTML = '';
+ }
+ jscoverage_selectTab(target);
+ if (target.id === 'summaryTab') {
+ jscoverage_recalculateSummaryTab();
+ }
+ else if (target.id === 'sourceTab') {
+ jscoverage_recalculateSourceTab();
+ }
+ else {
+ jscoverage_endLengthyOperation();
+ }
+ }, 50);
+}
+
+// -----------------------------------------------------------------------------
+// progress bar
+
+var ProgressBar = {
+ init: function(element) {
+ element._percentage = 0;
+
+ /* doing this via JavaScript crashes Safari */
+/*
+ var pctGraph = document.createElement('div');
+ pctGraph.className = 'pctGraph';
+ element.appendChild(pctGraph);
+ var covered = document.createElement('div');
+ covered.className = 'covered';
+ pctGraph.appendChild(covered);
+ var pct = document.createElement('span');
+ pct.className = 'pct';
+ element.appendChild(pct);
+*/
+
+ ProgressBar._update(element);
+ },
+ setPercentage: function(element, percentage) {
+ element._percentage = percentage;
+ ProgressBar._update(element);
+ },
+ _update: function(element) {
+ var pctGraph = element.getElementsByTagName('div').item(0);
+ var covered = pctGraph.getElementsByTagName('div').item(0);
+ var pct = element.getElementsByTagName('span').item(0);
+ pct.innerHTML = element._percentage.toString() + '%';
+ covered.style.width = element._percentage + 'px';
+ }
+};
+
+// -----------------------------------------------------------------------------
+// reports
+
+function jscoverage_pad(s) {
+ return '0000'.substr(s.length) + s;
+}
+
+function jscoverage_quote(s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + jscoverage_pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+}
+
+function jscoverage_serializeCoverageToJSON() {
+ var json = [];
+ for (var file in _$jscoverage) {
+ var coverage = _$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(jscoverage_quote(file) + ':[' + array.join(',') + ']');
+ }
+ return '{' + json.join(',') + '}';
+}
+
+function jscoverage_storeButton_click() {
+ if (jscoverage_inLengthyOperation) {
+ return;
+ }
+
+ jscoverage_beginLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'visible';
+
+ var request = jscoverage_createRequest();
+ request.open('POST', '/jscoverage-store', true);
+ request.onreadystatechange = function (event) {
+ if (request.readyState === 4) {
+ var message;
+ try {
+ if (request.status !== 200 && request.status !== 201 && request.status !== 204) {
+ throw request.status;
+ }
+ message = request.responseText;
+ }
+ catch (e) {
+ if (e.toString().search(/^\d{3}$/) === 0) {
+ message = e + ': ' + request.responseText;
+ }
+ else {
+ message = 'Could not connect to server: ' + e;
+ }
+ }
+
+ jscoverage_endLengthyOperation();
+ var img = document.getElementById('storeImg');
+ img.style.visibility = 'hidden';
+
+ var div = document.getElementById('storeDiv');
+ div.appendChild(document.createTextNode(new Date() + ': ' + message));
+ div.appendChild(document.createElement('br'));
+ }
+ };
+ request.setRequestHeader('Content-Type', 'application/json');
+ var json = jscoverage_serializeCoverageToJSON();
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm b/tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm
new file mode 100644
index 0000000..053691c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.jsm
@@ -0,0 +1,22 @@
+/*
+ jscoverage.jsm - Firefox module
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+var EXPORTED_SYMBOLS = ['_$jscoverage'];
+
+var _$jscoverage = {};
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest b/tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest
new file mode 100644
index 0000000..a0f3d9f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.manifest
@@ -0,0 +1,2 @@
+content jscoverage jscoverage/
+overlay chrome://browser/content/browser.xul chrome://jscoverage/content/jscoverage.xul
diff --git a/tools/node_modules/expresso/deps/jscoverage/jscoverage.xul b/tools/node_modules/expresso/deps/jscoverage/jscoverage.xul
new file mode 100644
index 0000000..c7296b2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/jscoverage.xul
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+ jscoverage.xul - XUL overlay
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+-->
+
+<overlay id="jscoverageOverlay"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="jscoverage-overlay.js"></script>
+ <commandset>
+ <command id="jscoverageViewCommand" oncommand="jscoverage_view();"/>
+ <command id="jscoverageStoreCommand" oncommand="jscoverage_store();"/>
+ </commandset>
+ <menupopup id="menu_ToolsPopup">
+ <menu label="JSCoverage" insertafter="javascriptConsole,devToolsSeparator">
+ <menupopup>
+ <menuitem label="View Coverage" command="jscoverageViewCommand"/>
+ <menuitem label="Store Coverage" command="jscoverageStoreCommand"/>
+ </menupopup>
+ </menu>
+ </menupopup>
+</overlay>
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4
new file mode 100644
index 0000000..66bc76f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/iconv.m4
@@ -0,0 +1,180 @@
+# iconv.m4 serial AM6 (gettext-0.17)
+dnl Copyright (C) 2000-2002, 2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+ dnl those with the standalone portable GNU libiconv installed).
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+ dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed libiconv and not disabled its use
+ dnl via --without-libiconv-prefix, he wants to use it. The first
+ dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
+ am_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+ AC_CACHE_CHECK([for iconv], am_cv_func_iconv, [
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ am_cv_func_iconv=yes)
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes)
+ LIBS="$am_save_LIBS"
+ fi
+ ])
+ if test "$am_cv_func_iconv" = yes; then
+ AC_CACHE_CHECK([for working iconv], am_cv_func_iconv_works, [
+ dnl This tests against bugs in AIX 5.1 and HP-UX 11.11.
+ am_save_LIBS="$LIBS"
+ if test $am_cv_lib_iconv = yes; then
+ LIBS="$LIBS $LIBICONV"
+ fi
+ AC_TRY_RUN([
+#include <iconv.h>
+#include <string.h>
+int main ()
+{
+ /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+ returns. */
+ {
+ iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+ if (cd_utf8_to_88591 != (iconv_t)(-1))
+ {
+ static const char input[] = "\342\202\254"; /* EURO SIGN */
+ char buf[10];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_utf8_to_88591,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res == 0)
+ return 1;
+ }
+ }
+#if 0 /* This bug could be worked around by the caller. */
+ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
+ {
+ iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+ if (cd_88591_to_utf8 != (iconv_t)(-1))
+ {
+ static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+ char buf[50];
+ const char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_88591_to_utf8,
+ (char **) &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if ((int)res > 0)
+ return 1;
+ }
+ }
+#endif
+ /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+ provided. */
+ if (/* Try standardized names. */
+ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+ /* Try IRIX, OSF/1 names. */
+ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+ /* Try AIX names. */
+ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+ /* Try HP-UX names. */
+ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+ return 1;
+ return 0;
+}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
+ [case "$host_os" in
+ aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+ *) am_cv_func_iconv_works="guessing yes" ;;
+ esac])
+ LIBS="$am_save_LIBS"
+ ])
+ case "$am_cv_func_iconv_works" in
+ *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+ *) am_func_iconv=yes ;;
+ esac
+ else
+ am_func_iconv=no am_cv_lib_iconv=no
+ fi
+ if test "$am_func_iconv" = yes; then
+ AC_DEFINE(HAVE_ICONV, 1,
+ [Define if you have the iconv() function and it works.])
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ AC_MSG_CHECKING([how to link with libiconv])
+ AC_MSG_RESULT([$LIBICONV])
+ else
+ dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+ dnl either.
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+ AC_SUBST(LIBICONV)
+ AC_SUBST(LTLIBICONV)
+])
+
+AC_DEFUN([AM_ICONV],
+[
+ AM_ICONV_LINK
+ if test "$am_cv_func_iconv" = yes; then
+ AC_MSG_CHECKING([for iconv declaration])
+ AC_CACHE_VAL(am_cv_proto_iconv, [
+ AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+ am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ AC_MSG_RESULT([$]{ac_t:-
+ }[$]am_cv_proto_iconv)
+ AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+ [Define as const if the declaration of iconv() needs const.])
+ fi
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4
new file mode 100644
index 0000000..96c4e2c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/lib-ld.m4
@@ -0,0 +1,110 @@
+# lib-ld.m4 serial 3 (gettext-0.13)
+dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ acl_cv_prog_gnu_ld=yes ;;
+*)
+ acl_cv_prog_gnu_ld=no ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]* | [A-Za-z]:[\\/]*)]
+ [re_direlt='/[^/][^/]*/\.\./']
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(acl_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break ;;
+ *)
+ test "$with_gnu_ld" != yes && break ;;
+ esac
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4
new file mode 100644
index 0000000..e3d26fc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/lib-link.m4
@@ -0,0 +1,709 @@
+# lib-link.m4 serial 13 (gettext-0.17)
+dnl Copyright (C) 2001-2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ(2.54)
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ define([Name],[translit([$1],[./-], [___])])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+ ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+ ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+ ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+ ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+ ])
+ LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+ LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+ INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+ LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+ dnl results of this search when this library appears as a dependency.
+ HAVE_LIB[]NAME=yes
+ undefine([Name])
+ undefine([NAME])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. If found, it
+dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
+dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ define([Name],[translit([$1],[./-], [___])])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+ dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+ dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed lib[]Name and not disabled its use
+ dnl via --without-lib[]Name-prefix, he wants to use it.
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+ AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+ ac_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIB[]NAME"
+ AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
+ LIBS="$ac_save_LIBS"
+ ])
+ if test "$ac_cv_lib[]Name" = yes; then
+ HAVE_LIB[]NAME=yes
+ AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
+ AC_MSG_CHECKING([how to link with lib[]$1])
+ AC_MSG_RESULT([$LIB[]NAME])
+ else
+ HAVE_LIB[]NAME=no
+ dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+ dnl $INC[]NAME either.
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIB[]NAME=
+ LTLIB[]NAME=
+ LIB[]NAME[]_PREFIX=
+ fi
+ AC_SUBST([HAVE_LIB]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ undefine([Name])
+ undefine([NAME])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl acl_libext,
+dnl acl_shlibext,
+dnl acl_hardcode_libdir_flag_spec,
+dnl acl_hardcode_libdir_separator,
+dnl acl_hardcode_direct,
+dnl acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+ dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+ m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
+ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
+ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+ AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+ ])
+ wl="$acl_cv_wl"
+ acl_libext="$acl_cv_libext"
+ acl_shlibext="$acl_cv_shlibext"
+ acl_libname_spec="$acl_cv_libname_spec"
+ acl_library_names_spec="$acl_cv_library_names_spec"
+ acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ acl_hardcode_direct="$acl_cv_hardcode_direct"
+ acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ dnl Determine whether the user wants rpath handling at all.
+ AC_ARG_ENABLE(rpath,
+ [ --disable-rpath do not hardcode runtime library paths],
+ :, enable_rpath=yes)
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ dnl Autoconf >= 2.61 supports dots in --with options.
+ define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix],
+[ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
+ --without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+])
+ dnl Search the library and its dependencies in $additional_libdir and
+ dnl $LDFLAGS. Using breadth-first-seach.
+ LIB[]NAME=
+ LTLIB[]NAME=
+ INC[]NAME=
+ LIB[]NAME[]_PREFIX=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='$1 $2'
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+ dnl or AC_LIB_HAVE_LINKFLAGS call.
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+ else
+ dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+ dnl that this library doesn't exist. So just drop it.
+ :
+ fi
+ else
+ dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+ dnl and the already constructed $LIBNAME/$LTLIBNAME.
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
+ if test -n "$acl_shlibext"; then
+ shrext=".$acl_shlibext" # typically: shrext=.so
+ else
+ shrext=
+ fi
+ if test $use_additional = yes; then
+ dir="$additional_libdir"
+ dnl The same code as in the loop below:
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ dnl Found the library.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ dnl Linking with a shared library. We attempt to hardcode its
+ dnl directory into the executable's runpath, unless it's the
+ dnl standard /usr/lib.
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
+ dnl No hardcoding is needed.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ dnl The hardcoding into $LIBNAME is system dependent.
+ if test "$acl_hardcode_direct" = yes; then
+ dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+ dnl resulting binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ dnl Rely on "-L$found_dir".
+ dnl But don't add it if it's already contained in the LDFLAGS
+ dnl or the already constructed $LIBNAME
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+ fi
+ if test "$acl_hardcode_minus_L" != no; then
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+ dnl here, because this doesn't fit in flags passed to the
+ dnl compiler. So give up. No hardcoding. This affects only
+ dnl very old systems.
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ dnl Linking with a static library.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+ else
+ dnl We shouldn't come here, but anyway it's good to have a
+ dnl fallback.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+ fi
+ fi
+ dnl Assume the include files are nearby.
+ additional_includedir=
+ case "$found_dir" in
+ */$acl_libdirstem | */$acl_libdirstem/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+ LIB[]NAME[]_PREFIX="$basedir"
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ dnl Potentially add $additional_includedir to $INCNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 3. if it's already present in $CPPFLAGS or the already
+ dnl constructed $INCNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INC[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $INCNAME.
+ INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ dnl Look for dependencies.
+ if test -n "$found_la"; then
+ dnl Read the .la file. It defines the variables
+ dnl dlname, library_names, old_library, dependency_libs, current,
+ dnl age, revision, installed, dlopen, dlpreopen, libdir.
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ dnl We use only dependency_libs.
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 3. if it's already present in $LDFLAGS or the already
+ dnl constructed $LIBNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LIBNAME.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LTLIBNAME.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ dnl Handle this in the next round.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ dnl Handle this in the next round. Throw away the .la's
+ dnl directory; it is already contained in a preceding -L
+ dnl option.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ dnl Most likely an immediate library name.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ dnl Didn't find the library; assume it is in the system directories
+ dnl known to the linker and runtime loader. (All the system
+ dnl directories known to the linker should also be known to the
+ dnl runtime loader, otherwise the system is severely misconfigured.)
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user must
+ dnl pass all path elements in one option. We can arrange that for a
+ dnl single library, but not when more than one $LIBNAMEs are used.
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+ done
+ dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ dnl When using libtool, the option that works for both libraries and
+ dnl executables is -R. The -R options are cumulative.
+ for found_dir in $ltrpathdirs; do
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+ done
+ fi
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+ for element in [$2]; do
+ haveit=
+ for x in $[$1]; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ [$1]="${[$1]}${[$1]:+ }$element"
+ fi
+ done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+ AC_REQUIRE([AC_LIB_RPATH])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ $1=
+ if test "$enable_rpath" != no; then
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode directories into the resulting
+ dnl binary.
+ rpathdirs=
+ next=
+ for opt in $2; do
+ if test -n "$next"; then
+ dir="$next"
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next=
+ else
+ case $opt in
+ -L) next=yes ;;
+ -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next= ;;
+ *) next= ;;
+ esac
+ fi
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n ""$3""; then
+ dnl libtool is used for linking. Use -R options.
+ for dir in $rpathdirs; do
+ $1="${$1}${$1:+ }-R$dir"
+ done
+ else
+ dnl The linker is used for linking directly.
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user
+ dnl must pass all path elements in one option.
+ alldirs=
+ for dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="${$1}${$1:+ }$flag"
+ done
+ fi
+ fi
+ fi
+ fi
+ fi
+ AC_SUBST([$1])
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4 b/tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4
new file mode 100644
index 0000000..a8684e1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/m4/lib-prefix.m4
@@ -0,0 +1,185 @@
+# lib-prefix.m4 serial 5 (gettext-0.15)
+dnl Copyright (C) 2001-2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+ AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib-prefix],
+[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+ --without-lib-prefix don't search for libraries in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+])
+ if test $use_additional = yes; then
+ dnl Potentially add $additional_includedir to $CPPFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's already present in $CPPFLAGS,
+ dnl 3. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ for x in $CPPFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $CPPFLAGS.
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ dnl Potentially add $additional_libdir to $LDFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's already present in $LDFLAGS,
+ dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ for x in $LDFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LDFLAGS.
+ LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+ dnl Unfortunately, prefix and exec_prefix get only finally determined
+ dnl at the end of configure.
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ $1
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing
+dnl the basename of the libdir, either "lib" or "lib64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+ dnl There is no formal standard regarding lib and lib64. The current
+ dnl practice is that on a system supporting 32-bit and 64-bit instruction
+ dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit
+ dnl libraries go under $prefix/lib. We determine the compiler's default
+ dnl mode by looking at the compiler's library search path. If at least
+ dnl of its elements ends in /lib64 or points to a directory whose absolute
+ dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the
+ dnl default, namely "lib".
+ acl_libdirstem=lib
+ searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+])
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh
new file mode 100644
index 0000000..cdc95f2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+set -e
+
+version=0.4
+distdir=jscoverage-${version}
+zipfile=${distdir}-windows.zip
+
+rm -fr $distdir
+mkdir $distdir
+
+cp -a doc $distdir
+cp -a jscoverage.exe jscoverage-server.exe $distdir
+strip $distdir/*.exe
+cp -a COPYING $distdir
+unix2dos $distdir/COPYING
+cp -a README $distdir/README.txt
+unix2dos $distdir/README.txt
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+rm -f $zipfile
+zip -X -r $zipfile $distdir -x '*/.svn/*'
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in
new file mode 100644
index 0000000..16bde27
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-bin-dist.sh.in
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+set -e
+
+version=@VERSION@
+distdir=jscoverage-${version}
+zipfile=${distdir}-windows.zip
+
+rm -fr $distdir
+mkdir $distdir
+
+cp -a doc $distdir
+cp -a jscoverage.exe jscoverage-server.exe $distdir
+strip $distdir/*.exe
+cp -a COPYING $distdir
+unix2dos $distdir/COPYING
+cp -a README $distdir/README.txt
+unix2dos $distdir/README.txt
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+rm -f $zipfile
+zip -X -r $zipfile $distdir -x '*/.svn/*'
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-dist.sh b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh
new file mode 100644
index 0000000..bf7ee0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+version=0.4
+distdir=jscoverage-${version}
+
+rm -fr $distdir
+mkdir $distdir
+
+# copy all files in SVN
+for file in $(svn status -qv | sed 's/.* //' | sort)
+do
+ if [ -f "$file" ]
+ then
+ cp -a --parents "$file" $distdir
+ fi
+done
+
+# add generated files
+cp -a --parents aclocal.m4 \
+ configure \
+ config.h.in \
+ Makefile.in config.guess config.sub depcomp install-sh missing \
+ $distdir
+cp -a --parents tests/Makefile.in $distdir
+cp -a --parents doc/instrumented $distdir
+cp -a --parents doc/instrumented-inverted $distdir
+
+# remove unnecessary files
+rm $distdir/TIMESTAMP
+rm $distdir/bootstrap.sh
+rm $distdir/make-maintainer-clean.sh
+rm -r $distdir/scriptaculous*
+rm -r $distdir/selenium
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+tarfile=${distdir}.tar
+tar cvf $tarfile --owner=root --group=root $distdir
+bzip2 -c $tarfile > ${tarfile}.bz2
+lzma -c $tarfile > ${tarfile}.lzma
diff --git a/tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in
new file mode 100644
index 0000000..f0a4282
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/make-dist.sh.in
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+version=@VERSION@
+distdir=jscoverage-${version}
+
+rm -fr $distdir
+mkdir $distdir
+
+# copy all files in SVN
+for file in $(svn status -qv | sed 's/.* //' | sort)
+do
+ if [ -f "$file" ]
+ then
+ cp -a --parents "$file" $distdir
+ fi
+done
+
+# add generated files
+cp -a --parents aclocal.m4 \
+ configure \
+ config.h.in \
+ Makefile.in config.guess config.sub depcomp install-sh missing \
+ $distdir
+cp -a --parents tests/Makefile.in $distdir
+cp -a --parents doc/instrumented $distdir
+cp -a --parents doc/instrumented-inverted $distdir
+
+# remove unnecessary files
+rm $distdir/TIMESTAMP
+rm $distdir/bootstrap.sh
+rm $distdir/make-maintainer-clean.sh
+rm -r $distdir/scriptaculous*
+rm -r $distdir/selenium
+
+timestamp=`cat TIMESTAMP`
+find $distdir -exec touch -d "$timestamp" {} \;
+
+tarfile=${distdir}.tar
+tar cvf $tarfile --owner=root --group=root $distdir
+bzip2 -c $tarfile > ${tarfile}.bz2
+lzma -c $tarfile > ${tarfile}.lzma
diff --git a/tools/node_modules/expresso/deps/jscoverage/missing b/tools/node_modules/expresso/deps/jscoverage/missing
new file mode 100755
index 0000000..1c8ff70
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/missing
@@ -0,0 +1,367 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2006-05-10.23
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
+# Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+ configure_ac=configure.ac
+else
+ configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+ # Try to run requested program, and just exit if it succeeds.
+ run=
+ shift
+ "$@" && exit 0
+ # Exit code 63 means version mismatch. This often happens
+ # when the user try to use an ancient version of a tool on
+ # a file that requires a minimum version. In this case we
+ # we should proceed has if the program had been absent, or
+ # if --run hadn't been passed.
+ if test $? = 63; then
+ run=:
+ msg="probably too old"
+ fi
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+ --run try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ autom4te touch the output file, or create a stub one
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ help2man touch the output file
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ tar try tar, gnutar, gtar, then tar without non-portable flags
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Now exit if we have it, but it failed. Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).
+case $1 in
+ lex|yacc)
+ # Not GNU programs, they don't have --version.
+ ;;
+
+ tar)
+ if test -n "$run"; then
+ echo 1>&2 "ERROR: \`tar' requires --run"
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ exit 1
+ fi
+ ;;
+
+ *)
+ if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+ # We have it, but it failed.
+ exit 1
+ elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+ # Could not run --version or --help. This is probably someone
+ # running `$TOOL --version' or `$TOOL --help' to check whether
+ # $TOOL exists and not knowing $TOOL uses missing.
+ exit 1
+ fi
+ ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $1 in
+ aclocal*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case $f in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake*)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ autom4te)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them.
+ You can get \`$1' as part of \`Autoconf' from any GNU
+ archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo "#! /bin/sh"
+ echo "# Created by GNU Automake missing as a replacement of"
+ echo "# $ $@"
+ echo "exit 0"
+ chmod +x $file
+ exit 1
+ fi
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f y.tab.h; then
+ echo >y.tab.h
+ fi
+ if test ! -f y.tab.c; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if test $# -ne 1; then
+ eval LASTARG="\${$#}"
+ case $LASTARG in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if test -f "$SRCFILE"; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if test ! -f lex.yy.c; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ help2man)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a dependency of a manual page. You may need the
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
+
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -f "$file"; then
+ touch $file
+ else
+ test -z "$file" || exec >$file
+ echo ".ab help2man is required to generate this page"
+ exit 1
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ # The file to touch is that specified with -o ...
+ file=`echo "$*" | sed -n "$sed_output"`
+ test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+ if test -z "$file"; then
+ # ... or it is the one specified with @setfilename ...
+ infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '
+ /^@setfilename/{
+ s/.* \([^ ]*\) *$/\1/
+ p
+ q
+ }' $infile`
+ # ... or it is derived from the source name (dir/f.texi becomes f.info)
+ test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+ fi
+ # If the file does not exist, the user really needs makeinfo;
+ # let's fail without touching anything.
+ test -f $file || exit 1
+ touch $file
+ ;;
+
+ tar)
+ shift
+
+ # We have already tried tar in the generic part.
+ # Look for gnutar/gtar before invocation to avoid ugly error
+ # messages.
+ if (gnutar --version > /dev/null 2>&1); then
+ gnutar "$@" && exit 0
+ fi
+ if (gtar --version > /dev/null 2>&1); then
+ gtar "$@" && exit 0
+ fi
+ firstarg="$1"
+ if shift; then
+ case $firstarg in
+ *o*)
+ firstarg=`echo "$firstarg" | sed s/o//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ case $firstarg in
+ *h*)
+ firstarg=`echo "$firstarg" | sed s/h//`
+ tar "$firstarg" "$@" && exit 0
+ ;;
+ esac
+ fi
+
+ echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+ You may want to install GNU tar or Free paxutils, or check the
+ command line arguments."
+ exit 1
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+ You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequisites for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/tools/node_modules/expresso/deps/jscoverage/node-jscoverage b/tools/node_modules/expresso/deps/jscoverage/node-jscoverage
new file mode 100755
index 0000000..56fcddd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/node-jscoverage
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/report.js b/tools/node_modules/expresso/deps/jscoverage/report.js
new file mode 100644
index 0000000..13ce04a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/report.js
@@ -0,0 +1,76 @@
+if (! window.jscoverage_report) {
+ window.jscoverage_report = function jscoverage_report(dir) {
+ var createRequest = function () {
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+ else if (window.ActiveXObject) {
+ return new ActiveXObject("Microsoft.XMLHTTP");
+ }
+ };
+
+ var pad = function (s) {
+ return '0000'.substr(s.length) + s;
+ };
+
+ var quote = function (s) {
+ return '"' + s.replace(/[\u0000-\u001f"\\\u007f-\uffff]/g, function (c) {
+ switch (c) {
+ case '\b':
+ return '\\b';
+ case '\f':
+ return '\\f';
+ case '\n':
+ return '\\n';
+ case '\r':
+ return '\\r';
+ case '\t':
+ return '\\t';
+ // IE doesn't support this
+ /*
+ case '\v':
+ return '\\v';
+ */
+ case '"':
+ return '\\"';
+ case '\\':
+ return '\\\\';
+ default:
+ return '\\u' + pad(c.charCodeAt(0).toString(16));
+ }
+ }) + '"';
+ };
+
+ var json = [];
+ for (var file in top._$jscoverage) {
+ var coverage = top._$jscoverage[file];
+ var array = [];
+ var length = coverage.length;
+ for (var line = 0; line < length; line++) {
+ var value = coverage[line];
+ if (value === undefined || value === null) {
+ value = 'null';
+ }
+ array.push(value);
+ }
+ json.push(quote(file) + ':[' + array.join(',') + ']');
+ }
+ json = '{' + json.join(',') + '}';
+
+ var request = createRequest();
+ var url = '/jscoverage-store';
+ if (dir) {
+ url += '/' + encodeURIComponent(dir);
+ }
+ request.open('POST', url, false);
+ request.setRequestHeader('Content-Type', 'application/json');
+ request.setRequestHeader('Content-Length', json.length.toString());
+ request.send(json);
+ if (request.status === 200 || request.status === 201 || request.status === 204) {
+ return request.responseText;
+ }
+ else {
+ throw request.status;
+ }
+ };
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/resource-manager.c b/tools/node_modules/expresso/deps/jscoverage/resource-manager.c
new file mode 100644
index 0000000..e8e8885
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/resource-manager.c
@@ -0,0 +1,59 @@
+/*
+ resource-manager.c - handles embedded files
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include "resource-manager.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+#include "resources.c"
+
+const struct Resource * get_resource(const char * name) {
+ int num_resources = sizeof(RESOURCES) / sizeof(struct Resource);
+ for (int i = 0; i < num_resources; i++) {
+ if (strcmp(RESOURCES[i].name, name) == 0) {
+ return &RESOURCES[i];
+ }
+ }
+ return NULL;
+}
+
+void copy_resource_to_stream(const char * resource, FILE * stream) {
+ const struct Resource * r = get_resource(resource);
+ assert(r != NULL);
+ if (fwrite(r->data, 1, r->length, stream) != r->length) {
+ fatal("cannot write to stream");
+ }
+}
+
+void copy_resource(const char * resource, const char * destination_directory) {
+ char * file = make_path(destination_directory, resource);
+ char * directory = make_dirname(file);
+ mkdirs(directory);
+ free(directory);
+ FILE * f = xfopen(file, "wb");
+ copy_resource_to_stream(resource, f);
+ fclose(f);
+ free(file);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/resource-manager.h b/tools/node_modules/expresso/deps/jscoverage/resource-manager.h
new file mode 100644
index 0000000..5a0a681
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/resource-manager.h
@@ -0,0 +1,46 @@
+/*
+ resource-manager.h - handles embedded files
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef RESOURCE_MANAGER_H_
+#define RESOURCE_MANAGER_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Resource {
+ const char * name;
+ const unsigned char * data;
+ const size_t length;
+};
+
+const struct Resource * get_resource(const char * name);
+
+void copy_resource_to_stream(const char * resource, FILE * stream);
+
+void copy_resource(const char * resource, const char * destination_directory);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RESOURCE_MANAGER_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/resources.c b/tools/node_modules/expresso/deps/jscoverage/resources.c
new file mode 100644
index 0000000..8b9664e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/resources.c
@@ -0,0 +1,3596 @@
+const unsigned char RESOURCE1_[] = {
+
+ 0x55,0x73,0x61,0x67,0x65,0x3a,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x53,0x4f,0x55,0x52,0x43,0x45,0x2d,0x44,0x49,0x52,0x45,0x43,0x54,0x4f,
+ 0x52,0x59,0x20,0x44,0x45,0x53,0x54,0x49,0x4e,0x41,0x54,0x49,0x4f,0x4e,0x2d,0x44,
+ 0x49,0x52,0x45,0x43,0x54,0x4f,0x52,0x59,0x0a,0x49,0x6e,0x73,0x74,0x72,0x75,0x6d,
+ 0x65,0x6e,0x74,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x77,
+ 0x69,0x74,0x68,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0a,0x0a,
+ 0x4f,0x70,0x74,0x69,0x6f,0x6e,0x73,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x65,0x6e,0x63,0x6f,0x64,0x69,0x6e,0x67,0x3d,0x45,0x4e,0x43,0x4f,0x44,0x49,
+ 0x4e,0x47,0x20,0x20,0x20,0x61,0x73,0x73,0x75,0x6d,0x65,0x20,0x2e,0x6a,0x73,0x20,
+ 0x66,0x69,0x6c,0x65,0x73,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x67,0x69,
+ 0x76,0x65,0x6e,0x20,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x20,0x65,0x6e,
+ 0x63,0x6f,0x64,0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x65,
+ 0x78,0x63,0x6c,0x75,0x64,0x65,0x3d,0x50,0x41,0x54,0x48,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x63,0x6f,0x70,0x79,0x20,0x50,
+ 0x41,0x54,0x48,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x6a,0x73,0x2d,0x76,
+ 0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x20,
+ 0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x70,0x65,0x63,0x69,0x66,0x69,0x65,
+ 0x64,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x76,0x65,0x72,
+ 0x73,0x69,0x6f,0x6e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x6e,0x6f,0x2d,
+ 0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x70,0x65,0x72,0x66,0x6f,0x72,0x6d,0x20,
+ 0x73,0x79,0x6e,0x74,0x61,0x78,0x20,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,
+ 0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x6e,0x6f,0x2d,0x69,
+ 0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,0x3d,0x50,0x41,0x54,0x48,0x20,0x20,
+ 0x63,0x6f,0x70,0x79,0x20,0x62,0x75,0x74,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,
+ 0x69,0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,0x20,0x50,0x41,0x54,0x48,0x0a,
+ 0x20,0x20,0x2d,0x76,0x2c,0x20,0x2d,0x2d,0x76,0x65,0x72,0x62,0x6f,0x73,0x65,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x78,0x70,0x6c,
+ 0x61,0x69,0x6e,0x20,0x77,0x68,0x61,0x74,0x20,0x69,0x73,0x20,0x62,0x65,0x69,0x6e,
+ 0x67,0x20,0x64,0x6f,0x6e,0x65,0x0a,0x20,0x20,0x2d,0x68,0x2c,0x20,0x2d,0x2d,0x68,
+ 0x65,0x6c,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x20,0x74,0x68,0x69,0x73,0x20,
+ 0x68,0x65,0x6c,0x70,0x20,0x61,0x6e,0x64,0x20,0x65,0x78,0x69,0x74,0x0a,0x20,0x20,
+ 0x2d,0x56,0x2c,0x20,0x2d,0x2d,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,
+ 0x79,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,
+ 0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x65,0x78,0x69,0x74,0x0a,
+};
+const unsigned char RESOURCE2_[] = {
+
+ 0x55,0x73,0x61,0x67,0x65,0x3a,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2d,0x73,0x65,0x72,0x76,0x65,0x72,0x20,0x5b,0x4f,0x50,0x54,0x49,0x4f,0x4e,
+ 0x5d,0x2e,0x2e,0x2e,0x0a,0x52,0x75,0x6e,0x20,0x61,0x20,0x73,0x65,0x72,0x76,0x65,
+ 0x72,0x20,0x66,0x6f,0x72,0x20,0x69,0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,
+ 0x69,0x6e,0x67,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x77,
+ 0x69,0x74,0x68,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0a,0x0a,
+ 0x4f,0x70,0x74,0x69,0x6f,0x6e,0x73,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2d,0x72,0x6f,0x6f,0x74,0x3d,0x44,
+ 0x49,0x52,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x20,0x63,0x6f,0x6e,0x74,0x65,
+ 0x6e,0x74,0x20,0x66,0x72,0x6f,0x6d,0x20,0x44,0x49,0x52,0x20,0x28,0x64,0x65,0x66,
+ 0x61,0x75,0x6c,0x74,0x3a,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x64,0x69,
+ 0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x65,0x6e,0x63,0x6f,0x64,0x69,0x6e,0x67,0x3d,0x45,0x4e,0x43,0x4f,0x44,0x49,
+ 0x4e,0x47,0x20,0x20,0x20,0x61,0x73,0x73,0x75,0x6d,0x65,0x20,0x2e,0x6a,0x73,0x20,
+ 0x66,0x69,0x6c,0x65,0x73,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x67,0x69,
+ 0x76,0x65,0x6e,0x20,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x20,0x65,0x6e,
+ 0x63,0x6f,0x64,0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x69,
+ 0x70,0x2d,0x61,0x64,0x64,0x72,0x65,0x73,0x73,0x3d,0x41,0x44,0x44,0x52,0x45,0x53,
+ 0x53,0x20,0x20,0x62,0x69,0x6e,0x64,0x20,0x74,0x6f,0x20,0x41,0x44,0x44,0x52,0x45,
+ 0x53,0x53,0x20,0x28,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,0x20,0x31,0x32,0x37,
+ 0x2e,0x30,0x2e,0x30,0x2e,0x31,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,
+ 0x6a,0x73,0x2d,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x56,0x45,0x52,0x53,0x49,
+ 0x4f,0x4e,0x20,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x70,0x65,0x63,
+ 0x69,0x66,0x69,0x65,0x64,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,
+ 0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,
+ 0x2d,0x6e,0x6f,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x70,0x65,0x72,0x66,
+ 0x6f,0x72,0x6d,0x20,0x73,0x79,0x6e,0x74,0x61,0x78,0x20,0x68,0x69,0x67,0x68,0x6c,
+ 0x69,0x67,0x68,0x74,0x69,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,
+ 0x6e,0x6f,0x2d,0x69,0x6e,0x73,0x74,0x72,0x75,0x6d,0x65,0x6e,0x74,0x3d,0x55,0x52,
+ 0x4c,0x20,0x20,0x20,0x64,0x6f,0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x73,0x74,0x72,
+ 0x75,0x6d,0x65,0x6e,0x74,0x20,0x55,0x52,0x4c,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x2d,0x2d,0x70,0x6f,0x72,0x74,0x3d,0x50,0x4f,0x52,0x54,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x75,0x73,0x65,0x20,0x50,0x4f,0x52,0x54,0x20,0x66,
+ 0x6f,0x72,0x20,0x54,0x43,0x50,0x20,0x70,0x6f,0x72,0x74,0x20,0x28,0x64,0x65,0x66,
+ 0x61,0x75,0x6c,0x74,0x3a,0x20,0x38,0x30,0x38,0x30,0x29,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x2d,0x2d,0x70,0x72,0x6f,0x78,0x79,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x75,0x6e,0x20,0x61,0x73,0x20,0x61,
+ 0x20,0x70,0x72,0x6f,0x78,0x79,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x72,
+ 0x65,0x70,0x6f,0x72,0x74,0x2d,0x64,0x69,0x72,0x3d,0x44,0x49,0x52,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x73,0x74,0x6f,0x72,0x65,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x20,
+ 0x74,0x6f,0x20,0x44,0x49,0x52,0x20,0x28,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,
+ 0x20,0x60,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x72,0x65,0x70,
+ 0x6f,0x72,0x74,0x27,0x29,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x73,0x68,
+ 0x75,0x74,0x64,0x6f,0x77,0x6e,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x73,0x74,0x6f,0x70,0x20,0x61,0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,
+ 0x20,0x73,0x65,0x72,0x76,0x65,0x72,0x0a,0x20,0x20,0x2d,0x76,0x2c,0x20,0x2d,0x2d,
+ 0x76,0x65,0x72,0x62,0x6f,0x73,0x65,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x65,0x78,0x70,0x6c,0x61,0x69,0x6e,0x20,0x77,0x68,0x61,0x74,
+ 0x20,0x69,0x73,0x20,0x62,0x65,0x69,0x6e,0x67,0x20,0x64,0x6f,0x6e,0x65,0x0a,0x20,
+ 0x20,0x2d,0x68,0x2c,0x20,0x2d,0x2d,0x68,0x65,0x6c,0x70,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,
+ 0x61,0x79,0x20,0x74,0x68,0x69,0x73,0x20,0x68,0x65,0x6c,0x70,0x20,0x61,0x6e,0x64,
+ 0x20,0x65,0x78,0x69,0x74,0x0a,0x20,0x20,0x2d,0x56,0x2c,0x20,0x2d,0x2d,0x76,0x65,
+ 0x72,0x73,0x69,0x6f,0x6e,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,
+ 0x6e,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,
+ 0x64,0x20,0x65,0x78,0x69,0x74,0x0a,
+};
+const unsigned char RESOURCE3_[] = {
+
+ 0x2f,0x2a,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x6a,0x73,0x6d,0x20,0x2d,0x20,0x46,0x69,0x72,0x65,0x66,0x6f,0x78,0x20,
+ 0x6d,0x6f,0x64,0x75,0x6c,0x65,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,
+ 0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,
+ 0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0a,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,
+ 0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,
+ 0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,
+ 0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,
+ 0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,
+ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,
+ 0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,
+ 0x65,0x20,0x61,0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,
+ 0x79,0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,
+ 0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,
+ 0x6f,0x6e,0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,
+ 0x6f,0x6e,0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,
+ 0x6e,0x73,0x65,0x2c,0x20,0x6f,0x72,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,
+ 0x79,0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,
+ 0x20,0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0a,
+ 0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,
+ 0x6d,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,
+ 0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,
+ 0x74,0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,
+ 0x66,0x75,0x6c,0x2c,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,
+ 0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,
+ 0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,
+ 0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,
+ 0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,
+ 0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,
+ 0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,
+ 0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,
+ 0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,
+ 0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,
+ 0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,
+ 0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0a,0x0a,0x20,0x20,0x20,0x20,
+ 0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,0x65,0x20,
+ 0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,0x79,0x20,
+ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,
+ 0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,
+ 0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,
+ 0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x3b,0x20,0x69,
+ 0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x6f,0x20,
+ 0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,
+ 0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x49,0x6e,
+ 0x63,0x2e,0x2c,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,0x72,0x61,0x6e,0x6b,
+ 0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,0x46,0x69,0x66,0x74,
+ 0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,0x74,0x6f,0x6e,0x2c,
+ 0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,0x30,0x31,0x20,0x55,
+ 0x53,0x41,0x2e,0x0a,0x2a,0x2f,0x0a,0x0a,0x76,0x61,0x72,0x20,0x45,0x58,0x50,0x4f,
+ 0x52,0x54,0x45,0x44,0x5f,0x53,0x59,0x4d,0x42,0x4f,0x4c,0x53,0x20,0x3d,0x20,0x5b,
+ 0x27,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x27,0x5d,0x3b,
+ 0x0a,0x0a,0x76,0x61,0x72,0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,
+};
+const unsigned char RESOURCE4_[] = {
+
+ 0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x0a,0x6f,
+ 0x76,0x65,0x72,0x6c,0x61,0x79,0x20,0x63,0x68,0x72,0x6f,0x6d,0x65,0x3a,0x2f,0x2f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2f,0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2e,0x78,0x75,0x6c,0x20,0x63,0x68,0x72,0x6f,
+ 0x6d,0x65,0x3a,0x2f,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,
+ 0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x78,0x75,0x6c,0x0a,
+};
+const unsigned char RESOURCE5_[] = {
+
+ 0x3c,0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x3d,0x22,0x31,
+ 0x2e,0x30,0x22,0x3f,0x3e,0x0a,0x3c,0x21,0x2d,0x2d,0x0a,0x20,0x20,0x20,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x78,0x75,0x6c,0x20,0x2d,0x20,
+ 0x58,0x55,0x4c,0x20,0x6f,0x76,0x65,0x72,0x6c,0x61,0x79,0x0a,0x20,0x20,0x20,0x20,
+ 0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,
+ 0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,
+ 0x63,0x6f,0x6d,0x0a,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,
+ 0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,0x73,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,
+ 0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,0x74,0x20,
+ 0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,
+ 0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,
+ 0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,
+ 0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,
+ 0x68,0x65,0x64,0x20,0x62,0x79,0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,
+ 0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,
+ 0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,
+ 0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,
+ 0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,0x20,0x6f,0x72,0x0a,0x20,0x20,0x20,
+ 0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,
+ 0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,
+ 0x69,0x6f,0x6e,0x2e,0x0a,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,
+ 0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,
+ 0x62,0x75,0x74,0x65,0x64,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,
+ 0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,
+ 0x65,0x20,0x75,0x73,0x65,0x66,0x75,0x6c,0x2c,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,
+ 0x74,0x20,0x57,0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,
+ 0x52,0x52,0x41,0x4e,0x54,0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,
+ 0x65,0x76,0x65,0x6e,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,
+ 0x20,0x77,0x61,0x72,0x72,0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0a,0x20,0x20,0x20,
+ 0x20,0x4d,0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,
+ 0x20,0x6f,0x72,0x20,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,
+ 0x41,0x20,0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,
+ 0x50,0x4f,0x53,0x45,0x2e,0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0a,0x20,
+ 0x20,0x20,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,
+ 0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,
+ 0x72,0x20,0x6d,0x6f,0x72,0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0a,
+ 0x0a,0x20,0x20,0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,
+ 0x68,0x61,0x76,0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,
+ 0x63,0x6f,0x70,0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,
+ 0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,
+ 0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0a,0x20,0x20,0x20,
+ 0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,
+ 0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,
+ 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,
+ 0x46,0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,
+ 0x20,0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,
+ 0x73,0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,
+ 0x33,0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0a,0x2d,0x2d,0x3e,0x0a,0x0a,0x3c,0x6f,
+ 0x76,0x65,0x72,0x6c,0x61,0x79,0x20,0x69,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x4f,0x76,0x65,0x72,0x6c,0x61,0x79,0x22,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3d,0x22,0x68,0x74,
+ 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,
+ 0x2e,0x6f,0x72,0x67,0x2f,0x6b,0x65,0x79,0x6d,0x61,0x73,0x74,0x65,0x72,0x2f,0x67,
+ 0x61,0x74,0x65,0x6b,0x65,0x65,0x70,0x65,0x72,0x2f,0x74,0x68,0x65,0x72,0x65,0x2e,
+ 0x69,0x73,0x2e,0x6f,0x6e,0x6c,0x79,0x2e,0x78,0x75,0x6c,0x22,0x3e,0x0a,0x20,0x20,
+ 0x3c,0x73,0x63,0x72,0x69,0x70,0x74,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x6f,0x76,0x65,0x72,0x6c,0x61,0x79,0x2e,
+ 0x6a,0x73,0x22,0x3e,0x3c,0x2f,0x73,0x63,0x72,0x69,0x70,0x74,0x3e,0x0a,0x20,0x20,
+ 0x3c,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x65,0x74,0x3e,0x0a,0x20,0x20,0x20,
+ 0x20,0x3c,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x69,0x64,0x3d,0x22,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x56,0x69,0x65,0x77,0x43,0x6f,0x6d,0x6d,
+ 0x61,0x6e,0x64,0x22,0x20,0x6f,0x6e,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x3d,0x22,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x76,0x69,0x65,0x77,0x28,
+ 0x29,0x3b,0x22,0x2f,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x63,0x6f,0x6d,0x6d,0x61,
+ 0x6e,0x64,0x20,0x69,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x53,0x74,0x6f,0x72,0x65,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x22,0x20,0x6f,
+ 0x6e,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x73,0x74,0x6f,0x72,0x65,0x28,0x29,0x3b,0x22,0x2f,0x3e,
+ 0x0a,0x20,0x20,0x3c,0x2f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x65,0x74,0x3e,
+ 0x0a,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x70,0x6f,0x70,0x75,0x70,0x20,0x69,0x64,
+ 0x3d,0x22,0x6d,0x65,0x6e,0x75,0x5f,0x54,0x6f,0x6f,0x6c,0x73,0x50,0x6f,0x70,0x75,
+ 0x70,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x20,0x6c,0x61,
+ 0x62,0x65,0x6c,0x3d,0x22,0x4a,0x53,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,
+ 0x20,0x69,0x6e,0x73,0x65,0x72,0x74,0x61,0x66,0x74,0x65,0x72,0x3d,0x22,0x6a,0x61,
+ 0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x43,0x6f,0x6e,0x73,0x6f,0x6c,0x65,0x2c,
+ 0x64,0x65,0x76,0x54,0x6f,0x6f,0x6c,0x73,0x53,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,
+ 0x72,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x70,
+ 0x6f,0x70,0x75,0x70,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6d,
+ 0x65,0x6e,0x75,0x69,0x74,0x65,0x6d,0x20,0x6c,0x61,0x62,0x65,0x6c,0x3d,0x22,0x56,
+ 0x69,0x65,0x77,0x20,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x20,0x63,0x6f,
+ 0x6d,0x6d,0x61,0x6e,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x56,0x69,0x65,0x77,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x22,0x2f,0x3e,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6d,0x65,0x6e,0x75,0x69,0x74,0x65,
+ 0x6d,0x20,0x6c,0x61,0x62,0x65,0x6c,0x3d,0x22,0x53,0x74,0x6f,0x72,0x65,0x20,0x43,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,
+ 0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x53,0x74,0x6f,0x72,
+ 0x65,0x43,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x22,0x2f,0x3e,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x3c,0x2f,0x6d,0x65,0x6e,0x75,0x70,0x6f,0x70,0x75,0x70,0x3e,0x0a,0x20,
+ 0x20,0x20,0x20,0x3c,0x2f,0x6d,0x65,0x6e,0x75,0x3e,0x0a,0x20,0x20,0x3c,0x2f,0x6d,
+ 0x65,0x6e,0x75,0x70,0x6f,0x70,0x75,0x70,0x3e,0x0a,0x3c,0x2f,0x6f,0x76,0x65,0x72,
+ 0x6c,0x61,0x79,0x3e,0x0a,
+};
+const unsigned char RESOURCE6_[] = {
+
+ 0x2f,0x2a,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2d,0x6f,0x76,0x65,0x72,0x6c,0x61,0x79,0x2e,0x6a,0x73,0x20,0x2d,0x20,0x73,
+ 0x63,0x72,0x69,0x70,0x74,0x20,0x66,0x6f,0x72,0x20,0x58,0x55,0x4c,0x20,0x6f,0x76,
+ 0x65,0x72,0x6c,0x61,0x79,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,
+ 0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,
+ 0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0a,0x0a,0x20,
+ 0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,
+ 0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,
+ 0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,
+ 0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,
+ 0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,
+ 0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,
+ 0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,
+ 0x20,0x61,0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,
+ 0x6e,0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,
+ 0x6e,0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,
+ 0x73,0x65,0x2c,0x20,0x6f,0x72,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,
+ 0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,
+ 0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0a,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,
+ 0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,
+ 0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,
+ 0x75,0x6c,0x2c,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,0x48,
+ 0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,
+ 0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,0x74,
+ 0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,0x61,
+ 0x6e,0x74,0x79,0x20,0x6f,0x66,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,0x48,
+ 0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,0x49,
+ 0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,0x54,
+ 0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,0x20,
+ 0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,0x55,
+ 0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,
+ 0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,0x65,
+ 0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0a,0x0a,0x20,0x20,0x20,0x20,0x59,
+ 0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,0x65,0x20,0x72,
+ 0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,0x79,0x20,0x6f,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,
+ 0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,
+ 0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68,0x20,
+ 0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x3b,0x20,0x69,0x66,
+ 0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x6f,0x20,0x74,
+ 0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,
+ 0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x49,0x6e,0x63,
+ 0x2e,0x2c,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,0x72,0x61,0x6e,0x6b,0x6c,
+ 0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,0x46,0x69,0x66,0x74,0x68,
+ 0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,0x74,0x6f,0x6e,0x2c,0x20,
+ 0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,0x30,0x31,0x20,0x55,0x53,
+ 0x41,0x2e,0x0a,0x2a,0x2f,0x0a,0x0a,0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,
+ 0x73,0x2e,0x75,0x74,0x69,0x6c,0x73,0x2e,0x69,0x6d,0x70,0x6f,0x72,0x74,0x28,0x27,
+ 0x72,0x65,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x2f,0x2f,0x67,0x72,0x65,0x2f,0x6d,
+ 0x6f,0x64,0x75,0x6c,0x65,0x73,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x6a,0x73,0x6d,0x27,0x29,0x3b,0x0a,0x0a,0x2f,0x2f,0x20,0x68,0x74,0x74,
+ 0x70,0x73,0x3a,0x2f,0x2f,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x2e,0x6d,
+ 0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x65,0x6e,0x2f,0x43,0x6f,
+ 0x64,0x65,0x5f,0x73,0x6e,0x69,0x70,0x70,0x65,0x74,0x73,0x2f,0x54,0x61,0x62,0x62,
+ 0x65,0x64,0x5f,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x41,0x6e,0x64,0x52,0x65,0x75,0x73,0x65,
+ 0x4f,0x6e,0x65,0x54,0x61,0x62,0x50,0x65,0x72,0x55,0x52,0x4c,0x28,0x75,0x72,0x6c,
+ 0x29,0x20,0x7b,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x77,0x6d,0x20,0x3d,0x20,0x43,
+ 0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x63,0x6c,0x61,0x73,0x73,0x65,
+ 0x73,0x5b,0x22,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,
+ 0x61,0x70,0x70,0x73,0x68,0x65,0x6c,0x6c,0x2f,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2d,
+ 0x6d,0x65,0x64,0x69,0x61,0x74,0x6f,0x72,0x3b,0x31,0x22,0x5d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x2e,0x67,0x65,0x74,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x28,0x43,0x6f,
+ 0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x69,0x6e,0x74,0x65,0x72,0x66,0x61,
+ 0x63,0x65,0x73,0x2e,0x6e,0x73,0x49,0x57,0x69,0x6e,0x64,0x6f,0x77,0x4d,0x65,0x64,
+ 0x69,0x61,0x74,0x6f,0x72,0x29,0x3b,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,0x6f,0x72,0x20,
+ 0x3d,0x20,0x77,0x6d,0x2e,0x67,0x65,0x74,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,
+ 0x6f,0x72,0x28,0x22,0x6e,0x61,0x76,0x69,0x67,0x61,0x74,0x6f,0x72,0x3a,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x22,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x43,
+ 0x68,0x65,0x63,0x6b,0x20,0x65,0x61,0x63,0x68,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,
+ 0x72,0x20,0x69,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x20,0x66,0x6f,0x72,0x20,0x6f,
+ 0x75,0x72,0x20,0x55,0x52,0x4c,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x6f,0x75,
+ 0x6e,0x64,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0a,0x20,0x20,0x77,0x68,
+ 0x69,0x6c,0x65,0x20,0x28,0x21,0x66,0x6f,0x75,0x6e,0x64,0x20,0x26,0x26,0x20,0x62,
+ 0x72,0x6f,0x77,0x73,0x65,0x72,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,0x6f,0x72,
+ 0x2e,0x68,0x61,0x73,0x4d,0x6f,0x72,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,
+ 0x28,0x29,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x57,0x69,0x6e,0x20,0x3d,0x20,0x62,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x45,0x6e,0x75,0x6d,0x65,0x72,0x61,0x74,0x6f,0x72,0x2e,0x67,0x65,0x74,
+ 0x4e,0x65,0x78,0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x74,0x61,0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x3d,0x20,0x62,0x72,0x6f,
+ 0x77,0x73,0x65,0x72,0x57,0x69,0x6e,0x2e,0x67,0x65,0x74,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x28,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x43,0x68,
+ 0x65,0x63,0x6b,0x20,0x65,0x61,0x63,0x68,0x20,0x74,0x61,0x62,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x69,0x73,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x69,0x6e,0x73,
+ 0x74,0x61,0x6e,0x63,0x65,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x75,
+ 0x6d,0x54,0x61,0x62,0x73,0x20,0x3d,0x20,0x74,0x61,0x62,0x62,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x2e,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x73,0x2e,0x6c,0x65,0x6e,0x67,
+ 0x74,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x28,0x76,0x61,0x72,0x20,
+ 0x69,0x6e,0x64,0x65,0x78,0x3d,0x30,0x3b,0x20,0x69,0x6e,0x64,0x65,0x78,0x3c,0x6e,
+ 0x75,0x6d,0x54,0x61,0x62,0x73,0x3b,0x20,0x69,0x6e,0x64,0x65,0x78,0x2b,0x2b,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x75,0x72,
+ 0x72,0x65,0x6e,0x74,0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x3d,0x20,0x74,0x61,
+ 0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2e,0x67,0x65,0x74,0x42,0x72,0x6f,0x77,
+ 0x73,0x65,0x72,0x41,0x74,0x49,0x6e,0x64,0x65,0x78,0x28,0x69,0x6e,0x64,0x65,0x78,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x75,0x72,0x6c,
+ 0x20,0x3d,0x3d,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x55,0x52,0x49,0x2e,0x73,0x70,
+ 0x65,0x63,0x29,0x20,0x7b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x54,0x68,0x65,0x20,0x55,0x52,0x4c,0x20,0x69,0x73,0x20,0x61,0x6c,0x72,
+ 0x65,0x61,0x64,0x79,0x20,0x6f,0x70,0x65,0x6e,0x65,0x64,0x2e,0x20,0x53,0x65,0x6c,
+ 0x65,0x63,0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x74,0x61,0x62,0x2e,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,
+ 0x2e,0x73,0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x54,0x61,0x62,0x20,0x3d,0x20,0x74,
+ 0x61,0x62,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2e,0x6d,0x54,0x61,0x62,0x73,0x5b,
+ 0x69,0x6e,0x64,0x65,0x78,0x5d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x2f,0x2f,0x20,0x46,0x6f,0x63,0x75,0x73,0x20,0x2a,0x74,0x68,0x69,0x73,0x2a,
+ 0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x2d,0x77,0x69,0x6e,0x64,0x6f,0x77,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x57,
+ 0x69,0x6e,0x2e,0x66,0x6f,0x63,0x75,0x73,0x28,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x3d,0x20,0x74,0x72,0x75,
+ 0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x72,0x65,0x61,0x6b,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x7d,0x0a,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x4f,0x75,0x72,0x20,0x55,0x52,
+ 0x4c,0x20,0x69,0x73,0x6e,0x27,0x74,0x20,0x6f,0x70,0x65,0x6e,0x2e,0x20,0x4f,0x70,
+ 0x65,0x6e,0x20,0x69,0x74,0x20,0x6e,0x6f,0x77,0x2e,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x66,0x6f,0x75,0x6e,0x64,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x72,0x65,0x63,0x65,0x6e,0x74,0x57,0x69,0x6e,0x64,0x6f,0x77,0x20,
+ 0x3d,0x20,0x77,0x6d,0x2e,0x67,0x65,0x74,0x4d,0x6f,0x73,0x74,0x52,0x65,0x63,0x65,
+ 0x6e,0x74,0x57,0x69,0x6e,0x64,0x6f,0x77,0x28,0x22,0x6e,0x61,0x76,0x69,0x67,0x61,
+ 0x74,0x6f,0x72,0x3a,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x22,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,0x65,0x63,0x65,0x6e,0x74,0x57,0x69,0x6e,
+ 0x64,0x6f,0x77,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,
+ 0x55,0x73,0x65,0x20,0x61,0x6e,0x20,0x65,0x78,0x69,0x73,0x74,0x69,0x6e,0x67,0x20,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x63,0x65,0x6e,0x74,0x57,0x69,0x6e,0x64,0x6f,
+ 0x77,0x2e,0x64,0x65,0x6c,0x61,0x79,0x65,0x64,0x4f,0x70,0x65,0x6e,0x54,0x61,0x62,
+ 0x28,0x75,0x72,0x6c,0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x2c,0x20,0x6e,0x75,0x6c,0x6c,
+ 0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x4e,0x6f,0x20,0x62,0x72,0x6f,0x77,
+ 0x73,0x65,0x72,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x61,0x72,0x65,0x20,
+ 0x6f,0x70,0x65,0x6e,0x2c,0x20,0x73,0x6f,0x20,0x6f,0x70,0x65,0x6e,0x20,0x61,0x20,
+ 0x6e,0x65,0x77,0x20,0x6f,0x6e,0x65,0x2e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x77,
+ 0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6f,0x70,0x65,0x6e,0x28,0x75,0x72,0x6c,0x29,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x7d,0x0a,0x7d,0x0a,0x0a,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x76,0x69,0x65,0x77,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x6f,0x70,0x65,
+ 0x6e,0x41,0x6e,0x64,0x52,0x65,0x75,0x73,0x65,0x4f,0x6e,0x65,0x54,0x61,0x62,0x50,
+ 0x65,0x72,0x55,0x52,0x4c,0x28,0x27,0x63,0x68,0x72,0x6f,0x6d,0x65,0x3a,0x2f,0x2f,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x63,0x6f,0x6e,0x74,0x65,
+ 0x6e,0x74,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,
+ 0x6d,0x6c,0x27,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x70,0x61,0x64,
+ 0x28,0x73,0x29,0x20,0x7b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,
+ 0x30,0x30,0x30,0x30,0x27,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x73,0x2e,0x6c,
+ 0x65,0x6e,0x67,0x74,0x68,0x29,0x20,0x2b,0x20,0x73,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x71,0x75,0x6f,0x74,0x65,0x28,0x73,0x29,0x20,0x7b,0x0a,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x22,0x27,0x20,0x2b,0x20,0x73,0x2e,0x72,
+ 0x65,0x70,0x6c,0x61,0x63,0x65,0x28,0x2f,0x5b,0x5c,0x75,0x30,0x30,0x30,0x30,0x2d,
+ 0x5c,0x75,0x30,0x30,0x31,0x66,0x22,0x5c,0x5c,0x5c,0x75,0x30,0x30,0x37,0x66,0x2d,
+ 0x5c,0x75,0x66,0x66,0x66,0x66,0x5d,0x2f,0x67,0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x28,0x63,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x73,0x77,
+ 0x69,0x74,0x63,0x68,0x20,0x28,0x63,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x63,
+ 0x61,0x73,0x65,0x20,0x27,0x5c,0x62,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x62,0x27,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x66,0x27,0x3a,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x66,0x27,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x6e,0x27,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,
+ 0x6e,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x72,
+ 0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x5c,0x5c,0x72,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x5c,0x74,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x27,0x5c,0x5c,0x74,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,
+ 0x73,0x65,0x20,0x27,0x5c,0x76,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x76,0x27,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x22,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x22,0x27,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x5c,0x27,0x3a,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x5c,0x5c,
+ 0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,
+ 0x75,0x27,0x20,0x2b,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x70,0x61,0x64,0x28,0x63,0x2e,0x63,0x68,0x61,0x72,0x43,0x6f,0x64,0x65,0x41,0x74,
+ 0x28,0x30,0x29,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x31,0x36,0x29,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x7d,0x29,0x20,0x2b,0x20,
+ 0x27,0x22,0x27,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,
+ 0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x74,0x6f,0x72,
+ 0x65,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x43,0x63,0x20,0x3d,0x20,0x43,0x6f,0x6d,
+ 0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x63,0x6c,0x61,0x73,0x73,0x65,0x73,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x73,0x74,0x20,0x43,0x69,0x20,0x3d,0x20,
+ 0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0x2e,0x69,0x6e,0x74,0x65,0x72,
+ 0x66,0x61,0x63,0x65,0x73,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x64,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x53,0x65,0x72,0x76,0x69,0x63,0x65,
+ 0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,
+ 0x6f,0x72,0x67,0x2f,0x66,0x69,0x6c,0x65,0x2f,0x64,0x69,0x72,0x65,0x63,0x74,0x6f,
+ 0x72,0x79,0x5f,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x3b,0x31,0x27,0x5d,0x2e,0x67,
+ 0x65,0x74,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,
+ 0x50,0x72,0x6f,0x70,0x65,0x72,0x74,0x69,0x65,0x73,0x29,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,
+ 0x74,0x6f,0x72,0x79,0x20,0x3d,0x20,0x64,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,
+ 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x2e,0x67,0x65,0x74,0x28,0x27,0x43,0x75,0x72,
+ 0x57,0x6f,0x72,0x6b,0x44,0x27,0x2c,0x20,0x43,0x69,0x2e,0x6e,0x73,0x49,0x4c,0x6f,
+ 0x63,0x61,0x6c,0x46,0x69,0x6c,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x2e,0x61,0x70,
+ 0x70,0x65,0x6e,0x64,0x52,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x50,0x61,0x74,0x68,
+ 0x28,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x72,0x65,0x70,
+ 0x6f,0x72,0x74,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x21,
+ 0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,
+ 0x2e,0x65,0x78,0x69,0x73,0x74,0x73,0x28,0x29,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,
+ 0x72,0x79,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,
+ 0x46,0x69,0x6c,0x65,0x2e,0x44,0x49,0x52,0x45,0x43,0x54,0x4f,0x52,0x59,0x5f,0x54,
+ 0x59,0x50,0x45,0x2c,0x20,0x30,0x37,0x35,0x35,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x6f,0x53,0x65,0x72,
+ 0x76,0x69,0x63,0x65,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,
+ 0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x6e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x2f,
+ 0x69,0x6f,0x2d,0x73,0x65,0x72,0x76,0x69,0x63,0x65,0x3b,0x31,0x27,0x5d,0x2e,0x67,
+ 0x65,0x74,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,
+ 0x49,0x4f,0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x20,0x3d,
+ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,
+ 0x6d,0x65,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x63,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x20,0x3d,0x20,0x69,0x6f,0x53,0x65,0x72,0x76,
+ 0x69,0x63,0x65,0x2e,0x6e,0x65,0x77,0x43,0x68,0x61,0x6e,0x6e,0x65,0x6c,0x28,0x27,
+ 0x63,0x68,0x72,0x6f,0x6d,0x65,0x3a,0x2f,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2f,0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2f,0x27,0x20,0x2b,0x20,
+ 0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x6e,0x75,0x6c,0x6c,0x2c,0x20,
+ 0x6e,0x75,0x6c,0x6c,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,
+ 0x61,0x6d,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,
+ 0x61,0x2e,0x6f,0x72,0x67,0x2f,0x62,0x69,0x6e,0x61,0x72,0x79,0x69,0x6e,0x70,0x75,
+ 0x74,0x73,0x74,0x72,0x65,0x61,0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,
+ 0x49,0x42,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,
+ 0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,
+ 0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x73,0x65,0x74,0x49,0x6e,
+ 0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x28,0x63,0x68,0x61,0x6e,0x6e,0x65,
+ 0x6c,0x2e,0x6f,0x70,0x65,0x6e,0x28,0x29,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x3d,0x20,0x43,
+ 0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,
+ 0x66,0x69,0x6c,0x65,0x2f,0x6c,0x6f,0x63,0x61,0x6c,0x3b,0x31,0x27,0x5d,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,
+ 0x2e,0x6e,0x73,0x49,0x4c,0x6f,0x63,0x61,0x6c,0x46,0x69,0x6c,0x65,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x2e,0x69,0x6e,0x69,
+ 0x74,0x57,0x69,0x74,0x68,0x46,0x69,0x6c,0x65,0x28,0x72,0x65,0x70,0x6f,0x72,0x74,
+ 0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x52,
+ 0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x50,0x61,0x74,0x68,0x28,0x66,0x69,0x6c,0x65,
+ 0x6e,0x61,0x6d,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,
+ 0x65,0x61,0x6d,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,
+ 0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x6e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x2f,0x66,
+ 0x69,0x6c,0x65,0x2d,0x6f,0x75,0x74,0x70,0x75,0x74,0x2d,0x73,0x74,0x72,0x65,0x61,
+ 0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x49,0x6e,0x73,0x74,
+ 0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,0x46,0x69,0x6c,0x65,0x4f,
+ 0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,
+ 0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x69,0x6e,0x69,0x74,0x28,0x66,0x69,0x6c,0x65,
+ 0x2c,0x20,0x30,0x78,0x30,0x32,0x20,0x7c,0x20,0x30,0x78,0x30,0x38,0x20,0x7c,0x20,
+ 0x30,0x78,0x32,0x30,0x2c,0x20,0x30,0x36,0x34,0x34,0x2c,0x20,0x30,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x69,0x6e,0x61,
+ 0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x20,0x3d,
+ 0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,
+ 0x67,0x2f,0x62,0x69,0x6e,0x61,0x72,0x79,0x6f,0x75,0x74,0x70,0x75,0x74,0x73,0x74,
+ 0x72,0x65,0x61,0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x49,
+ 0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,0x42,0x69,
+ 0x6e,0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,
+ 0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x73,0x65,
+ 0x74,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x28,0x66,0x69,
+ 0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x29,0x3b,
+ 0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,
+ 0x28,0x3b,0x3b,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x61,0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,
+ 0x20,0x3d,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,
+ 0x72,0x65,0x61,0x6d,0x2e,0x61,0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x28,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x61,0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x30,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x62,0x72,0x65,0x61,0x6b,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x62,0x79,0x74,0x65,0x73,0x20,0x3d,0x20,
+ 0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,
+ 0x6d,0x2e,0x72,0x65,0x61,0x64,0x42,0x79,0x74,0x65,0x73,0x28,0x61,0x76,0x61,0x69,
+ 0x6c,0x61,0x62,0x6c,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,
+ 0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x77,0x72,0x69,0x74,0x65,0x42,0x79,0x74,0x65,
+ 0x73,0x28,0x62,0x79,0x74,0x65,0x73,0x2c,0x20,0x62,0x79,0x74,0x65,0x73,0x2e,0x6c,
+ 0x65,0x6e,0x67,0x74,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6a,0x73,0x27,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x73,0x20,0x3d,0x20,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x20,0x3d,0x20,0x74,0x72,
+ 0x75,0x65,0x3b,0x5c,0x6e,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,
+ 0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x2c,0x20,
+ 0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6e,0x61,0x6c,0x6c,0x79,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x69,0x6e,
+ 0x61,0x72,0x79,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x2e,
+ 0x63,0x6c,0x6f,0x73,0x65,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x66,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x62,0x69,0x6e,0x61,0x72,0x79,0x49,0x6e,0x70,0x75,0x74,0x53,0x74,
+ 0x72,0x65,0x61,0x6d,0x2e,0x63,0x6c,0x6f,0x73,0x65,0x28,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,0x27,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,0x6d,0x6c,0x27,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,0x27,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6a,0x73,0x27,0x29,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,
+ 0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x63,0x73,0x73,0x27,
+ 0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,
+ 0x65,0x28,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,
+ 0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x27,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x70,0x79,0x43,0x68,0x72,0x6f,0x6d,0x65,0x28,0x27,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,
+ 0x68,0x74,0x2e,0x63,0x73,0x73,0x27,0x29,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x20,0x64,0x61,0x74,0x61,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x3d,0x20,0x43,0x63,0x5b,0x27,0x40,0x6d,0x6f,
+ 0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x66,0x69,0x6c,0x65,0x2f,0x6c,
+ 0x6f,0x63,0x61,0x6c,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x49,
+ 0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,0x73,0x49,0x4c,0x6f,
+ 0x63,0x61,0x6c,0x46,0x69,0x6c,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x69,
+ 0x6c,0x65,0x2e,0x69,0x6e,0x69,0x74,0x57,0x69,0x74,0x68,0x46,0x69,0x6c,0x65,0x28,
+ 0x72,0x65,0x70,0x6f,0x72,0x74,0x44,0x69,0x72,0x65,0x63,0x74,0x6f,0x72,0x79,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x2e,0x61,0x70,0x70,0x65,0x6e,
+ 0x64,0x52,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x50,0x61,0x74,0x68,0x28,0x27,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6a,0x73,0x6f,0x6e,0x27,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,
+ 0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,0x20,0x3d,0x20,0x43,0x63,0x5b,
+ 0x27,0x40,0x6d,0x6f,0x7a,0x69,0x6c,0x6c,0x61,0x2e,0x6f,0x72,0x67,0x2f,0x6e,0x65,
+ 0x74,0x77,0x6f,0x72,0x6b,0x2f,0x66,0x69,0x6c,0x65,0x2d,0x6f,0x75,0x74,0x70,0x75,
+ 0x74,0x2d,0x73,0x74,0x72,0x65,0x61,0x6d,0x3b,0x31,0x27,0x5d,0x2e,0x63,0x72,0x65,
+ 0x61,0x74,0x65,0x49,0x6e,0x73,0x74,0x61,0x6e,0x63,0x65,0x28,0x43,0x69,0x2e,0x6e,
+ 0x73,0x49,0x46,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,
+ 0x61,0x6d,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,
+ 0x74,0x72,0x65,0x61,0x6d,0x2e,0x69,0x6e,0x69,0x74,0x28,0x66,0x69,0x6c,0x65,0x2c,
+ 0x20,0x30,0x78,0x30,0x32,0x20,0x7c,0x20,0x30,0x78,0x30,0x38,0x20,0x7c,0x20,0x30,
+ 0x78,0x32,0x30,0x2c,0x20,0x30,0x36,0x34,0x34,0x2c,0x20,0x30,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x28,0x73,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,
+ 0x6d,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x2c,0x20,0x73,0x2e,0x6c,0x65,0x6e,
+ 0x67,0x74,0x68,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x7b,0x27,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x72,0x73,0x74,0x20,
+ 0x3d,0x20,0x74,0x72,0x75,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,0x5f,
+ 0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x69,0x72,0x73,0x74,
+ 0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,
+ 0x72,0x73,0x74,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,
+ 0x6c,0x73,0x65,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x2c,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x71,
+ 0x75,0x6f,0x74,0x65,0x28,0x66,0x69,0x6c,0x65,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x3a,0x7b,0x22,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x3a,0x5b,0x27,0x29,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,
+ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x30,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3c,
+ 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x2b,0x2b,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x6c,0x69,0x6e,0x65,0x20,0x3e,0x20,0x30,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,
+ 0x2c,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x76,
+ 0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,
+ 0x6c,0x69,0x6e,0x65,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x69,0x66,0x20,0x28,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x75,
+ 0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x7c,0x7c,0x20,0x76,0x61,0x6c,0x75,
+ 0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,
+ 0x3d,0x20,0x27,0x6e,0x75,0x6c,0x6c,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x77,0x72,0x69,0x74,0x65,0x28,0x76,0x61,0x6c,0x75,0x65,0x2e,0x74,0x6f,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x28,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,
+ 0x28,0x27,0x5d,0x2c,0x22,0x73,0x6f,0x75,0x72,0x63,0x65,0x22,0x3a,0x5b,0x27,0x29,
+ 0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x6f,
+ 0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x2e,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x66,0x6f,0x72,0x20,0x28,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x30,0x3b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x6c,0x69,
+ 0x6e,0x65,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,0x65,0x20,0x3e,0x20,0x30,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x28,0x27,0x2c,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x77,0x72,0x69,0x74,0x65,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x71,0x75,0x6f,0x74,0x65,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x5b,0x6c,0x69,
+ 0x6e,0x65,0x5d,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,
+ 0x5d,0x7d,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x77,0x72,0x69,0x74,0x65,0x28,0x27,0x7d,0x27,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x61,0x6c,0x65,0x72,0x74,0x28,0x27,0x43,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x20,0x64,0x61,0x74,0x61,0x20,0x73,0x74,0x6f,0x72,0x65,
+ 0x64,0x2e,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,
+ 0x66,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x66,0x69,0x6c,0x65,0x4f,0x75,0x74,0x70,0x75,0x74,0x53,0x74,0x72,0x65,0x61,0x6d,
+ 0x2e,0x63,0x6c,0x6f,0x73,0x65,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x7d,0x0a,0x20,0x20,0x63,0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x20,0x20,0x61,0x6c,0x65,0x72,0x74,0x28,0x65,0x29,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x64,0x75,0x6d,0x70,0x28,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x64,0x75,0x6d,0x70,0x28,0x27,0x5c,0x6e,0x27,0x29,0x3b,0x0a,0x20,0x20,0x7d,
+ 0x0a,0x7d,0x0a,
+};
+const unsigned char RESOURCE7_[] = {
+
+ 0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x68,0x74,0x6d,0x6c,0x3e,0x0d,
+ 0x0a,0x3c,0x21,0x2d,0x2d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,0x6d,0x6c,0x20,0x2d,0x20,0x63,0x6f,0x64,
+ 0x65,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20,0x4a,
+ 0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,
+ 0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,
+ 0x37,0x2c,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,
+ 0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,
+ 0x66,0x72,0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,
+ 0x6f,0x75,0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,
+ 0x75,0x74,0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,
+ 0x64,0x69,0x66,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,
+ 0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,
+ 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,
+ 0x73,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,
+ 0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,
+ 0x3b,0x20,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,
+ 0x20,0x32,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,
+ 0x65,0x2c,0x20,0x6f,0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,
+ 0x6f,0x75,0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,
+ 0x6c,0x61,0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,
+ 0x64,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,
+ 0x61,0x74,0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,
+ 0x65,0x66,0x75,0x6c,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,
+ 0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,
+ 0x4e,0x54,0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,
+ 0x6e,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,
+ 0x72,0x72,0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,
+ 0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,
+ 0x72,0x20,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,
+ 0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,
+ 0x53,0x45,0x2e,0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,
+ 0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,
+ 0x20,0x6d,0x6f,0x72,0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,
+ 0x20,0x68,0x61,0x76,0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,
+ 0x20,0x63,0x6f,0x70,0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,
+ 0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,
+ 0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,
+ 0x67,0x72,0x61,0x6d,0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,
+ 0x69,0x74,0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,
+ 0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,
+ 0x69,0x6f,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x35,0x31,0x20,0x46,0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,
+ 0x65,0x74,0x2c,0x20,0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,
+ 0x20,0x42,0x6f,0x73,0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,
+ 0x30,0x2d,0x31,0x33,0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2d,0x2d,0x3e,
+ 0x0d,0x0a,0x0d,0x0a,0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,
+ 0x64,0x3e,0x0d,0x0a,0x3c,0x74,0x69,0x74,0x6c,0x65,0x3e,0x4a,0x53,0x43,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x0d,0x0a,0x3c,
+ 0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65,0x73,
+ 0x68,0x65,0x65,0x74,0x22,0x20,0x74,0x79,0x70,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,
+ 0x2f,0x63,0x73,0x73,0x22,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,
+ 0x2e,0x63,0x73,0x73,0x22,0x3e,0x0d,0x0a,0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,
+ 0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65,0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x74,
+ 0x79,0x70,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x63,0x73,0x73,0x22,0x20,0x68,
+ 0x72,0x65,0x66,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,
+ 0x63,0x73,0x73,0x22,0x3e,0x0d,0x0a,0x3c,0x21,0x2d,0x2d,0x5b,0x69,0x66,0x20,0x49,
+ 0x45,0x5d,0x3e,0x0d,0x0a,0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,
+ 0x73,0x74,0x79,0x6c,0x65,0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x74,0x79,0x70,0x65,
+ 0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x63,0x73,0x73,0x22,0x20,0x68,0x72,0x65,0x66,
+ 0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x69,0x65,0x2e,
+ 0x63,0x73,0x73,0x22,0x3e,0x0d,0x0a,0x3c,0x21,0x5b,0x65,0x6e,0x64,0x69,0x66,0x5d,
+ 0x2d,0x2d,0x3e,0x0d,0x0a,0x3c,0x73,0x63,0x72,0x69,0x70,0x74,0x20,0x74,0x79,0x70,
+ 0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x2f,0x6a,0x61,0x76,0x61,0x73,0x63,0x72,0x69,
+ 0x70,0x74,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2e,0x6a,0x73,0x22,0x3e,0x3c,0x2f,0x73,0x63,0x72,0x69,0x70,0x74,
+ 0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x0d,0x0a,0x3c,0x62,
+ 0x6f,0x64,0x79,0x20,0x6f,0x6e,0x6c,0x6f,0x61,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x6f,0x64,0x79,0x5f,0x6c,0x6f,0x61,0x64,
+ 0x28,0x29,0x3b,0x22,0x20,0x6f,0x6e,0x72,0x65,0x73,0x69,0x7a,0x65,0x3d,0x22,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x6f,0x64,0x79,0x5f,0x72,
+ 0x65,0x73,0x69,0x7a,0x65,0x28,0x29,0x3b,0x22,0x3e,0x0d,0x0a,0x3c,0x64,0x69,0x76,
+ 0x20,0x69,0x64,0x3d,0x22,0x6d,0x61,0x69,0x6e,0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,
+ 0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x68,0x65,0x61,0x64,0x69,0x6e,0x67,
+ 0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,0x3c,0x68,0x31,0x3e,0x4a,0x53,0x43,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x3c,0x64,0x69,0x76,
+ 0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x42,0x61,0x72,0x22,0x20,0x69,0x64,0x3d,0x22,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,
+ 0x73,0x42,0x61,0x72,0x22,0x3e,0x3c,0x73,0x70,0x61,0x6e,0x20,0x63,0x6c,0x61,0x73,
+ 0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x50,0x65,0x72,0x63,0x65,
+ 0x6e,0x74,0x61,0x67,0x65,0x22,0x3e,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x3c,0x64,
+ 0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x47,0x72,0x61,0x70,0x68,0x22,0x3e,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,
+ 0x61,0x73,0x73,0x3d,0x22,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x43,0x6f,0x76,
+ 0x65,0x72,0x65,0x64,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,0x73,0x70,0x61,0x6e,0x20,
+ 0x69,0x64,0x3d,0x22,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,
+ 0x6c,0x22,0x3e,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x0d,0x0a,0x0d,0x0a,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x74,
+ 0x61,0x62,0x73,0x22,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x54,0x61,0x62,0x73,
+ 0x22,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x62,
+ 0x72,0x6f,0x77,0x73,0x65,0x72,0x54,0x61,0x62,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,
+ 0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,
+ 0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,
+ 0x74,0x3d,0x22,0x22,0x3e,0x20,0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x3c,0x69,
+ 0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,
+ 0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,
+ 0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x54,0x61,0x62,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x22,
+ 0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,
+ 0x6c,0x74,0x3d,0x22,0x22,0x3e,0x20,0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x20,0x3c,
+ 0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,
+ 0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x22,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x64,0x69,
+ 0x73,0x61,0x62,0x6c,0x65,0x64,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,
+ 0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,
+ 0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,
+ 0x22,0x3e,0x20,0x53,0x6f,0x75,0x72,0x63,0x65,0x20,0x3c,0x69,0x6d,0x67,0x20,0x73,
+ 0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,
+ 0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,
+ 0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,
+ 0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,0x54,0x61,0x62,0x22,
+ 0x3e,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,0x54,
+ 0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,
+ 0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x20,0x53,
+ 0x74,0x6f,0x72,0x65,0x20,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,
+ 0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,
+ 0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,
+ 0x3d,0x22,0x61,0x62,0x6f,0x75,0x74,0x54,0x61,0x62,0x22,0x3e,0x3c,0x69,0x6d,0x67,
+ 0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,0x61,
+ 0x6c,0x74,0x3d,0x22,0x22,0x3e,0x20,0x41,0x62,0x6f,0x75,0x74,0x20,0x3c,0x69,0x6d,
+ 0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,0x66,0x22,0x20,
+ 0x61,0x6c,0x74,0x3d,0x22,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,
+ 0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,
+ 0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x22,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,
+ 0x22,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x3c,
+ 0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x54,0x61,0x62,0x50,0x61,
+ 0x67,0x65,0x22,0x20,0x69,0x64,0x3d,0x22,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x54,
+ 0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,
+ 0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x44,
+ 0x69,0x76,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x55,0x52,0x4c,0x3a,0x20,0x3c,
+ 0x69,0x6e,0x70,0x75,0x74,0x20,0x69,0x64,0x3d,0x22,0x6c,0x6f,0x63,0x61,0x74,0x69,
+ 0x6f,0x6e,0x22,0x20,0x74,0x79,0x70,0x65,0x3d,0x22,0x74,0x65,0x78,0x74,0x22,0x20,
+ 0x73,0x69,0x7a,0x65,0x3d,0x22,0x37,0x30,0x22,0x20,0x6f,0x6e,0x6b,0x65,0x79,0x70,
+ 0x72,0x65,0x73,0x73,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6b,0x65,0x79,0x70,0x72,0x65,0x73,0x73,0x28,
+ 0x65,0x76,0x65,0x6e,0x74,0x29,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x62,
+ 0x75,0x74,0x74,0x6f,0x6e,0x20,0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x3d,0x22,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x75,0x74,0x74,0x6f,0x6e,
+ 0x5f,0x63,0x6c,0x69,0x63,0x6b,0x28,0x29,0x3b,0x22,0x3e,0x47,0x6f,0x3c,0x2f,0x62,
+ 0x75,0x74,0x74,0x6f,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,
+ 0x22,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x69,0x66,0x72,0x61,0x6d,0x65,0x20,0x69,0x64,0x3d,0x22,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x49,0x66,0x72,0x61,0x6d,0x65,0x22,0x20,0x6f,0x6e,0x6c,
+ 0x6f,0x61,0x64,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x5f,0x6c,0x6f,0x61,0x64,0x28,0x29,0x3b,0x22,
+ 0x3e,0x3c,0x2f,0x69,0x66,0x72,0x61,0x6d,0x65,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,
+ 0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x69,0x6e,0x70,0x75,0x74,0x20,0x74,0x79,0x70,0x65,0x3d,0x22,0x63,0x68,0x65,0x63,
+ 0x6b,0x62,0x6f,0x78,0x22,0x20,0x69,0x64,0x3d,0x22,0x63,0x68,0x65,0x63,0x6b,0x62,
+ 0x6f,0x78,0x22,0x20,0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x3d,0x22,0x72,0x65,0x74,
+ 0x75,0x72,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,
+ 0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x28,0x29,0x3b,
+ 0x22,0x3e,0x20,0x3c,0x6c,0x61,0x62,0x65,0x6c,0x20,0x66,0x6f,0x72,0x3d,0x22,0x63,
+ 0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x22,0x3e,0x53,0x68,0x6f,0x77,0x20,0x6d,0x69,
+ 0x73,0x73,0x69,0x6e,0x67,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,
+ 0x20,0x63,0x6f,0x6c,0x75,0x6d,0x6e,0x3c,0x2f,0x6c,0x61,0x62,0x65,0x6c,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,
+ 0x45,0x72,0x72,0x6f,0x72,0x44,0x69,0x76,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x69,0x64,0x3d,
+ 0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x22,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x74,0x72,0x20,0x69,0x64,0x3d,0x22,0x68,0x65,0x61,0x64,0x65,0x72,
+ 0x52,0x6f,0x77,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x68,0x20,0x63,
+ 0x6c,0x61,0x73,0x73,0x3d,0x22,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x22,0x3e,0x46,0x69,0x6c,0x65,0x3c,0x2f,0x74,0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x3c,0x74,0x68,0x3e,0x3c,0x61,0x62,0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,
+ 0x3d,0x22,0x54,0x68,0x65,0x20,0x74,0x6f,0x74,0x61,0x6c,0x20,0x6e,0x75,0x6d,0x62,
+ 0x65,0x72,0x20,0x6f,0x66,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x61,0x62,0x6c,0x65,
+ 0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x22,0x3e,0x53,0x74,0x61,
+ 0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x3c,0x2f,0x61,0x62,0x62,0x72,0x3e,0x3c,0x2f,
+ 0x74,0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x68,0x3e,0x3c,0x61,0x62,
+ 0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,0x3d,0x22,0x54,0x68,0x65,0x20,0x6e,0x75,
+ 0x6d,0x62,0x65,0x72,0x20,0x6f,0x66,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,
+ 0x74,0x73,0x20,0x61,0x63,0x74,0x75,0x61,0x6c,0x6c,0x79,0x20,0x65,0x78,0x65,0x63,
+ 0x75,0x74,0x65,0x64,0x22,0x3e,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x3c,0x2f,
+ 0x61,0x62,0x62,0x72,0x3e,0x3c,0x2f,0x74,0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x74,0x68,0x3e,0x3c,0x61,0x62,0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,0x3d,
+ 0x22,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x6f,0x66,0x20,0x65,0x78,0x65,0x63,0x75,
+ 0x74,0x65,0x64,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x61,
+ 0x73,0x20,0x61,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x6f,
+ 0x66,0x20,0x74,0x6f,0x74,0x61,0x6c,0x20,0x6e,0x75,0x6d,0x62,0x65,0x72,0x20,0x6f,
+ 0x66,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x22,0x3e,0x43,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x3c,0x2f,0x61,0x62,0x62,0x72,0x3e,0x3c,0x2f,0x74,
+ 0x68,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x72,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x3c,0x74,0x72,0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x6c,
+ 0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x73,0x70,0x61,0x6e,0x20,0x63,
+ 0x6c,0x61,0x73,0x73,0x3d,0x22,0x74,0x69,0x74,0x6c,0x65,0x22,0x3e,0x54,0x6f,0x74,
+ 0x61,0x6c,0x3a,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x73,0x70,0x61,0x6e,0x3e,0x30,0x3c,
+ 0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x6e,0x75,0x6d,0x65,0x72,0x69,
+ 0x63,0x22,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x6e,0x75,
+ 0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,
+ 0x3d,0x22,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,
+ 0x6c,0x61,0x73,0x73,0x3d,0x22,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x22,0x3e,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x63,0x6f,
+ 0x76,0x65,0x72,0x65,0x64,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,
+ 0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,
+ 0x73,0x70,0x61,0x6e,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x70,0x63,0x74,0x22,
+ 0x3e,0x30,0x25,0x3c,0x2f,0x73,0x70,0x61,0x6e,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x2f,0x74,0x72,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x68,
+ 0x65,0x61,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x62,0x6f,0x64,0x79,
+ 0x20,0x69,0x64,0x3d,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,
+ 0x79,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x21,0x2d,0x2d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x74,0x72,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x74,0x64,0x3e,0x30,0x25,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x74,0x64,0x3e,0x30,0x3c,0x2f,0x74,0x64,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x3c,0x2f,0x74,0x72,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2d,0x2d,0x3e,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,
+ 0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,
+ 0x3d,0x22,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x66,0x69,0x6c,0x65,0x44,0x69,
+ 0x76,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,
+ 0x76,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,
+ 0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,
+ 0x73,0x3d,0x22,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x20,0x69,0x64,0x3d,0x22,
+ 0x73,0x74,0x6f,0x72,0x65,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x3c,0x62,0x75,0x74,0x74,0x6f,0x6e,0x20,0x69,0x64,0x3d,0x22,
+ 0x73,0x74,0x6f,0x72,0x65,0x42,0x75,0x74,0x74,0x6f,0x6e,0x22,0x20,0x6f,0x6e,0x63,
+ 0x6c,0x69,0x63,0x6b,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x73,0x74,0x6f,0x72,0x65,0x42,0x75,0x74,0x74,0x6f,0x6e,0x5f,0x63,0x6c,0x69,
+ 0x63,0x6b,0x28,0x29,0x3b,0x22,0x3e,0x53,0x74,0x6f,0x72,0x65,0x20,0x52,0x65,0x70,
+ 0x6f,0x72,0x74,0x3c,0x2f,0x62,0x75,0x74,0x74,0x6f,0x6e,0x3e,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,
+ 0x49,0x6d,0x67,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x2d,0x74,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x67,0x69,
+ 0x66,0x22,0x20,0x61,0x6c,0x74,0x3d,0x22,0x6c,0x6f,0x61,0x64,0x69,0x6e,0x67,0x2e,
+ 0x2e,0x2e,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,
+ 0x64,0x3d,0x22,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x22,0x3e,0x3c,0x2f,0x64,
+ 0x69,0x76,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x20,
+ 0x20,0x3c,0x64,0x69,0x76,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x54,0x61,0x62,
+ 0x50,0x61,0x67,0x65,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x70,0x3e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x69,0x73,0x20,0x76,0x65,0x72,
+ 0x73,0x69,0x6f,0x6e,0x20,0x30,0x2e,0x34,0x20,0x6f,0x66,0x20,0x4a,0x53,0x43,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x2c,0x20,0x61,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,
+ 0x6d,0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,
+ 0x73,0x20,0x63,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x20,0x73,0x74,0x61,0x74,0x69,0x73,0x74,0x69,0x63,0x73,0x20,
+ 0x66,0x6f,0x72,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x2e,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,
+ 0x70,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x53,0x65,0x65,0x20,0x3c,0x61,0x20,0x68,
+ 0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x69,0x6c,0x69,
+ 0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x2f,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,
+ 0x2f,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,
+ 0x6d,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2f,0x3c,0x2f,0x61,
+ 0x3e,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,
+ 0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x70,
+ 0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x26,0x63,0x6f,0x70,0x79,0x3b,
+ 0x20,0x32,0x30,0x30,0x37,0x2c,0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,
+ 0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x20,0x20,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0d,0x0a,0x3c,0x2f,0x64,0x69,0x76,0x3e,
+ 0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74,0x6d,
+ 0x6c,0x3e,0x0d,0x0a,
+};
+const unsigned char RESOURCE8_[] = {
+
+ 0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x63,0x73,0x73,0x20,0x2d,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20,0x4a,0x61,0x76,0x61,0x53,
+ 0x63,0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,
+ 0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x37,0x2c,0x20,0x32,
+ 0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,
+ 0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,
+ 0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,
+ 0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,
+ 0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,
+ 0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,
+ 0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,
+ 0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,0x70,0x75,
+ 0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,
+ 0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,0x65,0x69,
+ 0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,0x20,0x6f,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,0x20,0x6f,
+ 0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,0x72,0x20,
+ 0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,0x74,0x65,
+ 0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,
+ 0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x69,0x6e,
+ 0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x69,
+ 0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,0x75,0x6c,
+ 0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,0x48,0x4f,
+ 0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x3b,
+ 0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,0x74,0x68,
+ 0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,0x61,0x6e,
+ 0x74,0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,0x48,
+ 0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,0x49,
+ 0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,0x54,
+ 0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,0x20,
+ 0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,
+ 0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,
+ 0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,
+ 0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,
+ 0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,
+ 0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,
+ 0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,
+ 0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,
+ 0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,
+ 0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,
+ 0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,
+ 0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,
+ 0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,
+ 0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,
+ 0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,
+ 0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x62,
+ 0x6f,0x64,0x79,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,
+ 0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x62,0x66,0x66,0x66,
+ 0x62,0x66,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x66,0x61,0x6d,0x69,
+ 0x6c,0x79,0x3a,0x20,0x73,0x61,0x6e,0x73,0x2d,0x73,0x65,0x72,0x69,0x66,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x20,0x31,0x30,
+ 0x30,0x25,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,0x20,0x30,
+ 0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x6d,0x61,0x69,0x6e,0x44,0x69,0x76,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,
+ 0x20,0x30,0x2e,0x38,0x31,0x32,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x23,0x68,0x65,0x61,0x64,0x69,0x6e,0x67,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,0x6f,
+ 0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x30,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,
+ 0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,
+ 0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x65,0x2d,0x68,0x65,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x31,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x68,0x31,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,
+ 0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,
+ 0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,
+ 0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x20,0x31,0x2e,0x33,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x42,0x61,0x72,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
+ 0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x69,0x73,0x69,0x62,
+ 0x69,0x6c,0x69,0x74,0x79,0x3a,0x20,0x68,0x69,0x64,0x64,0x65,0x6e,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x50,0x65,
+ 0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x64,0x69,
+ 0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,0x62,0x6c,0x6f,0x63,0x6b,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x74,0x65,0x78,0x74,0x2d,0x61,0x6c,0x69,0x67,0x6e,0x3a,0x20,0x72,0x69,0x67,0x68,
+ 0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x47,0x72,0x61,0x70,0x68,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,
+ 0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,
+ 0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,
+ 0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x62,
+ 0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,
+ 0x20,0x62,0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,
+ 0x6e,0x2d,0x74,0x6f,0x70,0x3a,0x20,0x30,0x2e,0x33,0x65,0x6d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,
+ 0x72,0x3a,0x20,0x23,0x64,0x34,0x64,0x30,0x63,0x38,0x3b,0x0d,0x0a,0x20,0x20,0x6f,
+ 0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x68,0x69,0x64,0x64,0x65,0x6e,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x43,0x6f,0x76,0x65,0x72,0x65,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,
+ 0x77,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x20,0x63,
+ 0x6f,0x6c,0x6f,0x72,0x20,0x41,0x63,0x74,0x69,0x76,0x65,0x43,0x61,0x70,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6f,0x72,0x20,0x48,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x20,
+ 0x2a,0x2f,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,
+ 0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x30,0x61,0x32,0x34,0x36,0x61,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x68,0x69,0x64,0x64,
+ 0x65,0x6e,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x70,0x72,0x6f,0x67,0x72,
+ 0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x64,0x69,
+ 0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,0x62,0x6c,0x6f,0x63,0x6b,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x30,
+ 0x2e,0x33,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x62,0x72,
+ 0x6f,0x77,0x73,0x65,0x72,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,
+ 0x0a,0x69,0x6e,0x70,0x75,0x74,0x23,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2c,
+ 0x20,0x62,0x75,0x74,0x74,0x6f,0x6e,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x62,
+ 0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,
+ 0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,
+ 0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,
+ 0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,
+ 0x20,0x61,0x62,0x73,0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,
+ 0x70,0x3a,0x20,0x33,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,
+ 0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,
+ 0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x69,0x66,0x72,
+ 0x61,0x6d,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,
+ 0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,
+ 0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x73,
+ 0x75,0x6d,0x6d,0x61,0x72,0x79,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,
+ 0x0d,0x0a,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,
+ 0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x33,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x65,0x6d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x65,0x6d,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x61,0x75,
+ 0x74,0x6f,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,
+ 0x67,0x68,0x74,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x2d,0x63,0x6f,0x6c,0x6c,0x61,0x70,0x73,0x65,0x3a,0x20,0x63,0x6f,
+ 0x6c,0x6c,0x61,0x70,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,
+ 0x73,0x69,0x7a,0x65,0x3a,0x20,0x73,0x6d,0x61,0x6c,0x6c,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,
+ 0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,0x2c,0x20,0x74,0x61,0x62,0x6c,0x65,0x23,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x64,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,0x6c,0x65,0x66,0x74,
+ 0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x23,0x64,0x39,0x64,
+ 0x39,0x64,0x39,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,
+ 0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,
+ 0x2e,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x2c,0x20,0x74,0x61,0x62,
+ 0x6c,0x65,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,
+ 0x74,0x64,0x2e,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,0x6c,0x65,0x66,0x74,0x2d,0x77,
+ 0x69,0x64,0x74,0x68,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,
+ 0x62,0x6c,0x65,0x20,0x74,0x68,0x2c,0x20,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x6c,0x65,0x20,0x74,0x64,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x3a,0x20,0x32,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x68,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,
+ 0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,
+ 0x20,0x23,0x65,0x36,0x66,0x66,0x65,0x36,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x74,0x64,0x2e,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x74,0x65,0x78,0x74,0x2d,0x61,0x6c,0x69,0x67,0x6e,0x3a,0x20,0x72,0x69,0x67,0x68,
+ 0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x61,0x62,0x62,0x72,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,0x68,0x65,0x6c,0x70,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x72,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x74,0x64,0x2e,0x6c,0x65,0x66,0x74,0x43,
+ 0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x73,0x70,0x61,0x6e,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x72,0x69,0x67,0x68,0x74,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x74,0x72,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,
+ 0x74,0x61,0x6c,0x73,0x20,0x74,0x64,0x2e,0x6c,0x65,0x66,0x74,0x43,0x6f,0x6c,0x75,
+ 0x6d,0x6e,0x20,0x73,0x70,0x61,0x6e,0x2e,0x74,0x69,0x74,0x6c,0x65,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x77,0x65,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x62,0x6f,0x6c,0x64,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x72,
+ 0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x74,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,
+ 0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x66,0x66,0x64,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x64,0x2e,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,
+ 0x35,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x64,0x2e,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x20,0x73,0x70,0x61,0x6e,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x72,0x69,0x67,0x68,0x74,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,
+ 0x74,0x3a,0x20,0x35,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x2e,0x70,0x63,0x74,
+ 0x47,0x72,0x61,0x70,0x68,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x64,
+ 0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3a,0x20,0x72,0x69,0x67,0x68,0x74,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,
+ 0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x23,0x30,0x30,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,
+ 0x6c,0x6f,0x72,0x3a,0x20,0x23,0x65,0x30,0x30,0x30,0x30,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x68,0x69,0x64,
+ 0x64,0x65,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,
+ 0x2d,0x74,0x6f,0x70,0x3a,0x20,0x34,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x2e,
+ 0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x2e,0x63,0x6f,0x76,0x65,0x72,0x65,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,
+ 0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x30,0x30,0x66,0x30,
+ 0x30,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,
+ 0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x2e,0x70,0x63,0x74,0x47,0x72,
+ 0x61,0x70,0x68,0x20,0x2e,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,
+ 0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x64,0x34,0x64,0x30,0x63,0x38,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x70,0x78,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,
+ 0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x74,0x62,0x6f,0x64,0x79,0x23,0x73,
+ 0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,0x79,0x20,0x74,0x72,0x2e,0x65,
+ 0x76,0x65,0x6e,0x20,0x74,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x61,
+ 0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,
+ 0x23,0x65,0x36,0x66,0x66,0x65,0x36,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,
+ 0x0a,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,
+ 0x0a,0x0d,0x0a,0x23,0x66,0x69,0x6c,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x3a,0x20,0x6c,0x61,0x72,0x67,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x77,0x65,0x69,0x67,0x68,
+ 0x74,0x3a,0x20,0x62,0x6f,0x6c,0x64,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,0x6f,0x6c,0x75,0x74,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x33,0x65,0x6d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x2d,0x63,0x6f,0x6c,0x6c,0x61,0x70,0x73,0x65,0x3a,0x20,0x63,0x6f,
+ 0x6c,0x6c,0x61,0x70,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,
+ 0x73,0x69,0x7a,0x65,0x3a,0x20,0x73,0x6d,0x61,0x6c,0x6c,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x2f,0x2a,0x0d,0x0a,0x49,0x45,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,
+ 0x74,0x20,0x62,0x65,0x68,0x61,0x76,0x69,0x6f,0x72,0x20,0x69,0x73,0x20,0x74,0x6f,
+ 0x20,0x6d,0x61,0x6b,0x65,0x20,0x3c,0x70,0x72,0x65,0x3e,0x20,0x73,0x6d,0x61,0x6c,
+ 0x6c,0x65,0x72,0x20,0x74,0x68,0x61,0x6e,0x20,0x73,0x75,0x72,0x72,0x6f,0x75,0x6e,
+ 0x64,0x69,0x6e,0x67,0x20,0x74,0x65,0x78,0x74,0x2e,0x20,0x20,0x42,0x65,0x63,0x61,
+ 0x75,0x73,0x65,0x0d,0x0a,0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x61,
+ 0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x68,0x61,0x73,0x20,0x66,0x6f,0x6e,0x74,0x2d,
+ 0x73,0x69,0x7a,0x65,0x20,0x73,0x6d,0x61,0x6c,0x6c,0x2c,0x20,0x74,0x68,0x69,0x73,
+ 0x20,0x77,0x6f,0x75,0x6c,0x64,0x20,0x6d,0x61,0x6b,0x65,0x20,0x74,0x68,0x65,0x20,
+ 0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,0x20,0x77,0x69,0x74,0x68,0x69,0x6e,
+ 0x20,0x74,0x68,0x65,0x0d,0x0a,0x3c,0x70,0x72,0x65,0x3e,0x20,0x78,0x2d,0x73,0x6d,
+ 0x61,0x6c,0x6c,0x2e,0x20,0x20,0x53,0x6f,0x20,0x77,0x65,0x20,0x64,0x6f,0x6e,0x27,
+ 0x74,0x20,0x72,0x65,0x6c,0x79,0x20,0x6f,0x6e,0x20,0x74,0x68,0x65,0x20,0x64,0x65,
+ 0x66,0x61,0x75,0x6c,0x74,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x74,0x61,0x62,0x6c,
+ 0x65,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x70,0x72,
+ 0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x69,0x7a,0x65,
+ 0x3a,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x74,0x61,0x62,0x6c,0x65,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,
+ 0x65,0x20,0x74,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,
+ 0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,
+ 0x67,0x2d,0x74,0x6f,0x70,0x3a,0x20,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x6c,
+ 0x65,0x66,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,
+ 0x64,0x64,0x69,0x6e,0x67,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,
+ 0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x74,0x61,0x62,0x6c,0x65,0x23,0x73,
+ 0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x70,0x72,0x65,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x30,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x3a,0x20,0x30,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x67,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,
+ 0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,
+ 0x20,0x23,0x62,0x66,0x66,0x66,0x62,0x66,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x2e,0x79,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,
+ 0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x66,0x66,0x66,0x66,0x62,
+ 0x66,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x72,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,
+ 0x72,0x3a,0x20,0x23,0x66,0x66,0x62,0x66,0x62,0x66,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x0d,0x0a,0x73,0x74,0x6f,0x72,0x65,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,
+ 0x2f,0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,
+ 0x73,0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,
+ 0x33,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x65,0x6d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x65,0x6d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x6f,0x76,0x65,0x72,0x66,0x6c,0x6f,0x77,0x3a,0x20,0x61,
+ 0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x61,0x62,0x6f,
+ 0x75,0x74,0x20,0x74,0x61,0x62,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x70,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x74,0x6f,0x70,0x3a,
+ 0x20,0x30,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,
+ 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x0d,0x0a,0x74,0x61,0x62,0x73,
+ 0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,
+ 0x6f,0x6c,0x75,0x74,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x33,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x2e,0x35,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x32,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,
+ 0x20,0x64,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,
+ 0x6f,0x75,0x6e,0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x77,0x68,0x69,0x74,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,
+ 0x72,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6c,0x6f,
+ 0x61,0x74,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,
+ 0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x62,
+ 0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,
+ 0x62,0x6f,0x74,0x74,0x6f,0x6d,0x2d,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x30,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,0x70,0x6f,0x69,0x6e,
+ 0x74,0x65,0x72,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x6c,
+ 0x65,0x66,0x74,0x3a,0x20,0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x6d,
+ 0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x30,0x2e,0x35,
+ 0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x6c,
+ 0x65,0x66,0x74,0x3a,0x20,0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x30,0x2e,
+ 0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x32,0x65,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,0x3a,
+ 0x20,0x31,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x65,0x2d,0x68,0x65,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x31,0x2e,0x38,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x23,0x74,0x61,0x62,0x73,0x20,0x64,0x69,0x76,0x2e,0x73,0x65,0x6c,0x65,0x63,
+ 0x74,0x65,0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,
+ 0x3a,0x20,0x33,0x3b,0x0d,0x0a,0x20,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,
+ 0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x74,0x61,0x62,0x73,0x20,0x64,0x69,0x76,0x2e,0x64,0x69,0x73,0x61,0x62,0x6c,0x65,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,
+ 0x73,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x47,
+ 0x72,0x61,0x79,0x54,0x65,0x78,0x74,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,0x63,0x6f,
+ 0x6c,0x6f,0x72,0x3a,0x20,0x23,0x38,0x30,0x38,0x30,0x38,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x3a,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,
+ 0x3b,0x20,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x54,0x61,0x62,0x50,0x61,0x67,
+ 0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x62,0x61,0x63,0x6b,0x67,0x72,0x6f,0x75,0x6e,
+ 0x64,0x2d,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x77,0x68,0x69,0x74,0x65,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,
+ 0x6f,0x6c,0x69,0x64,0x20,0x62,0x6c,0x61,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,0x70,
+ 0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x61,0x62,0x73,0x6f,0x6c,0x75,0x74,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,0x20,0x35,0x65,0x6d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x2e,0x35,0x65,0x6d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x2e,0x35,0x65,0x6d,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x2e,0x35,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,0x3a,0x20,0x32,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x3a,0x20,0x31,0x65,
+ 0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,0x6e,
+ 0x6f,0x6e,0x65,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x50,
+ 0x61,0x67,0x65,0x73,0x20,0x64,0x69,0x76,0x2e,0x73,0x65,0x6c,0x65,0x63,0x74,0x65,
+ 0x64,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x3a,0x20,
+ 0x62,0x6c,0x6f,0x63,0x6b,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x69,0x6d,0x67,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,
+ 0x3a,0x20,0x68,0x69,0x64,0x64,0x65,0x6e,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE9_[] = {
+
+ 0x23,0x68,0x65,0x61,0x64,0x69,0x6e,0x67,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,0x74,0x61,0x74,0x69,
+ 0x63,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x6c,0x65,0x66,
+ 0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,
+ 0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x74,0x6f,0x70,0x3a,0x20,
+ 0x30,0x2e,0x35,0x65,0x6d,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,
+ 0x62,0x73,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x63,0x6c,0x65,0x61,0x72,0x3a,0x20,0x61,
+ 0x6c,0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,
+ 0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x6f,0x70,0x3a,
+ 0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,0x66,0x74,0x3a,0x20,
+ 0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,
+ 0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,
+ 0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,
+ 0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,0x3a,0x20,0x31,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,0x20,
+ 0x64,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
+ 0x6e,0x3a,0x20,0x72,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x6c,0x69,0x6e,0x65,0x2d,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x6e,0x6f,
+ 0x72,0x6d,0x61,0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,
+ 0x2d,0x74,0x6f,0x70,0x3a,0x20,0x35,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,
+ 0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x35,0x70,
+ 0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x74,0x61,0x62,0x73,0x20,0x64,
+ 0x69,0x76,0x2e,0x73,0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,
+ 0x20,0x36,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,0x6e,0x64,0x65,0x78,
+ 0x3a,0x20,0x32,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2e,0x54,0x61,0x62,0x50,
+ 0x61,0x67,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
+ 0x6e,0x3a,0x20,0x72,0x65,0x6c,0x61,0x74,0x69,0x76,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x74,0x6f,0x70,0x3a,0x20,0x2d,0x31,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x65,
+ 0x66,0x74,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x69,0x67,
+ 0x68,0x74,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x74,
+ 0x74,0x6f,0x6d,0x3a,0x20,0x61,0x75,0x74,0x6f,0x3b,0x0d,0x0a,0x20,0x20,0x63,0x6c,
+ 0x65,0x61,0x72,0x3a,0x20,0x6c,0x65,0x66,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x61,
+ 0x72,0x67,0x69,0x6e,0x2d,0x6c,0x65,0x66,0x74,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x72,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,
+ 0x6e,0x67,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x20,0x20,0x7a,0x2d,0x69,
+ 0x6e,0x64,0x65,0x78,0x3a,0x20,0x31,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,
+ 0x31,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x69,0x66,0x72,
+ 0x61,0x6d,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,
+ 0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,
+ 0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,
+ 0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,
+ 0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x66,0x69,
+ 0x6c,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,
+ 0x6e,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,
+ 0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,
+ 0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x73,
+ 0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x70,0x6f,0x73,
+ 0x69,0x74,0x69,0x6f,0x6e,0x3a,0x20,0x73,0x74,0x61,0x74,0x69,0x63,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x31,0x30,0x30,0x25,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x20,0x73,0x6f,0x6d,0x65,0x20,0x64,0x65,0x66,
+ 0x61,0x75,0x6c,0x74,0x73,0x20,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x2e,0x54,0x61,0x62,
+ 0x50,0x61,0x67,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x36,0x35,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,
+ 0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x68,
+ 0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x36,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,
+ 0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x36,0x30,0x30,
+ 0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,
+ 0x65,0x44,0x69,0x76,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,
+ 0x3a,0x20,0x36,0x30,0x30,0x70,0x78,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE10_[] = {
+
+ 0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2d,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x2e,0x63,0x73,0x73,
+ 0x20,0x2d,0x20,0x4a,0x53,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x73,0x79,
+ 0x6e,0x74,0x61,0x78,0x20,0x68,0x69,0x67,0x68,0x6c,0x69,0x67,0x68,0x74,0x69,0x6e,
+ 0x67,0x20,0x73,0x74,0x79,0x6c,0x65,0x20,0x73,0x68,0x65,0x65,0x74,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,
+ 0x20,0x32,0x30,0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,
+ 0x6b,0x73,0x2e,0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,
+ 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,
+ 0x65,0x65,0x20,0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,
+ 0x20,0x63,0x61,0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,
+ 0x65,0x20,0x69,0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,
+ 0x66,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,
+ 0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,
+ 0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,
+ 0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,
+ 0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,
+ 0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,
+ 0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,
+ 0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,
+ 0x20,0x6f,0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,
+ 0x72,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,
+ 0x74,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,
+ 0x20,0x69,0x73,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,
+ 0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,
+ 0x20,0x69,0x74,0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,
+ 0x75,0x6c,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,
+ 0x48,0x4f,0x55,0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,
+ 0x59,0x3b,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,
+ 0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,
+ 0x61,0x6e,0x74,0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,
+ 0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,
+ 0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,
+ 0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,
+ 0x2e,0x20,0x20,0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,
+ 0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,
+ 0x6f,0x72,0x65,0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,
+ 0x61,0x76,0x65,0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,
+ 0x6f,0x70,0x79,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,
+ 0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,
+ 0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
+ 0x61,0x6d,0x3b,0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,
+ 0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,
+ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,
+ 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,
+ 0x20,0x46,0x72,0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,
+ 0x2c,0x20,0x46,0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,
+ 0x6f,0x73,0x74,0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,
+ 0x31,0x33,0x30,0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,
+ 0x0a,0x2f,0x2a,0x20,0x6b,0x65,0x79,0x77,0x6f,0x72,0x64,0x2c,0x20,0x74,0x79,0x70,
+ 0x65,0x2c,0x20,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x2c,0x20,0x63,0x62,0x72,0x61,0x63,
+ 0x6b,0x65,0x74,0x20,0x2a,0x2f,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,
+ 0x61,0x62,0x6c,0x65,0x20,0x2e,0x6b,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x6e,
+ 0x74,0x2d,0x77,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x62,0x6f,0x6c,0x64,0x3b,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2c,
+ 0x20,0x72,0x65,0x67,0x65,0x78,0x70,0x2c,0x20,0x6e,0x75,0x6d,0x62,0x65,0x72,0x20,
+ 0x2a,0x2f,0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,
+ 0x20,0x2e,0x73,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,
+ 0x23,0x30,0x30,0x36,0x34,0x30,0x30,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,
+ 0x2a,0x20,0x73,0x70,0x65,0x63,0x69,0x61,0x6c,0x63,0x68,0x61,0x72,0x20,0x2a,0x2f,
+ 0x0d,0x0a,0x23,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x2e,
+ 0x74,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3a,0x20,0x23,0x32,
+ 0x65,0x38,0x62,0x35,0x37,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x20,
+ 0x63,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x20,0x2a,0x2f,0x0d,0x0a,0x23,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x54,0x61,0x62,0x6c,0x65,0x20,0x2e,0x63,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x6e,0x74,0x2d,0x73,0x74,0x79,0x6c,0x65,0x3a,0x20,0x69,0x74,0x61,
+ 0x6c,0x69,0x63,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE11_[] = {
+
+ 0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x6a,0x73,0x20,0x2d,0x20,0x63,0x6f,0x64,0x65,0x20,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x20,0x66,0x6f,0x72,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,
+ 0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,
+ 0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30,0x37,0x2c,0x20,0x32,0x30,
+ 0x30,0x38,0x20,0x73,0x69,0x6c,0x69,0x63,0x6f,0x6e,0x66,0x6f,0x72,0x6b,0x73,0x2e,
+ 0x63,0x6f,0x6d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,
+ 0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,0x20,0x66,0x72,0x65,0x65,0x20,
+ 0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x3b,0x20,0x79,0x6f,0x75,0x20,0x63,0x61,
+ 0x6e,0x20,0x72,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x20,0x69,
+ 0x74,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x69,0x74,0x20,0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,
+ 0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,
+ 0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,
+ 0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x61,0x73,0x20,0x70,0x75,0x62,
+ 0x6c,0x69,0x73,0x68,0x65,0x64,0x20,0x62,0x79,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,
+ 0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,
+ 0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x3b,0x20,0x65,0x69,0x74,
+ 0x68,0x65,0x72,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x32,0x20,0x6f,0x66,
+ 0x20,0x74,0x68,0x65,0x20,0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x2c,0x20,0x6f,0x72,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x28,0x61,0x74,0x20,0x79,0x6f,0x75,0x72,0x20,0x6f,
+ 0x70,0x74,0x69,0x6f,0x6e,0x29,0x20,0x61,0x6e,0x79,0x20,0x6c,0x61,0x74,0x65,0x72,
+ 0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x54,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x69,0x73,
+ 0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x69,0x6e,0x20,
+ 0x74,0x68,0x65,0x20,0x68,0x6f,0x70,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x69,0x74,
+ 0x20,0x77,0x69,0x6c,0x6c,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x66,0x75,0x6c,0x2c,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x62,0x75,0x74,0x20,0x57,0x49,0x54,0x48,0x4f,0x55,
+ 0x54,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x3b,0x20,
+ 0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x65,0x76,0x65,0x6e,0x20,0x74,0x68,0x65,
+ 0x20,0x69,0x6d,0x70,0x6c,0x69,0x65,0x64,0x20,0x77,0x61,0x72,0x72,0x61,0x6e,0x74,
+ 0x79,0x20,0x6f,0x66,0x0d,0x0a,0x20,0x20,0x20,0x20,0x4d,0x45,0x52,0x43,0x48,0x41,
+ 0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x20,0x6f,0x72,0x20,0x46,0x49,0x54,
+ 0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52,0x20,0x41,0x20,0x50,0x41,0x52,0x54,0x49,
+ 0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x2e,0x20,0x20,
+ 0x53,0x65,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x47,0x4e,0x55,
+ 0x20,0x47,0x65,0x6e,0x65,0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,
+ 0x4c,0x69,0x63,0x65,0x6e,0x73,0x65,0x20,0x66,0x6f,0x72,0x20,0x6d,0x6f,0x72,0x65,
+ 0x20,0x64,0x65,0x74,0x61,0x69,0x6c,0x73,0x2e,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x59,0x6f,0x75,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x68,0x61,0x76,0x65,
+ 0x20,0x72,0x65,0x63,0x65,0x69,0x76,0x65,0x64,0x20,0x61,0x20,0x63,0x6f,0x70,0x79,
+ 0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x47,0x4e,0x55,0x20,0x47,0x65,0x6e,0x65,
+ 0x72,0x61,0x6c,0x20,0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x4c,0x69,0x63,0x65,0x6e,
+ 0x73,0x65,0x20,0x61,0x6c,0x6f,0x6e,0x67,0x0d,0x0a,0x20,0x20,0x20,0x20,0x77,0x69,
+ 0x74,0x68,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x3b,
+ 0x20,0x69,0x66,0x20,0x6e,0x6f,0x74,0x2c,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,
+ 0x6f,0x20,0x74,0x68,0x65,0x20,0x46,0x72,0x65,0x65,0x20,0x53,0x6f,0x66,0x74,0x77,
+ 0x61,0x72,0x65,0x20,0x46,0x6f,0x75,0x6e,0x64,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,
+ 0x49,0x6e,0x63,0x2e,0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x35,0x31,0x20,0x46,0x72,
+ 0x61,0x6e,0x6b,0x6c,0x69,0x6e,0x20,0x53,0x74,0x72,0x65,0x65,0x74,0x2c,0x20,0x46,
+ 0x69,0x66,0x74,0x68,0x20,0x46,0x6c,0x6f,0x6f,0x72,0x2c,0x20,0x42,0x6f,0x73,0x74,
+ 0x6f,0x6e,0x2c,0x20,0x4d,0x41,0x20,0x30,0x32,0x31,0x31,0x30,0x2d,0x31,0x33,0x30,
+ 0x31,0x20,0x55,0x53,0x41,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,
+ 0x2a,0x0d,0x0a,0x49,0x6e,0x69,0x74,0x69,0x61,0x6c,0x69,0x7a,0x65,0x73,0x20,0x74,
+ 0x68,0x65,0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x20,0x69,0x6e,0x20,0x61,0x20,0x77,0x69,0x6e,0x64,
+ 0x6f,0x77,0x2e,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,
+ 0x20,0x62,0x65,0x20,0x74,0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x0d,0x0a,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x61,0x6c,0x6c,0x65,0x64,0x20,0x69,
+ 0x6e,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x2e,0x0d,0x0a,0x40,0x70,0x61,
+ 0x72,0x61,0x6d,0x20,0x20,0x77,0x20,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x68,0x6f,
+ 0x75,0x6c,0x64,0x20,0x61,0x6c,0x77,0x61,0x79,0x73,0x20,0x62,0x65,0x20,0x74,0x68,
+ 0x65,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x20,
+ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,
+ 0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x69,0x6e,0x69,0x74,0x28,0x77,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x74,0x72,0x79,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x69,0x6e,0x20,0x53,0x61,
+ 0x66,0x61,0x72,0x69,0x2c,0x20,0x22,0x69,0x6d,0x70,0x6f,0x72,0x74,0x22,0x20,0x69,
+ 0x73,0x20,0x61,0x20,0x73,0x79,0x6e,0x74,0x61,0x78,0x20,0x65,0x72,0x72,0x6f,0x72,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,
+ 0x2e,0x75,0x74,0x69,0x6c,0x73,0x5b,0x27,0x69,0x6d,0x70,0x6f,0x72,0x74,0x27,0x5d,
+ 0x28,0x27,0x72,0x65,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x2f,0x2f,0x67,0x72,0x65,
+ 0x2f,0x6d,0x6f,0x64,0x75,0x6c,0x65,0x73,0x2f,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2e,0x6a,0x73,0x6d,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,
+ 0x65,0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x74,0x72,0x75,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x63,0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,
+ 0x20,0x7b,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x77,0x2e,0x6f,
+ 0x70,0x65,0x6e,0x65,0x72,0x20,0x26,0x26,0x20,0x77,0x2e,0x6f,0x70,0x65,0x6e,0x65,
+ 0x72,0x2e,0x74,0x6f,0x70,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x77,0x65,
+ 0x20,0x61,0x72,0x65,0x20,0x69,0x6e,0x20,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,
+ 0x20,0x6d,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,
+ 0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x3d,0x20,0x77,0x2e,0x6f,0x70,0x65,0x6e,0x65,0x72,0x2e,0x74,0x6f,0x70,0x2e,0x5f,
+ 0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x77,0x65,0x20,0x61,0x72,
+ 0x65,0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x20,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,
+ 0x64,0x20,0x6d,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,0x72,0x74,0x65,
+ 0x64,0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,
+ 0x46,0x69,0x6c,0x65,0x20,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x3b,0x0d,0x0a,0x76,0x61,
+ 0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,
+ 0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x3b,
+ 0x0d,0x0a,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,
+ 0x0d,0x0a,0x2f,0x2a,0x0d,0x0a,0x50,0x6f,0x73,0x73,0x69,0x62,0x6c,0x65,0x20,0x73,
+ 0x74,0x61,0x74,0x65,0x73,0x3a,0x0d,0x0a,0x09,0x09,0x09,0x69,0x73,0x49,0x6e,0x76,
+ 0x65,0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x09,0x69,0x73,0x53,0x65,0x72,0x76,
+ 0x65,0x72,0x09,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x09,0x74,0x61,0x62,0x73,
+ 0x0d,0x0a,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x09,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,
+ 0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,
+ 0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x0d,0x0a,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,
+ 0x64,0x09,0x09,0x74,0x72,0x75,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,
+ 0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x0d,0x0a,0x73,0x65,0x72,0x76,0x65,0x72,0x2c,
+ 0x20,0x6e,0x6f,0x72,0x6d,0x61,0x6c,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,
+ 0x74,0x72,0x75,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x42,0x72,0x6f,
+ 0x77,0x73,0x65,0x72,0x2c,0x20,0x53,0x74,0x6f,0x72,0x65,0x0d,0x0a,0x73,0x65,0x72,
+ 0x76,0x65,0x72,0x2c,0x20,0x69,0x6e,0x76,0x65,0x72,0x74,0x65,0x64,0x09,0x74,0x72,
+ 0x75,0x65,0x09,0x09,0x74,0x72,0x75,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,
+ 0x09,0x53,0x74,0x6f,0x72,0x65,0x0d,0x0a,0x72,0x65,0x70,0x6f,0x72,0x74,0x09,0x09,
+ 0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x66,0x61,0x6c,0x73,0x65,0x09,0x09,0x74,
+ 0x72,0x75,0x65,0x09,0x09,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,
+ 0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,
+ 0x3b,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x69,0x73,0x53,0x65,0x72,0x76,0x65,0x72,0x20,0x3d,0x20,0x66,0x61,0x6c,
+ 0x73,0x65,0x3b,0x0d,0x0a,0x76,0x61,0x72,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x20,0x3d,0x20,0x66,
+ 0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x69,0x6e,0x69,0x74,0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,0x29,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x72,0x65,0x61,0x74,0x65,0x52,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x2f,0x2f,
+ 0x20,0x4e,0x6f,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x65,0x20,0x49,
+ 0x45,0x37,0x20,0x58,0x4d,0x4c,0x48,0x74,0x74,0x70,0x52,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x20,0x64,0x6f,0x65,0x73,0x20,0x6e,0x6f,0x74,0x20,0x73,0x75,0x70,0x70,0x6f,
+ 0x72,0x74,0x20,0x66,0x69,0x6c,0x65,0x20,0x55,0x52,0x4c,0x27,0x73,0x2e,0x0d,0x0a,
+ 0x20,0x20,0x2f,0x2f,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x78,0x68,0x61,0x62,
+ 0x2e,0x62,0x6c,0x6f,0x67,0x73,0x70,0x6f,0x74,0x2e,0x63,0x6f,0x6d,0x2f,0x32,0x30,
+ 0x30,0x36,0x2f,0x31,0x31,0x2f,0x69,0x65,0x37,0x2d,0x73,0x75,0x70,0x70,0x6f,0x72,
+ 0x74,0x2d,0x66,0x6f,0x72,0x2d,0x78,0x6d,0x6c,0x68,0x74,0x74,0x70,0x72,0x65,0x71,
+ 0x75,0x65,0x73,0x74,0x2e,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,
+ 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x62,0x6c,0x6f,0x67,0x73,0x2e,0x6d,0x73,0x64,
+ 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x69,0x65,0x2f,0x61,0x72,0x63,0x68,0x69,0x76,0x65,
+ 0x2f,0x32,0x30,0x30,0x36,0x2f,0x31,0x32,0x2f,0x30,0x36,0x2f,0x66,0x69,0x6c,0x65,
+ 0x2d,0x75,0x72,0x69,0x73,0x2d,0x69,0x6e,0x2d,0x77,0x69,0x6e,0x64,0x6f,0x77,0x73,
+ 0x2e,0x61,0x73,0x70,0x78,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,
+ 0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x77,
+ 0x69,0x6e,0x64,0x6f,0x77,0x2e,0x41,0x63,0x74,0x69,0x76,0x65,0x58,0x4f,0x62,0x6a,
+ 0x65,0x63,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x6e,0x65,0x77,0x20,0x41,0x63,0x74,0x69,0x76,0x65,0x58,0x4f,0x62,
+ 0x6a,0x65,0x63,0x74,0x28,0x22,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,
+ 0x58,0x4d,0x4c,0x48,0x54,0x54,0x50,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x65,0x77,0x20,0x58,0x4d,0x4c,0x48,0x74,0x74,
+ 0x70,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,
+ 0x2f,0x77,0x77,0x77,0x2e,0x71,0x75,0x69,0x72,0x6b,0x73,0x6d,0x6f,0x64,0x65,0x2e,
+ 0x6f,0x72,0x67,0x2f,0x6a,0x73,0x2f,0x66,0x69,0x6e,0x64,0x70,0x6f,0x73,0x2e,0x68,
+ 0x74,0x6d,0x6c,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,
+ 0x28,0x6f,0x62,0x6a,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x72,
+ 0x65,0x73,0x75,0x6c,0x74,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x64,0x6f,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x20,0x2b,
+ 0x3d,0x20,0x6f,0x62,0x6a,0x2e,0x6f,0x66,0x66,0x73,0x65,0x74,0x54,0x6f,0x70,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x6f,0x62,0x6a,0x20,0x3d,0x20,0x6f,0x62,0x6a,0x2e,
+ 0x6f,0x66,0x66,0x73,0x65,0x74,0x50,0x61,0x72,0x65,0x6e,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x28,0x6f,0x62,0x6a,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65,0x73,
+ 0x75,0x6c,0x74,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x68,0x74,
+ 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x71,0x75,0x69,0x72,0x6b,0x73,0x6d,
+ 0x6f,0x64,0x65,0x2e,0x6f,0x72,0x67,0x2f,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,
+ 0x2f,0x63,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x2e,0x68,
+ 0x74,0x6d,0x6c,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,0x65,0x74,0x56,0x69,0x65,0x77,
+ 0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x28,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,
+ 0x20,0x2f,0x4d,0x53,0x49,0x45,0x2f,0x2e,0x74,0x65,0x73,0x74,0x28,0x6e,0x61,0x76,
+ 0x69,0x67,0x61,0x74,0x6f,0x72,0x2e,0x75,0x73,0x65,0x72,0x41,0x67,0x65,0x6e,0x74,
+ 0x29,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x73,0x65,0x6c,0x66,0x2e,0x69,0x6e,
+ 0x6e,0x65,0x72,0x48,0x65,0x69,0x67,0x68,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x2f,0x2f,0x20,0x61,0x6c,0x6c,0x20,0x65,0x78,0x63,0x65,0x70,0x74,0x20,
+ 0x45,0x78,0x70,0x6c,0x6f,0x72,0x65,0x72,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x73,0x65,0x6c,0x66,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,
+ 0x65,0x69,0x67,0x68,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,
+ 0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x20,0x26,0x26,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x6c,0x69,
+ 0x65,0x6e,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x2f,0x2f,0x20,0x45,0x78,0x70,0x6c,0x6f,0x72,0x65,0x72,0x20,0x36,0x20,
+ 0x53,0x74,0x72,0x69,0x63,0x74,0x20,0x4d,0x6f,0x64,0x65,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x63,0x6c,0x69,0x65,0x6e,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,0x64,0x79,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x45,
+ 0x78,0x70,0x6c,0x6f,0x72,0x65,0x72,0x73,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x62,0x6f,
+ 0x64,0x79,0x2e,0x63,0x6c,0x69,0x65,0x6e,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x22,0x43,0x6f,0x75,0x6c,
+ 0x64,0x6e,0x27,0x74,0x20,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x20,0x76,
+ 0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x22,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,
+ 0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x49,0x6e,0x64,0x69,0x63,0x61,0x74,0x65,0x73,0x20,
+ 0x76,0x69,0x73,0x75,0x61,0x6c,0x6c,0x79,0x20,0x74,0x68,0x61,0x74,0x20,0x61,0x20,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x79,0x20,0x6f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,
+ 0x6e,0x20,0x68,0x61,0x73,0x20,0x62,0x65,0x67,0x75,0x6e,0x2e,0x20,0x20,0x54,0x68,
+ 0x65,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x20,0x62,0x61,0x72,0x20,0x69,
+ 0x73,0x0d,0x0a,0x64,0x69,0x73,0x70,0x6c,0x61,0x79,0x65,0x64,0x2c,0x20,0x61,0x6e,
+ 0x64,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x20,0x69,0x73,0x20,
+ 0x63,0x68,0x61,0x6e,0x67,0x65,0x64,0x20,0x74,0x6f,0x20,0x62,0x75,0x73,0x79,0x20,
+ 0x28,0x6f,0x6e,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x73,0x20,0x77,0x68,0x69,
+ 0x63,0x68,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x74,0x68,0x69,0x73,0x29,
+ 0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,
+ 0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,
+ 0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x74,0x79,0x6c,
+ 0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,
+ 0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,0x6f,
+ 0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,
+ 0x65,0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x2c,0x20,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,
+ 0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x4c,0x61,0x62,0x65,0x6c,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x76,0x69,
+ 0x73,0x69,0x62,0x6c,0x65,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,
+ 0x62,0x6c,0x61,0x63,0x6b,0x6c,0x69,0x73,0x74,0x20,0x62,0x75,0x67,0x67,0x79,0x20,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x73,0x20,0x2a,0x2f,0x0d,0x0a,0x2f,0x2f,0x23,
+ 0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x0d,0x0a,0x20,
+ 0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x2f,0x4f,0x70,0x65,0x72,0x61,0x7c,0x57,0x65,
+ 0x62,0x4b,0x69,0x74,0x2f,0x2e,0x74,0x65,0x73,0x74,0x28,0x6e,0x61,0x76,0x69,0x67,
+ 0x61,0x74,0x6f,0x72,0x2e,0x75,0x73,0x65,0x72,0x41,0x67,0x65,0x6e,0x74,0x29,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x43,0x68,0x61,0x6e,0x67,0x65,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x73,0x6f,
+ 0x72,0x20,0x73,0x74,0x79,0x6c,0x65,0x20,0x6f,0x66,0x20,0x65,0x61,0x63,0x68,0x20,
+ 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x20,0x20,0x4e,0x6f,0x74,0x65,0x20,0x74,
+ 0x68,0x61,0x74,0x20,0x63,0x68,0x61,0x6e,0x67,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,
+ 0x20,0x63,0x6c,0x61,0x73,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x20,0x28,0x74,0x6f,0x20,0x6f,
+ 0x6e,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x62,0x75,0x73,0x79,0x20,0x63,
+ 0x75,0x72,0x73,0x6f,0x72,0x29,0x20,0x69,0x73,0x20,0x62,0x75,0x67,0x67,0x79,0x20,
+ 0x69,0x6e,0x20,0x49,0x45,0x2e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2a,0x2f,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x2e,0x67,
+ 0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,
+ 0x61,0x6d,0x65,0x28,0x27,0x64,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,
+ 0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,0x62,
+ 0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x73,0x2e,0x69,0x74,0x65,
+ 0x6d,0x28,0x69,0x29,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x63,0x75,0x72,0x73,0x6f,
+ 0x72,0x20,0x3d,0x20,0x27,0x77,0x61,0x69,0x74,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,
+ 0x2a,0x0d,0x0a,0x52,0x65,0x6d,0x6f,0x76,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x70,
+ 0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x20,0x62,0x61,0x72,0x20,0x61,0x6e,0x64,0x20,
+ 0x62,0x75,0x73,0x79,0x20,0x63,0x75,0x72,0x73,0x6f,0x72,0x2e,0x0d,0x0a,0x2a,0x2f,
+ 0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,
+ 0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,
+ 0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,
+ 0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x42,0x61,0x72,0x2c,0x20,0x31,0x30,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x65,
+ 0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,
+ 0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,
+ 0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,
+ 0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x4c,0x61,0x62,0x65,0x6c,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,
+ 0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,0x64,0x64,0x65,0x6e,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x4c,0x61,0x62,0x65,0x6c,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,
+ 0x3d,0x20,0x27,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,
+ 0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x64,0x69,
+ 0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,
+ 0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,0x62,0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x74,0x61,0x62,0x73,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,0x29,0x2e,0x73,0x74,
+ 0x79,0x6c,0x65,0x2e,0x63,0x75,0x72,0x73,0x6f,0x72,0x20,0x3d,0x20,0x27,0x27,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x20,0x35,0x30,
+ 0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x74,
+ 0x53,0x69,0x7a,0x65,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,
+ 0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x20,0x2f,0x4d,0x53,0x49,0x45,
+ 0x2f,0x2e,0x74,0x65,0x73,0x74,0x28,0x6e,0x61,0x76,0x69,0x67,0x61,0x74,0x6f,0x72,
+ 0x2e,0x75,0x73,0x65,0x72,0x41,0x67,0x65,0x6e,0x74,0x29,0x0d,0x0a,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,
+ 0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,
+ 0x65,0x74,0x56,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x62,
+ 0x6f,0x72,0x64,0x65,0x72,0x2d,0x74,0x6f,0x70,0x2d,0x77,0x69,0x64,0x74,0x68,0x3a,
+ 0x20,0x20,0x20,0x20,0x20,0x31,0x70,0x78,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,
+ 0x69,0x6e,0x67,0x2d,0x74,0x6f,0x70,0x3a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x31,0x30,0x70,0x78,0x0d,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,
+ 0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x3a,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x30,
+ 0x70,0x78,0x0d,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x2d,0x62,0x6f,0x74,
+ 0x74,0x6f,0x6d,0x2d,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x20,0x31,0x70,0x78,0x0d,
+ 0x0a,0x20,0x20,0x6d,0x61,0x72,0x67,0x69,0x6e,0x2d,0x62,0x6f,0x74,0x74,0x6f,0x6d,
+ 0x3a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x31,0x30,0x70,0x78,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x33,0x32,0x70,0x78,0x0d,0x0a,0x20,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,
+ 0x67,0x65,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,0x76,0x69,0x65,0x77,
+ 0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,
+ 0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x29,0x20,0x2d,0x20,0x33,0x32,0x29,0x20,
+ 0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,
+ 0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x50,0x61,0x67,
+ 0x65,0x73,0x2e,0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x6e,
+ 0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x69,0x20,0x3d,0x20,
+ 0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,
+ 0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,
+ 0x6f,0x64,0x65,0x20,0x3d,0x20,0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x69,
+ 0x74,0x65,0x6d,0x28,0x69,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x6e,0x6f,0x64,0x65,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x21,
+ 0x3d,0x3d,0x20,0x31,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,
+ 0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,
+ 0x48,0x65,0x69,0x67,0x68,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x20,
+ 0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,
+ 0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x69,0x66,0x72,0x61,0x6d,
+ 0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x6d,0x61,
+ 0x79,0x20,0x6e,0x6f,0x74,0x20,0x65,0x78,0x69,0x73,0x74,0x20,0x69,0x66,0x20,0x77,
+ 0x65,0x20,0x68,0x61,0x76,0x65,0x20,0x72,0x65,0x6d,0x6f,0x76,0x65,0x64,0x20,0x74,
+ 0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x20,0x74,0x61,0x62,0x0d,0x0a,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x2e,
+ 0x73,0x74,0x79,0x6c,0x65,0x2e,0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,
+ 0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,
+ 0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,
+ 0x50,0x6f,0x73,0x28,0x69,0x66,0x72,0x61,0x6d,0x65,0x44,0x69,0x76,0x29,0x20,0x2d,
+ 0x20,0x32,0x31,0x29,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x44,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,
+ 0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x2e,0x73,0x74,0x79,
+ 0x6c,0x65,0x2e,0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,0x76,0x69,0x65,
+ 0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,
+ 0x28,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x44,0x69,0x76,0x29,0x20,0x2d,0x20,0x32,
+ 0x31,0x29,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,
+ 0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,
+ 0x69,0x76,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x68,0x65,0x69,0x67,0x68,0x74,0x20,
+ 0x3d,0x20,0x28,0x76,0x69,0x65,0x77,0x70,0x6f,0x72,0x74,0x48,0x65,0x69,0x67,0x68,
+ 0x74,0x20,0x2d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,
+ 0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,
+ 0x29,0x20,0x2d,0x20,0x32,0x31,0x29,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,
+ 0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,
+ 0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x74,0x6f,
+ 0x72,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,
+ 0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x68,0x65,0x69,0x67,0x68,0x74,0x20,0x3d,0x20,0x28,0x76,0x69,0x65,0x77,0x70,0x6f,
+ 0x72,0x74,0x48,0x65,0x69,0x67,0x68,0x74,0x20,0x2d,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,0x73,0x74,
+ 0x6f,0x72,0x65,0x44,0x69,0x76,0x29,0x20,0x2d,0x20,0x32,0x31,0x29,0x20,0x2b,0x20,
+ 0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,
+ 0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,0x0d,
+ 0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x52,0x65,0x74,0x75,0x72,
+ 0x6e,0x73,0x20,0x74,0x68,0x65,0x20,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x20,0x76,
+ 0x61,0x6c,0x75,0x65,0x20,0x6f,0x66,0x20,0x61,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,
+ 0x2e,0x20,0x20,0x56,0x61,0x6c,0x75,0x65,0x73,0x20,0x27,0x66,0x61,0x6c,0x73,0x65,
+ 0x27,0x2c,0x20,0x27,0x66,0x27,0x2c,0x20,0x27,0x6e,0x6f,0x27,0x2c,0x20,0x27,0x6e,
+ 0x27,0x2c,0x20,0x27,0x6f,0x66,0x66,0x27,0x2c,0x0d,0x0a,0x61,0x6e,0x64,0x20,0x27,
+ 0x30,0x27,0x20,0x28,0x75,0x70,0x70,0x65,0x72,0x20,0x6f,0x72,0x20,0x6c,0x6f,0x77,
+ 0x65,0x72,0x20,0x63,0x61,0x73,0x65,0x29,0x20,0x61,0x72,0x65,0x20,0x66,0x61,0x6c,
+ 0x73,0x65,0x2e,0x0d,0x0a,0x40,0x70,0x61,0x72,0x61,0x6d,0x20,0x20,0x73,0x20,0x20,
+ 0x74,0x68,0x65,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x0d,0x0a,0x40,0x72,0x65,0x74,
+ 0x75,0x72,0x6e,0x20,0x20,0x61,0x20,0x62,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x20,0x76,
+ 0x61,0x6c,0x75,0x65,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,0x65,
+ 0x74,0x42,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x56,0x61,0x6c,0x75,0x65,0x28,0x73,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x73,0x20,0x3d,0x20,0x73,0x2e,0x74,0x6f,0x4c,0x6f,
+ 0x77,0x65,0x72,0x43,0x61,0x73,0x65,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x66,0x61,0x6c,0x73,0x65,0x27,0x20,
+ 0x7c,0x7c,0x20,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x66,0x27,0x20,0x7c,0x7c,0x20,
+ 0x73,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x6e,0x6f,0x27,0x20,0x7c,0x7c,0x20,0x73,0x20,
+ 0x3d,0x3d,0x3d,0x20,0x27,0x6e,0x27,0x20,0x7c,0x7c,0x20,0x73,0x20,0x3d,0x3d,0x3d,
+ 0x20,0x27,0x6f,0x66,0x66,0x27,0x20,0x7c,0x7c,0x20,0x73,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x27,0x30,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x54,
+ 0x61,0x62,0x28,0x69,0x64,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x74,0x61,0x62,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,
+ 0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x69,0x64,
+ 0x20,0x2b,0x20,0x27,0x54,0x61,0x62,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x61,
+ 0x62,0x2e,0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,0x65,0x6d,
+ 0x6f,0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x74,0x61,0x62,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x69,0x64,0x20,0x2b,0x20,0x27,0x54,0x61,
+ 0x62,0x50,0x61,0x67,0x65,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x61,0x62,0x50,
+ 0x61,0x67,0x65,0x2e,0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,
+ 0x65,0x6d,0x6f,0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x74,0x61,0x62,0x50,0x61,
+ 0x67,0x65,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,
+ 0x49,0x6e,0x69,0x74,0x69,0x61,0x6c,0x69,0x7a,0x65,0x73,0x20,0x74,0x68,0x65,0x20,
+ 0x63,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,
+ 0x74,0x61,0x62,0x73,0x2e,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x73,0x65,0x74,0x73,
+ 0x20,0x74,0x68,0x65,0x20,0x69,0x6e,0x69,0x74,0x69,0x61,0x6c,0x20,0x76,0x61,0x6c,
+ 0x75,0x65,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x0d,0x0a,0x69,0x6e,0x70,0x75,
+ 0x74,0x20,0x66,0x69,0x65,0x6c,0x64,0x20,0x61,0x6e,0x64,0x20,0x69,0x66,0x72,0x61,
+ 0x6d,0x65,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x22,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x22,0x20,0x74,0x61,0x62,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,
+ 0x22,0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x22,0x0d,0x0a,0x74,0x61,0x62,0x2e,0x0d,
+ 0x0a,0x40,0x70,0x61,0x72,0x61,0x6d,0x20,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x20,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x68,0x6f,0x75,0x6c,
+ 0x64,0x20,0x61,0x6c,0x77,0x61,0x79,0x73,0x20,0x62,0x65,0x20,0x6c,0x6f,0x63,0x61,
+ 0x74,0x69,0x6f,0x6e,0x2e,0x73,0x65,0x61,0x72,0x63,0x68,0x0d,0x0a,0x2a,0x2f,0x0d,
+ 0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,
+ 0x65,0x6e,0x74,0x73,0x28,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,0x6e,0x67,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x68,0x6f,0x77,0x4d,
+ 0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x3d,0x20,0x66,
+ 0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x61,0x72,
+ 0x61,0x6d,0x65,0x74,0x65,0x72,0x73,0x2c,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,
+ 0x65,0x72,0x2c,0x20,0x69,0x2c,0x20,0x69,0x6e,0x64,0x65,0x78,0x2c,0x20,0x75,0x72,
+ 0x6c,0x2c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,
+ 0x6e,0x67,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3e,0x20,0x30,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x63,0x68,0x6f,0x70,0x20,0x6f,0x66,
+ 0x66,0x20,0x74,0x68,0x65,0x20,0x71,0x75,0x65,0x73,0x74,0x69,0x6f,0x6e,0x20,0x6d,
+ 0x61,0x72,0x6b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x20,0x3d,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,
+ 0x6e,0x67,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x31,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x73,
+ 0x20,0x3d,0x20,0x71,0x75,0x65,0x72,0x79,0x53,0x74,0x72,0x69,0x6e,0x67,0x2e,0x73,
+ 0x70,0x6c,0x69,0x74,0x28,0x2f,0x26,0x7c,0x3b,0x2f,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,
+ 0x3c,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x73,0x2e,0x6c,0x65,0x6e,
+ 0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x20,0x3d,0x20,0x70,
+ 0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x73,0x5b,0x69,0x5d,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x70,0x61,0x72,
+ 0x61,0x6d,0x65,0x74,0x65,0x72,0x2e,0x69,0x6e,0x64,0x65,0x78,0x4f,0x66,0x28,0x27,
+ 0x3d,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,
+ 0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x3d,0x3d,0x20,0x2d,0x31,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x73,0x74,0x69,0x6c,
+ 0x6c,0x20,0x77,0x6f,0x72,0x6b,0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x6f,0x6c,0x64,
+ 0x20,0x73,0x79,0x6e,0x74,0x61,0x78,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,
+ 0x65,0x72,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x30,0x2c,0x20,0x69,0x6e,0x64,
+ 0x65,0x78,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,
+ 0x6c,0x75,0x65,0x20,0x3d,0x20,0x70,0x61,0x72,0x61,0x6d,0x65,0x74,0x65,0x72,0x2e,
+ 0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x69,0x6e,0x64,0x65,0x78,0x20,0x2b,0x20,0x31,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,
+ 0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,
+ 0x67,0x27,0x20,0x7c,0x7c,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,
+ 0x6d,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,
+ 0x6d,0x6e,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x67,0x65,0x74,0x42,0x6f,0x6f,0x6c,0x65,0x61,0x6e,0x56,0x61,0x6c,0x75,0x65,0x28,
+ 0x76,0x61,0x6c,0x75,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x69,0x66,0x20,0x28,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x75,
+ 0x72,0x6c,0x27,0x20,0x7c,0x7c,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x27,0x75,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x76,0x61,0x6c,0x75,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x63,0x68,0x65,0x63,
+ 0x6b,0x62,0x6f,0x78,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x63,0x68,0x65,0x63,0x6b,
+ 0x62,0x6f,0x78,0x2e,0x63,0x68,0x65,0x63,0x6b,0x65,0x64,0x20,0x3d,0x20,0x73,0x68,
+ 0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,
+ 0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2f,
+ 0x20,0x74,0x68,0x69,0x73,0x20,0x77,0x69,0x6c,0x6c,0x20,0x61,0x75,0x74,0x6f,0x6d,
+ 0x61,0x74,0x69,0x63,0x61,0x6c,0x6c,0x79,0x20,0x70,0x72,0x6f,0x70,0x61,0x67,0x61,
+ 0x74,0x65,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,
+ 0x66,0x69,0x65,0x6c,0x64,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x75,0x72,0x6c,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x5b,
+ 0x30,0x5d,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x75,0x72,
+ 0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,
+ 0x69,0x66,0x20,0x74,0x68,0x65,0x20,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x20,0x74,
+ 0x61,0x62,0x20,0x69,0x73,0x20,0x61,0x62,0x73,0x65,0x6e,0x74,0x2c,0x20,0x77,0x65,
+ 0x20,0x68,0x61,0x76,0x65,0x20,0x74,0x6f,0x20,0x69,0x6e,0x69,0x74,0x69,0x61,0x6c,
+ 0x69,0x7a,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x20,
+ 0x74,0x61,0x62,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x42,0x79,0x49,0x64,0x28,0x27,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x54,0x61,0x62,
+ 0x27,0x29,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,
+ 0x65,0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x6f,
+ 0x64,0x79,0x5f,0x6c,0x6f,0x61,0x64,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x20,0x3d,
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x69,0x6e,0x69,0x74,0x28,0x70,0x72,0x6f,
+ 0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x45,
+ 0x72,0x72,0x6f,0x72,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,
+ 0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,
+ 0x79,0x49,0x64,0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,
+ 0x62,0x62,0x65,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x73,0x75,0x6d,
+ 0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x73,0x74,0x79,
+ 0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,
+ 0x27,0x68,0x69,0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x64,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x45,0x72,0x72,0x6f,0x72,0x44,0x69,
+ 0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x69,0x6e,
+ 0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x27,0x45,0x72,0x72,0x6f,0x72,
+ 0x3a,0x20,0x27,0x20,0x2b,0x20,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x69,0x73,0x52,0x65,0x70,0x6f,0x72,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,
+ 0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,
+ 0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x20,
+ 0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,
+ 0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,
+ 0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x68,0x72,0x6f,0x62,0x62,
+ 0x65,0x72,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,0x6c,
+ 0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x27,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,0x70,0x65,0x6e,0x28,0x27,
+ 0x47,0x45,0x54,0x27,0x2c,0x20,0x27,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x6a,0x73,0x6f,0x6e,0x27,0x2c,0x20,0x74,0x72,0x75,0x65,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,
+ 0x6e,0x72,0x65,0x61,0x64,0x79,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6e,0x67,
+ 0x65,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x65,0x76,
+ 0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x61,0x64,
+ 0x79,0x53,0x74,0x61,0x74,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x34,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,
+ 0x20,0x21,0x3d,0x3d,0x20,0x30,0x20,0x26,0x26,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x21,0x3d,0x3d,0x20,0x32,0x30,0x30,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,
+ 0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,
+ 0x65,0x20,0x3d,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x73,0x70,
+ 0x6f,0x6e,0x73,0x65,0x54,0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,0x65,0x73,0x70,0x6f,
+ 0x6e,0x73,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x72,
+ 0x6f,0x77,0x20,0x34,0x30,0x34,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x65,
+ 0x76,0x61,0x6c,0x28,0x27,0x28,0x27,0x20,0x2b,0x20,0x72,0x65,0x73,0x70,0x6f,0x6e,
+ 0x73,0x65,0x20,0x2b,0x20,0x27,0x29,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x66,
+ 0x6f,0x72,0x20,0x28,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,0x6a,0x73,0x6f,0x6e,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x43,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x20,0x3d,0x20,0x6a,0x73,0x6f,0x6e,0x5b,0x66,0x69,0x6c,0x65,0x5d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,
+ 0x6c,0x65,0x5d,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x24,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x2e,0x73,
+ 0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,
+ 0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x68,0x72,0x6f,0x62,0x62,0x65,0x72,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,
+ 0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,
+ 0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x45,0x72,
+ 0x72,0x6f,0x72,0x28,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x6e,0x64,0x28,0x6e,0x75,
+ 0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x61,0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x65,0x70,0x6f,0x72,0x74,0x45,0x72,0x72,0x6f,0x72,0x28,
+ 0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,
+ 0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x73,0x74,
+ 0x6f,0x72,0x65,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,
+ 0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x73,0x49,0x6e,0x76,0x65,
+ 0x72,0x74,0x65,0x64,0x4d,0x6f,0x64,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,
+ 0x6d,0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x62,0x72,0x6f,0x77,0x73,0x65,0x72,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x73,0x53,0x65,0x72,0x76,0x65,0x72,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x54,0x61,0x62,0x28,0x27,0x73,0x74,0x6f,0x72,
+ 0x65,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x69,0x6e,0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x28,
+ 0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x69,0x6e,0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,0x65,0x6e,
+ 0x74,0x73,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x73,0x65,0x61,0x72,
+ 0x63,0x68,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,
+ 0x6f,0x64,0x79,0x5f,0x72,0x65,0x73,0x69,0x7a,0x65,0x28,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x2f,0x4d,0x53,0x49,0x45,0x2f,0x2e,0x74,0x65,0x73,
+ 0x74,0x28,0x6e,0x61,0x76,0x69,0x67,0x61,0x74,0x6f,0x72,0x2e,0x75,0x73,0x65,0x72,
+ 0x41,0x67,0x65,0x6e,0x74,0x29,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x74,0x53,0x69,0x7a,
+ 0x65,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x2f,0x2f,0x20,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x0d,0x0a,0x2f,0x2f,0x20,0x74,0x61,0x62,0x20,0x31,0x0d,0x0a,0x0d,0x0a,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x42,0x72,0x6f,0x77,0x73,0x65,0x72,0x28,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x6e,0x70,0x75,0x74,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x6c,0x6f,0x63,0x61,
+ 0x74,0x69,0x6f,0x6e,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x72,0x61,0x6d,0x65,
+ 0x73,0x5b,0x30,0x5d,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
+ 0x69,0x6e,0x70,0x75,0x74,0x2e,0x76,0x61,0x6c,0x75,0x65,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x70,0x75,0x74,0x5f,0x6b,0x65,0x79,
+ 0x70,0x72,0x65,0x73,0x73,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x65,0x2e,0x6b,0x65,0x79,0x43,0x6f,0x64,0x65,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x31,0x33,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x42,0x72,0x6f,0x77,
+ 0x73,0x65,0x72,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x75,0x74,0x74,0x6f,0x6e,0x5f,0x63,0x6c,0x69,
+ 0x63,0x6b,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x42,0x72,0x6f,0x77,0x73,
+ 0x65,0x72,0x28,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,
+ 0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x62,0x72,0x6f,0x77,0x73,0x65,0x72,0x5f,0x6c,0x6f,0x61,0x64,0x28,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,0x75,0x70,0x64,0x61,0x74,0x65,0x20,0x74,0x68,
+ 0x65,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x62,0x6f,0x78,0x20,0x2a,0x2f,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x22,
+ 0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2a,0x20,0x73,0x6f,0x6d,0x65,0x74,
+ 0x69,0x6d,0x65,0x73,0x20,0x49,0x45,0x20,0x73,0x65,0x65,0x6d,0x73,0x20,0x74,0x6f,
+ 0x20,0x66,0x69,0x72,0x65,0x20,0x74,0x68,0x69,0x73,0x20,0x61,0x66,0x74,0x65,0x72,
+ 0x20,0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x68,0x61,0x73,0x20,0x62,0x65,0x65,
+ 0x6e,0x20,0x72,0x65,0x6d,0x6f,0x76,0x65,0x64,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x69,0x6e,0x70,0x75,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x6e,0x70,0x75,0x74,0x2e,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,
+ 0x66,0x72,0x61,0x6d,0x65,0x73,0x5b,0x30,0x5d,0x2e,0x6c,0x6f,0x63,0x61,0x74,0x69,
+ 0x6f,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,
+ 0x2f,0x20,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,
+ 0x0a,0x2f,0x2f,0x20,0x74,0x61,0x62,0x20,0x32,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,
+ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x63,0x72,0x65,0x61,0x74,0x65,0x4c,0x69,0x6e,0x6b,0x28,0x66,0x69,0x6c,0x65,
+ 0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x69,0x6e,0x6b,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,
+ 0x61,0x22,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x75,0x72,
+ 0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x61,0x6c,0x6c,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x20,0x2b,0x20,0x22,0x2e,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x68,0x74,0x6d,0x6c,0x3f,
+ 0x22,0x20,0x2b,0x20,0x6c,0x69,0x6e,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,
+ 0x61,0x6c,0x6c,0x20,0x3d,0x20,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x67,0x65,0x74,0x28,0x27,0x22,0x20,0x2b,0x20,0x66,0x69,0x6c,0x65,0x20,
+ 0x2b,0x20,0x22,0x27,0x2c,0x20,0x22,0x20,0x2b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x2b,
+ 0x20,0x22,0x29,0x3b,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,0x74,
+ 0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x66,0x69,
+ 0x6c,0x65,0x20,0x2b,0x20,0x22,0x2e,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x2e,0x68,0x74,0x6d,0x6c,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,
+ 0x6c,0x6c,0x20,0x3d,0x20,0x22,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x67,0x65,0x74,0x28,0x27,0x22,0x20,0x2b,0x20,0x66,0x69,0x6c,0x65,0x20,0x2b,
+ 0x20,0x22,0x27,0x29,0x3b,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x65,0x78,
+ 0x74,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x6b,0x2e,0x73,0x65,0x74,0x41,0x74,0x74,0x72,
+ 0x69,0x62,0x75,0x74,0x65,0x28,0x27,0x68,0x72,0x65,0x66,0x27,0x2c,0x20,0x27,0x6a,
+ 0x61,0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x3a,0x27,0x20,0x2b,0x20,0x63,0x61,
+ 0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6c,0x69,0x6e,0x6b,0x2e,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,0x65,
+ 0x28,0x74,0x65,0x78,0x74,0x29,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x6c,0x69,0x6e,0x6b,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,
+ 0x53,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x63,0x63,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x63,0x68,0x65,0x63,
+ 0x6b,0x62,0x6f,0x78,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,
+ 0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x20,0x3d,0x20,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x2e,0x63,0x68,0x65,0x63,
+ 0x6b,0x65,0x64,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,
+ 0x63,0x63,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x63,0x20,0x3d,0x20,
+ 0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x20,0x63,0x63,0x29,0x20,0x7b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,
+ 0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x20,0x30,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x22,0x4e,0x6f,0x20,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,
+ 0x20,0x66,0x6f,0x75,0x6e,0x64,0x2e,0x22,0x3b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,
+ 0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x62,0x6f,
+ 0x64,0x79,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,
+ 0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x22,0x73,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,0x79,0x22,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x28,0x74,0x62,0x6f,0x64,0x79,0x2e,0x68,0x61,
+ 0x73,0x43,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x28,0x29,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x62,0x6f,0x64,0x79,0x2e,0x72,0x65,0x6d,0x6f,
+ 0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x74,0x62,0x6f,0x64,0x79,0x2e,0x66,0x69,
+ 0x72,0x73,0x74,0x43,0x68,0x69,0x6c,0x64,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x20,
+ 0x3d,0x20,0x7b,0x20,0x66,0x69,0x6c,0x65,0x73,0x3a,0x30,0x2c,0x20,0x73,0x74,0x61,
+ 0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x3a,0x30,0x2c,0x20,0x65,0x78,0x65,0x63,0x75,
+ 0x74,0x65,0x64,0x3a,0x30,0x2c,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x3a,
+ 0x30,0x2c,0x20,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x3a,0x30,0x20,0x7d,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x73,0x20,0x3d,0x20,0x5b,0x5d,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x66,0x69,0x6c,0x65,0x20,0x69,
+ 0x6e,0x20,0x63,0x63,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,
+ 0x65,0x73,0x2e,0x70,0x75,0x73,0x68,0x28,0x66,0x69,0x6c,0x65,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x66,0x69,0x6c,0x65,0x73,0x2e,0x73,0x6f,0x72,
+ 0x74,0x28,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x6f,
+ 0x77,0x43,0x6f,0x75,0x6e,0x74,0x65,0x72,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x66,0x20,0x3d,0x20,0x30,0x3b,
+ 0x20,0x66,0x20,0x3c,0x20,0x66,0x69,0x6c,0x65,0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x3b,0x20,0x66,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,
+ 0x69,0x6c,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x73,0x5b,0x66,0x5d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,
+ 0x62,0x65,0x72,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x75,
+ 0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,0x20,0x30,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x75,0x6d,0x5f,0x65,
+ 0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x20,0x3d,0x20,
+ 0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,
+ 0x65,0x43,0x43,0x20,0x3d,0x20,0x63,0x63,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,
+ 0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x43,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,
+ 0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,
+ 0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,
+ 0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x20,0x3d,0x20,0x6e,0x75,0x6c,
+ 0x6c,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x69,0x6c,0x65,
+ 0x43,0x43,0x2e,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,
+ 0x69,0x6f,0x6e,0x61,0x6c,0x73,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x43,0x2e,
+ 0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x6c,
+ 0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,0x20,0x30,0x3b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,
+ 0x74,0x68,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x2b,0x2b,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,
+ 0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x43,0x43,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,
+ 0x6d,0x62,0x65,0x72,0x5d,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,
+ 0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,
+ 0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x3d,0x20,0x30,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,
+ 0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x30,0x20,0x26,0x26,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,
+ 0x6e,0x61,0x6c,0x73,0x20,0x26,0x26,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,
+ 0x6e,0x61,0x6c,0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x5d,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x75,0x72,
+ 0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,
+ 0x6e,0x64,0x20,0x3d,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,
+ 0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x5d,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x69,0x66,0x20,0x28,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,
+ 0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x21,0x3d,0x3d,0x20,0x30,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,
+ 0x74,0x69,0x6e,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x7c,0x7c,0x20,
+ 0x6e,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x2e,0x70,0x75,0x73,0x68,0x28,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,
+ 0x65,0x72,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x6e,0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,
+ 0x64,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,
+ 0x6e,0x74,0x73,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,
+ 0x61,0x67,0x65,0x20,0x3d,0x20,0x28,0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,
+ 0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x20,0x3f,0x20,0x30,
+ 0x20,0x3a,0x20,0x70,0x61,0x72,0x73,0x65,0x49,0x6e,0x74,0x28,0x31,0x30,0x30,0x20,
+ 0x2a,0x20,0x6e,0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x2f,
+ 0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x29,
+ 0x20,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,
+ 0x6f,0x77,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,
+ 0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x72,0x22,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x2e,0x63,0x6c,0x61,0x73,
+ 0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x28,0x20,0x72,0x6f,0x77,0x43,0x6f,0x75,
+ 0x6e,0x74,0x65,0x72,0x2b,0x2b,0x20,0x25,0x20,0x32,0x20,0x3d,0x3d,0x20,0x30,0x20,
+ 0x3f,0x20,0x22,0x6f,0x64,0x64,0x22,0x20,0x3a,0x20,0x22,0x65,0x76,0x65,0x6e,0x22,
+ 0x20,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,
+ 0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x64,
+ 0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x63,0x6c,
+ 0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x6c,0x65,0x66,0x74,0x43,
+ 0x6f,0x6c,0x75,0x6d,0x6e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x69,0x6e,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x63,0x72,0x65,0x61,0x74,0x65,0x4c,0x69,0x6e,0x6b,0x28,0x66,0x69,
+ 0x6c,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,
+ 0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x6c,0x69,0x6e,0x6b,0x29,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x63,0x65,0x6c,0x6c,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,
+ 0x3d,0x20,0x27,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,
+ 0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,0x65,0x28,0x6e,0x75,0x6d,0x5f,0x73,
+ 0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,
+ 0x64,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,
+ 0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,
+ 0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x63,
+ 0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x6e,0x75,0x6d,0x65,
+ 0x72,0x69,0x63,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,
+ 0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,
+ 0x6f,0x64,0x65,0x28,0x6e,0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,
+ 0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,
+ 0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x6e,0x65,0x77,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x74,0x64,0x20,0x63,0x6f,0x6e,0x74,0x61,0x69,
+ 0x6e,0x69,0x6e,0x67,0x20,0x61,0x20,0x62,0x61,0x72,0x20,0x67,0x72,0x61,0x70,0x68,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x28,0x22,0x74,0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x63,0x65,0x6c,0x6c,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,
+ 0x20,0x27,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x3d,
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,
+ 0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x64,0x69,0x76,0x22,0x29,0x2c,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x64,0x69,0x76,0x22,0x29,
+ 0x2c,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x20,0x3d,
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,
+ 0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x73,0x70,0x61,0x6e,0x22,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x63,
+ 0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x22,0x70,0x63,0x74,0x47,
+ 0x72,0x61,0x70,0x68,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x28,0x20,
+ 0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x30,0x20,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,
+ 0x61,0x6d,0x65,0x20,0x3d,0x20,0x22,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x22,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,0x61,0x70,
+ 0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,
+ 0x65,0x28,0x22,0x4e,0x2f,0x41,0x22,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,
+ 0x61,0x6d,0x65,0x20,0x3d,0x20,0x22,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x22,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,
+ 0x64,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x77,0x69,0x64,0x74,0x68,0x20,0x3d,0x20,
+ 0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x2b,0x20,0x22,0x70,0x78,
+ 0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,
+ 0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,
+ 0x6f,0x64,0x65,0x28,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x2b,
+ 0x20,0x27,0x25,0x27,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,
+ 0x65,0x20,0x3d,0x20,0x22,0x70,0x63,0x74,0x22,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,
+ 0x68,0x69,0x6c,0x64,0x28,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,
+ 0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,
+ 0x43,0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x72,0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,
+ 0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,
+ 0x6c,0x75,0x6d,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,
+ 0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x22,0x74,0x64,
+ 0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,
+ 0x76,0x61,0x72,0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6d,
+ 0x69,0x73,0x73,0x69,0x6e,0x67,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,
+ 0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x69,0x20,0x21,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,
+ 0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,
+ 0x65,0x28,0x22,0x2c,0x20,0x22,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6c,0x69,
+ 0x6e,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x63,0x72,0x65,0x61,0x74,0x65,0x4c,0x69,0x6e,0x6b,0x28,0x66,0x69,0x6c,0x65,0x2c,
+ 0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x5b,0x69,0x5d,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x65,0x6c,0x6c,0x2e,0x61,0x70,0x70,0x65,
+ 0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x6c,0x69,0x6e,0x6b,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,
+ 0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,
+ 0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x74,0x62,0x6f,0x64,0x79,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,
+ 0x43,0x68,0x69,0x6c,0x64,0x28,0x72,0x6f,0x77,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x66,0x69,0x6c,0x65,0x73,
+ 0x27,0x5d,0x20,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x6f,0x74,0x61,
+ 0x6c,0x73,0x5b,0x27,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x27,0x5d,
+ 0x20,0x2b,0x3d,0x20,0x6e,0x75,0x6d,0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,
+ 0x74,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,
+ 0x27,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x27,0x5d,0x20,0x2b,0x3d,0x20,0x6e,
+ 0x75,0x6d,0x5f,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x27,0x5d,0x20,0x2b,0x3d,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,
+ 0x67,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x28,0x20,0x6e,0x75,0x6d,
+ 0x5f,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,0x3d,0x3d,0x3d,0x20,
+ 0x30,0x20,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,
+ 0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x73,0x6b,0x69,0x70,0x70,0x65,0x64,0x27,0x5d,
+ 0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x2f,0x2f,0x20,0x77,0x72,0x69,0x74,0x65,0x20,0x74,0x6f,0x74,0x61,0x6c,
+ 0x73,0x20,0x64,0x61,0x74,0x61,0x20,0x69,0x6e,0x74,0x6f,0x20,0x73,0x75,0x6d,0x6d,
+ 0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x72,0x6f,0x77,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,
+ 0x79,0x49,0x64,0x28,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,
+ 0x6c,0x73,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,
+ 0x72,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x74,0x64,0x73,0x20,0x3d,0x20,0x74,0x72,0x2e,0x67,0x65,0x74,0x45,0x6c,
+ 0x65,0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,
+ 0x22,0x74,0x64,0x22,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x74,0x64,0x73,0x5b,0x30,0x5d,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x22,0x73,0x70,0x61,
+ 0x6e,0x22,0x29,0x5b,0x31,0x5d,0x2e,0x66,0x69,0x72,0x73,0x74,0x43,0x68,0x69,0x6c,
+ 0x64,0x2e,0x6e,0x6f,0x64,0x65,0x56,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x74,0x6f,
+ 0x74,0x61,0x6c,0x73,0x5b,0x27,0x66,0x69,0x6c,0x65,0x73,0x27,0x5d,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x64,0x73,0x5b,0x31,0x5d,0x2e,0x66,
+ 0x69,0x72,0x73,0x74,0x43,0x68,0x69,0x6c,0x64,0x2e,0x6e,0x6f,0x64,0x65,0x56,0x61,
+ 0x6c,0x75,0x65,0x20,0x3d,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x73,0x74,
+ 0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x27,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x74,0x64,0x73,0x5b,0x32,0x5d,0x2e,0x66,0x69,0x72,0x73,
+ 0x74,0x43,0x68,0x69,0x6c,0x64,0x2e,0x6e,0x6f,0x64,0x65,0x56,0x61,0x6c,0x75,0x65,
+ 0x20,0x3d,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x65,0x78,0x65,0x63,0x75,
+ 0x74,0x65,0x64,0x27,0x5d,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,
+ 0x20,0x70,0x61,0x72,0x73,0x65,0x49,0x6e,0x74,0x28,0x74,0x6f,0x74,0x61,0x6c,0x73,
+ 0x5b,0x27,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x27,0x5d,0x20,0x2f,0x20,0x28,
+ 0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x66,0x69,0x6c,0x65,0x73,0x27,0x5d,
+ 0x20,0x2d,0x20,0x74,0x6f,0x74,0x61,0x6c,0x73,0x5b,0x27,0x73,0x6b,0x69,0x70,0x70,
+ 0x65,0x64,0x27,0x5d,0x20,0x29,0x20,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x28,0x20,0x69,0x73,0x4e,0x61,0x4e,0x28,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x29,0x20,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x64,0x73,0x5b,
+ 0x33,0x5d,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,
+ 0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x22,0x73,0x70,0x61,0x6e,0x22,0x29,0x5b,
+ 0x30,0x5d,0x2e,0x66,0x69,0x72,0x73,0x74,0x43,0x68,0x69,0x6c,0x64,0x2e,0x6e,0x6f,
+ 0x64,0x65,0x56,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x20,0x2b,0x20,0x27,0x25,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x74,0x64,0x73,0x5b,0x33,0x5d,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x22,
+ 0x64,0x69,0x76,0x22,0x29,0x5b,0x31,0x5d,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x77,
+ 0x69,0x64,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,
+ 0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x61,0x70,0x70,0x65,0x6e,0x64,0x4d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x68,0x65,0x61,0x64,0x65,0x72,0x52,0x6f,0x77,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x68,0x65,0x61,0x64,0x65,0x72,0x52,
+ 0x6f,0x77,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x69,0x73,
+ 0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x28,0x27,0x74,0x68,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,
+ 0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,0x2e,0x69,0x64,0x20,0x3d,
+ 0x20,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,0x27,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,
+ 0x65,0x72,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x27,
+ 0x3c,0x61,0x62,0x62,0x72,0x20,0x74,0x69,0x74,0x6c,0x65,0x3d,0x22,0x4c,0x69,0x73,
+ 0x74,0x20,0x6f,0x66,0x20,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x73,0x20,
+ 0x6d,0x69,0x73,0x73,0x65,0x64,0x20,0x64,0x75,0x72,0x69,0x6e,0x67,0x20,0x65,0x78,
+ 0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x22,0x3e,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,
+ 0x3c,0x2f,0x61,0x62,0x62,0x72,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x68,0x65,0x61,
+ 0x64,0x65,0x72,0x52,0x6f,0x77,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,
+ 0x6c,0x64,0x28,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,
+ 0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x65,0x6d,0x70,0x74,0x79,
+ 0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,
+ 0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x27,0x74,0x64,0x27,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x65,0x6d,0x70,0x74,0x79,0x2e,0x69,0x64,0x20,0x3d,0x20,0x27,
+ 0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x65,0x6c,0x6c,0x27,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x6f,0x74,0x61,0x6c,0x73,0x2e,0x61,
+ 0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x65,0x6d,0x70,0x74,0x79,
+ 0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,
+ 0x6f,0x76,0x65,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,
+ 0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x69,0x73,0x73,
+ 0x69,0x6e,0x67,0x4e,0x6f,0x64,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,
+ 0x69,0x6e,0x67,0x4e,0x6f,0x64,0x65,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x48,0x65,0x61,0x64,0x65,0x72,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x4e,0x6f,
+ 0x64,0x65,0x2e,0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,0x65,
+ 0x6d,0x6f,0x76,0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x6d,0x69,0x73,0x73,0x69,0x6e,
+ 0x67,0x4e,0x6f,0x64,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x4e,0x6f,0x64,0x65,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x65,0x6c,0x6c,0x27,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x4e,0x6f,0x64,0x65,0x2e,
+ 0x70,0x61,0x72,0x65,0x6e,0x74,0x4e,0x6f,0x64,0x65,0x2e,0x72,0x65,0x6d,0x6f,0x76,
+ 0x65,0x43,0x68,0x69,0x6c,0x64,0x28,0x6d,0x69,0x73,0x73,0x69,0x6e,0x67,0x4e,0x6f,
+ 0x64,0x65,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,
+ 0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x28,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,
+ 0x72,0x61,0x74,0x69,0x6f,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x62,0x65,0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,
+ 0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,
+ 0x49,0x64,0x28,0x27,0x63,0x68,0x65,0x63,0x6b,0x62,0x6f,0x78,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,
+ 0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x20,0x3d,0x20,0x63,0x68,0x65,0x63,0x6b,
+ 0x62,0x6f,0x78,0x2e,0x63,0x68,0x65,0x63,0x6b,0x65,0x64,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x73,0x68,0x6f,0x77,0x4d,0x69,0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,
+ 0x6d,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x61,0x70,0x70,0x65,0x6e,0x64,0x4d,0x69,
+ 0x73,0x73,0x69,0x6e,0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x28,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x72,0x65,0x6d,0x6f,0x76,0x65,0x4d,0x69,0x73,0x73,0x69,0x6e,
+ 0x67,0x43,0x6f,0x6c,0x75,0x6d,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x75,0x6d,
+ 0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x2c,
+ 0x20,0x35,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x74,0x72,0x75,0x65,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,
+ 0x20,0x74,0x61,0x62,0x20,0x33,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x6d,0x61,
+ 0x6b,0x65,0x54,0x61,0x62,0x6c,0x65,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,0x20,0x5f,0x24,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x46,0x69,0x6c,
+ 0x65,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x73,
+ 0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x73,0x6f,0x75,0x72,
+ 0x63,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x2f,0x2f,0x20,0x74,0x68,0x69,0x73,
+ 0x20,0x63,0x61,0x6e,0x20,0x68,0x61,0x70,0x70,0x65,0x6e,0x20,0x69,0x66,0x20,0x74,
+ 0x68,0x65,0x72,0x65,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,
+ 0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,
+ 0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x20,0x66,0x69,0x6c,0x65,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x21,0x20,0x6c,0x69,0x6e,0x65,0x73,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6c,0x69,0x6e,0x65,0x73,0x20,0x3d,0x20,
+ 0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x72,0x6f,0x77,0x73,0x20,0x3d,0x20,0x5b,0x27,0x3c,0x74,0x61,0x62,0x6c,
+ 0x65,0x20,0x69,0x64,0x3d,0x22,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x6c,
+ 0x65,0x22,0x3e,0x27,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x20,
+ 0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x6c,0x65,0x48,0x54,
+ 0x4d,0x4c,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x75,0x72,0x72,0x65,
+ 0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,
+ 0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x6f,0x69,0x6e,0x54,0x61,0x62,0x6c,0x65,0x52,0x6f,0x77,
+ 0x73,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x6c,0x65,
+ 0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x72,0x6f,0x77,0x73,0x2e,0x6a,0x6f,0x69,0x6e,
+ 0x28,0x27,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,
+ 0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,0x65,0x6e,
+ 0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,
+ 0x2c,0x20,0x36,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2a,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x6d,0x61,0x79,0x20,0x62,0x65,0x20,
+ 0x61,0x20,0x6c,0x6f,0x6e,0x67,0x20,0x64,0x65,0x6c,0x61,0x79,0x2c,0x20,0x73,0x6f,
+ 0x20,0x73,0x65,0x74,0x20,0x61,0x20,0x74,0x69,0x6d,0x65,0x6f,0x75,0x74,0x20,0x6f,
+ 0x66,0x20,0x31,0x30,0x30,0x20,0x6d,0x73,0x20,0x74,0x6f,0x20,0x6d,0x61,0x6b,0x65,
+ 0x20,0x73,0x75,0x72,0x65,0x20,0x74,0x68,0x65,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,
+ 0x69,0x73,0x70,0x6c,0x61,0x79,0x20,0x69,0x73,0x20,0x75,0x70,0x64,0x61,0x74,0x65,
+ 0x64,0x2e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2a,0x2f,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x61,0x70,0x70,0x65,0x6e,
+ 0x64,0x54,0x61,0x62,0x6c,0x65,0x2c,0x20,0x31,0x30,0x30,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,
+ 0x20,0x61,0x70,0x70,0x65,0x6e,0x64,0x54,0x61,0x62,0x6c,0x65,0x28,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,
+ 0x44,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,
+ 0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,
+ 0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x2e,0x69,0x6e,0x6e,0x65,0x72,
+ 0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x74,0x61,0x62,0x6c,0x65,0x48,0x54,0x4d,0x4c,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,
+ 0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2c,0x20,0x38,0x30,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,
+ 0x75,0x74,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x63,
+ 0x72,0x6f,0x6c,0x6c,0x54,0x6f,0x4c,0x69,0x6e,0x65,0x2c,0x20,0x30,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,
+ 0x28,0x69,0x20,0x3c,0x20,0x6c,0x69,0x6e,0x65,0x73,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6c,0x69,
+ 0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6c,0x69,0x6e,
+ 0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x3d,0x3d,0x3d,0x20,0x63,0x75,0x72,0x72,
+ 0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,
+ 0x64,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x75,0x72,0x72,
+ 0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,
+ 0x64,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x63,0x75,0x72,0x72,
+ 0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x45,0x6e,
+ 0x64,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x20,0x26,0x26,0x20,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x2e,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,
+ 0x20,0x26,0x26,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x2e,0x63,0x6f,0x6e,
+ 0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,
+ 0x6d,0x62,0x65,0x72,0x5d,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,
+ 0x61,0x6c,0x45,0x6e,0x64,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x2e,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x73,0x5b,0x6c,0x69,
+ 0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x6f,0x77,
+ 0x20,0x3d,0x20,0x27,0x3c,0x74,0x72,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,
+ 0x73,0x3d,0x22,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,0x27,0x20,0x2b,0x20,
+ 0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x2b,0x20,0x27,0x3c,0x2f,
+ 0x74,0x64,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,
+ 0x69,0x6d,0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x3d,0x20,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,
+ 0x65,0x72,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x69,
+ 0x6d,0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x21,0x3d,0x3d,0x20,
+ 0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x26,0x26,0x20,0x74,0x69,0x6d,
+ 0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x20,0x21,0x3d,0x3d,0x20,0x6e,
+ 0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,
+ 0x20,0x28,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,
+ 0x6f,0x6e,0x61,0x6c,0x45,0x6e,0x64,0x20,0x21,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,
+ 0x20,0x27,0x3c,0x74,0x64,0x20,0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x79,0x20,0x6e,
+ 0x75,0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,
+ 0x69,0x66,0x20,0x28,0x74,0x69,0x6d,0x65,0x73,0x45,0x78,0x65,0x63,0x75,0x74,0x65,
+ 0x64,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x74,0x64,0x20,
+ 0x63,0x6c,0x61,0x73,0x73,0x3d,0x22,0x72,0x20,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,
+ 0x22,0x20,0x69,0x64,0x3d,0x22,0x6c,0x69,0x6e,0x65,0x2d,0x27,0x20,0x2b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x4e,0x75,0x6d,0x62,0x65,0x72,0x20,0x2b,0x20,0x27,0x22,0x3e,0x27,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x74,0x64,0x20,0x63,0x6c,
+ 0x61,0x73,0x73,0x3d,0x22,0x67,0x20,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x22,0x3e,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x74,0x69,0x6d,0x65,0x73,0x45,
+ 0x78,0x65,0x63,0x75,0x74,0x65,0x64,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x2f,0x74,0x64,0x3e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,
+ 0x20,0x27,0x3c,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x64,0x3e,0x27,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,
+ 0x20,0x27,0x3c,0x74,0x64,0x3e,0x3c,0x70,0x72,0x65,0x3e,0x27,0x20,0x2b,0x20,0x6c,
+ 0x69,0x6e,0x65,0x73,0x5b,0x69,0x5d,0x20,0x2b,0x20,0x27,0x3c,0x2f,0x70,0x72,0x65,
+ 0x3e,0x3c,0x2f,0x74,0x64,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,
+ 0x77,0x20,0x2b,0x3d,0x20,0x27,0x3c,0x2f,0x74,0x72,0x3e,0x27,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x72,0x6f,0x77,0x20,0x2b,0x3d,0x20,0x27,0x5c,0x6e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x72,0x6f,0x77,0x73,0x5b,0x6c,0x69,0x6e,0x65,0x4e,0x75,
+ 0x6d,0x62,0x65,0x72,0x5d,0x20,0x3d,0x20,0x72,0x6f,0x77,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x72,
+ 0x6f,0x77,0x73,0x5b,0x69,0x20,0x2b,0x20,0x31,0x5d,0x20,0x3d,0x20,0x27,0x3c,0x2f,
+ 0x74,0x61,0x62,0x6c,0x65,0x3e,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x50,0x72,0x6f,0x67,
+ 0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,0x65,0x72,0x63,0x65,
+ 0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,
+ 0x72,0x2c,0x20,0x34,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x65,0x74,0x54,0x69,
+ 0x6d,0x65,0x6f,0x75,0x74,0x28,0x6a,0x6f,0x69,0x6e,0x54,0x61,0x62,0x6c,0x65,0x52,
+ 0x6f,0x77,0x73,0x2c,0x20,0x30,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x73,0x63,0x72,0x6f,0x6c,0x6c,0x54,0x6f,0x4c,0x69,0x6e,0x65,0x28,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x27,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,
+ 0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x64,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x3d,
+ 0x3d,0x20,0x31,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,
+ 0x73,0x63,0x72,0x6f,0x6c,0x6c,0x54,0x6f,0x70,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x65,0x6c,0x6c,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x6c,0x69,0x6e,0x65,0x2d,0x27,0x20,0x2b,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,
+ 0x6e,0x74,0x4c,0x69,0x6e,0x65,0x29,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x2f,0x2f,0x20,0x74,0x68,0x69,0x73,0x20,0x6d,0x69,0x67,0x68,0x74,0x20,0x6e,0x6f,
+ 0x74,0x20,0x62,0x65,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x69,0x66,0x20,0x74,0x68,
+ 0x65,0x72,0x65,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,0x20,
+ 0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x20,
+ 0x4a,0x61,0x76,0x61,0x53,0x63,0x72,0x69,0x70,0x74,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x63,0x65,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x64,0x69,0x76,0x4f,0x66,0x66,0x73,0x65,0x74,
+ 0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,0x69,
+ 0x6e,0x64,0x50,0x6f,0x73,0x28,0x64,0x69,0x76,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x65,0x6c,0x6c,0x4f,0x66,0x66,0x73,0x65,
+ 0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x66,
+ 0x69,0x6e,0x64,0x50,0x6f,0x73,0x28,0x63,0x65,0x6c,0x6c,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x73,0x63,0x72,0x6f,0x6c,0x6c,0x54,
+ 0x6f,0x70,0x20,0x3d,0x20,0x63,0x65,0x6c,0x6c,0x4f,0x66,0x66,0x73,0x65,0x74,0x20,
+ 0x2d,0x20,0x64,0x69,0x76,0x4f,0x66,0x66,0x73,0x65,0x74,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,
+ 0x6e,0x65,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,
+ 0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x4c,0x6f,0x61,0x64,0x73,0x20,0x74,0x68,
+ 0x65,0x20,0x67,0x69,0x76,0x65,0x6e,0x20,0x66,0x69,0x6c,0x65,0x20,0x28,0x61,0x6e,
+ 0x64,0x20,0x6f,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x20,0x6c,0x69,0x6e,0x65,0x29,
+ 0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,
+ 0x61,0x62,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x67,0x65,0x74,
+ 0x28,0x66,0x69,0x6c,0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,
+ 0x69,0x6f,0x6e,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,
+ 0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,
+ 0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x73,0x6f,0x75,0x72,0x63,
+ 0x65,0x44,0x69,0x76,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,
+ 0x20,0x27,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x27,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x66,0x69,0x6c,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,
+ 0x74,0x46,0x69,0x6c,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,
+ 0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x46,0x69,0x6c,0x65,0x20,0x3d,0x3d,
+ 0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x42,0x79,0x49,0x64,0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x2e,
+ 0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x2e,0x6f,0x6e,0x63,
+ 0x6c,0x69,0x63,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x74,0x61,0x62,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x46,
+ 0x69,0x6c,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,
+ 0x72,0x72,0x65,0x6e,0x74,0x4c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,
+ 0x20,0x7c,0x7c,0x20,0x31,0x3b,0x20,0x20,0x2f,0x2f,0x20,0x77,0x68,0x65,0x6e,0x20,
+ 0x63,0x68,0x61,0x6e,0x67,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x2c,0x20,0x61,0x6c,0x77,0x61,0x79,0x73,0x20,0x73,0x63,0x72,0x6f,
+ 0x6c,0x6c,0x20,0x74,0x6f,0x20,0x74,0x6f,0x70,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x66,0x69,0x6c,0x65,0x44,0x69,0x76,0x27,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x66,0x69,0x6c,0x65,0x44,0x69,
+ 0x76,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,
+ 0x46,0x69,0x6c,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,
+ 0x61,0x74,0x65,0x53,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x20,0x35,0x30,0x29,0x3b,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x43,0x61,0x6c,0x63,
+ 0x75,0x6c,0x61,0x74,0x65,0x73,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,
+ 0x73,0x74,0x61,0x74,0x69,0x73,0x74,0x69,0x63,0x73,0x20,0x66,0x6f,0x72,0x20,0x74,
+ 0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,
+ 0x65,0x20,0x66,0x69,0x6c,0x65,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,
+ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x6f,0x75,0x72,
+ 0x63,0x65,0x54,0x61,0x62,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x21,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x63,0x75,
+ 0x72,0x72,0x65,0x6e,0x74,0x46,0x69,0x6c,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,
+ 0x67,0x72,0x65,0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x20,0x3d,0x20,0x64,0x6f,0x63,
+ 0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x4c,0x61,
+ 0x62,0x65,0x6c,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x4c,0x61,0x62,0x65,0x6c,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,
+ 0x4c,0x20,0x3d,0x20,0x27,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x69,0x6e,0x67,
+ 0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x2e,0x2e,0x2e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,
+ 0x61,0x72,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,
+ 0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x70,0x72,
+ 0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,0x2e,0x73,0x65,0x74,0x50,
+ 0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x28,0x70,0x72,0x6f,0x67,0x72,0x65,
+ 0x73,0x73,0x42,0x61,0x72,0x2c,0x20,0x32,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,
+ 0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,0x74,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x6d,0x61,0x6b,0x65,0x54,0x61,0x62,0x6c,0x65,0x2c,0x20,
+ 0x30,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,0x20,0x74,
+ 0x61,0x62,0x73,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x49,0x6e,0x69,0x74,
+ 0x69,0x61,0x6c,0x69,0x7a,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,
+ 0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x2e,0x20,0x20,0x54,0x68,0x69,0x73,0x20,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6d,0x75,0x73,0x74,0x20,0x62,0x65,0x20,
+ 0x63,0x61,0x6c,0x6c,0x65,0x64,0x20,0x77,0x68,0x65,0x6e,0x20,0x74,0x68,0x65,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x20,0x69,0x73,0x0d,0x0a,0x6c,0x6f,0x61,
+ 0x64,0x65,0x64,0x2e,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,
+ 0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,
+ 0x69,0x74,0x54,0x61,0x62,0x43,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x28,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x63,0x68,0x69,0x6c,0x64,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,
+ 0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,
+ 0x62,0x73,0x2e,0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x6c,0x65,
+ 0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x68,0x69,0x6c,0x64,0x20,0x3d,0x20,0x74,0x61,0x62,0x73,0x2e,0x63,
+ 0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,0x68,0x69,0x6c,
+ 0x64,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x31,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,
+ 0x68,0x69,0x6c,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x21,
+ 0x3d,0x3d,0x20,0x27,0x64,0x69,0x73,0x61,0x62,0x6c,0x65,0x64,0x27,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x68,0x69,0x6c,0x64,0x2e,
+ 0x6f,0x6e,0x63,0x6c,0x69,0x63,0x6b,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,
+ 0x72,0x61,0x67,0x65,0x5f,0x74,0x61,0x62,0x5f,0x63,0x6c,0x69,0x63,0x6b,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,
+ 0x61,0x67,0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x30,0x29,
+ 0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x53,0x65,0x6c,
+ 0x65,0x63,0x74,0x73,0x20,0x61,0x20,0x74,0x61,0x62,0x2e,0x0d,0x0a,0x40,0x70,0x61,
+ 0x72,0x61,0x6d,0x20,0x20,0x74,0x61,0x62,0x20,0x20,0x74,0x68,0x65,0x20,0x69,0x6e,
+ 0x74,0x65,0x67,0x65,0x72,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x6f,0x66,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x28,0x30,0x2c,0x20,0x31,0x2c,0x20,0x32,0x2c,
+ 0x20,0x6f,0x72,0x20,0x33,0x29,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x4f,0x52,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x49,0x44,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4f,0x52,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x20,0x69,
+ 0x74,0x73,0x65,0x6c,0x66,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,
+ 0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,0x28,0x74,0x61,0x62,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x79,0x70,0x65,0x6f,0x66,0x20,0x74,0x61,
+ 0x62,0x20,0x21,0x3d,0x3d,0x20,0x27,0x6e,0x75,0x6d,0x62,0x65,0x72,0x27,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x20,0x3d,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x74,0x61,0x62,0x49,0x6e,0x64,0x65,0x78,
+ 0x4f,0x66,0x28,0x74,0x61,0x62,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,
+ 0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,
+ 0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6e,0x6f,0x64,0x65,0x4c,
+ 0x69,0x73,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x4e,
+ 0x75,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x6e,0x6f,0x64,0x65,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,
+ 0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x73,0x2e,
+ 0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x74,
+ 0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6e,0x6f,
+ 0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,
+ 0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x20,
+ 0x3d,0x20,0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x69,0x74,0x65,0x6d,0x28,
+ 0x69,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x6f,0x64,
+ 0x65,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x21,0x3d,0x3d,0x20,0x31,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x74,0x69,
+ 0x6e,0x75,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x6f,0x64,0x65,0x2e,0x63,0x6c,0x61,0x73,
+ 0x73,0x4e,0x61,0x6d,0x65,0x20,0x21,0x3d,0x3d,0x20,0x27,0x64,0x69,0x73,0x61,0x62,
+ 0x6c,0x65,0x64,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x74,0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x3d,0x3d,0x20,0x74,0x61,
+ 0x62,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,
+ 0x64,0x65,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,
+ 0x73,0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x2e,
+ 0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6e,0x6f,0x64,0x65,0x4c,0x69,0x73,
+ 0x74,0x20,0x3d,0x20,0x74,0x61,0x62,0x50,0x61,0x67,0x65,0x73,0x2e,0x63,0x68,0x69,
+ 0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x74,0x61,0x62,0x4e,
+ 0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,
+ 0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x6e,0x6f,0x64,0x65,0x4c,
+ 0x69,0x73,0x74,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,0x20,0x3d,0x20,0x6e,
+ 0x6f,0x64,0x65,0x4c,0x69,0x73,0x74,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x6e,0x6f,0x64,0x65,0x2e,0x6e,
+ 0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x21,0x3d,0x3d,0x20,0x31,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x69,0x66,0x20,0x28,0x74,0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x3d,0x3d,0x20,0x74,
+ 0x61,0x62,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,
+ 0x65,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x73,
+ 0x65,0x6c,0x65,0x63,0x74,0x65,0x64,0x20,0x54,0x61,0x62,0x50,0x61,0x67,0x65,0x27,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,
+ 0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x64,0x65,
+ 0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x54,0x61,
+ 0x62,0x50,0x61,0x67,0x65,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2a,0x2a,0x0d,0x0a,0x52,0x65,
+ 0x74,0x75,0x72,0x6e,0x73,0x20,0x61,0x6e,0x20,0x69,0x6e,0x74,0x65,0x67,0x65,0x72,
+ 0x20,0x28,0x30,0x2c,0x20,0x31,0x2c,0x20,0x32,0x2c,0x20,0x6f,0x72,0x20,0x33,0x29,
+ 0x20,0x72,0x65,0x70,0x72,0x65,0x73,0x65,0x6e,0x74,0x69,0x6e,0x67,0x20,0x74,0x68,
+ 0x65,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x6f,0x66,0x20,0x61,0x20,0x67,0x69,0x76,
+ 0x65,0x6e,0x20,0x74,0x61,0x62,0x2e,0x0d,0x0a,0x40,0x70,0x61,0x72,0x61,0x6d,0x20,
+ 0x20,0x74,0x61,0x62,0x20,0x20,0x74,0x68,0x65,0x20,0x49,0x44,0x20,0x6f,0x66,0x20,
+ 0x74,0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4f,0x52,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x74,
+ 0x68,0x65,0x20,0x74,0x61,0x62,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x20,0x69,
+ 0x74,0x73,0x65,0x6c,0x66,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,
+ 0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x74,
+ 0x61,0x62,0x49,0x6e,0x64,0x65,0x78,0x4f,0x66,0x28,0x74,0x61,0x62,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x79,0x70,0x65,0x6f,0x66,0x20,0x74,
+ 0x61,0x62,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x73,0x74,0x72,0x69,0x6e,0x67,0x27,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x42,0x79,0x49,0x64,0x28,0x74,0x61,0x62,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x62,0x73,0x20,0x3d,0x20,0x64,
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x27,0x74,0x61,0x62,0x73,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x69,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x63,0x68,0x69,0x6c,0x64,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,
+ 0x61,0x62,0x4e,0x75,0x6d,0x20,0x3d,0x20,0x30,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,
+ 0x72,0x20,0x28,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x69,0x20,0x3c,0x20,0x74,0x61,
+ 0x62,0x73,0x2e,0x63,0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x6c,0x65,
+ 0x6e,0x67,0x74,0x68,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x63,0x68,0x69,0x6c,0x64,0x20,0x3d,0x20,0x74,0x61,0x62,0x73,0x2e,0x63,
+ 0x68,0x69,0x6c,0x64,0x4e,0x6f,0x64,0x65,0x73,0x2e,0x69,0x74,0x65,0x6d,0x28,0x69,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,0x68,0x69,0x6c,
+ 0x64,0x2e,0x6e,0x6f,0x64,0x65,0x54,0x79,0x70,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x31,
+ 0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x63,
+ 0x68,0x69,0x6c,0x64,0x20,0x3d,0x3d,0x3d,0x20,0x74,0x61,0x62,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x74,0x61,0x62,0x4e,0x75,0x6d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x61,0x62,0x4e,0x75,0x6d,0x2b,0x2b,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x2f,
+ 0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x49,0x46,0x20,
+ 0x30,0x0d,0x0a,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x22,0x54,0x61,0x62,0x20,
+ 0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x22,0x3b,0x0d,0x0a,0x2f,0x2f,0x23,
+ 0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,0x45,0x5f,0x45,0x4e,0x44,0x49,0x46,
+ 0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x74,0x61,0x62,0x5f,0x63,
+ 0x6c,0x69,0x63,0x6b,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,
+ 0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x74,0x61,0x72,0x67,0x65,
+ 0x74,0x3b,0x0d,0x0a,0x2f,0x2f,0x23,0x4a,0x53,0x43,0x4f,0x56,0x45,0x52,0x41,0x47,
+ 0x45,0x5f,0x49,0x46,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x65,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x20,0x3d,0x20,0x65,
+ 0x2e,0x74,0x61,0x72,0x67,0x65,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,
+ 0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,
+ 0x2e,0x65,0x76,0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x49,0x45,0x0d,0x0a,0x20,0x20,0x20,0x20,0x74,0x61,0x72,0x67,0x65,0x74,
+ 0x20,0x3d,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x65,0x76,0x65,0x6e,0x74,0x2e,
+ 0x73,0x72,0x63,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x7d,
+ 0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x63,
+ 0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x73,0x65,
+ 0x6c,0x65,0x63,0x74,0x65,0x64,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,
+ 0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x73,0x65,0x74,0x54,0x69,0x6d,0x65,0x6f,0x75,
+ 0x74,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,
+ 0x64,0x20,0x3d,0x3d,0x3d,0x20,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,
+ 0x62,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x74,0x62,0x6f,0x64,0x79,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x22,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x62,0x6f,0x64,0x79,0x22,0x29,
+ 0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x28,
+ 0x74,0x62,0x6f,0x64,0x79,0x2e,0x68,0x61,0x73,0x43,0x68,0x69,0x6c,0x64,0x4e,0x6f,
+ 0x64,0x65,0x73,0x28,0x29,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x74,0x62,0x6f,0x64,0x79,0x2e,0x72,0x65,0x6d,0x6f,0x76,0x65,0x43,0x68,
+ 0x69,0x6c,0x64,0x28,0x74,0x62,0x6f,0x64,0x79,0x2e,0x66,0x69,0x72,0x73,0x74,0x43,
+ 0x68,0x69,0x6c,0x64,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,
+ 0x20,0x69,0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x20,0x3d,
+ 0x3d,0x3d,0x20,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x73,0x6f,0x75,
+ 0x72,0x63,0x65,0x44,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,
+ 0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,
+ 0x28,0x27,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x44,0x69,0x76,0x2e,
+ 0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,0x27,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x6c,0x65,0x63,0x74,0x54,0x61,0x62,
+ 0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,
+ 0x66,0x20,0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x20,0x3d,0x3d,0x3d,
+ 0x20,0x27,0x73,0x75,0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x27,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x75,
+ 0x6d,0x6d,0x61,0x72,0x79,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x69,0x66,0x20,
+ 0x28,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x20,0x3d,0x3d,0x3d,0x20,0x27,
+ 0x73,0x6f,0x75,0x72,0x63,0x65,0x54,0x61,0x62,0x27,0x29,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x72,0x65,0x63,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x65,0x53,0x6f,0x75,0x72,0x63,
+ 0x65,0x54,0x61,0x62,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x65,0x6e,0x64,
+ 0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,
+ 0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x2c,
+ 0x20,0x35,0x30,0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,
+ 0x20,0x70,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x20,0x62,0x61,0x72,0x0d,0x0a,0x0d,
+ 0x0a,0x76,0x61,0x72,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,0x72,
+ 0x20,0x3d,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x6e,0x69,0x74,0x3a,0x20,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,
+ 0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x20,0x3d,0x20,0x30,0x3b,0x0d,
+ 0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,0x2a,0x20,0x64,0x6f,0x69,0x6e,0x67,0x20,
+ 0x74,0x68,0x69,0x73,0x20,0x76,0x69,0x61,0x20,0x4a,0x61,0x76,0x61,0x53,0x63,0x72,
+ 0x69,0x70,0x74,0x20,0x63,0x72,0x61,0x73,0x68,0x65,0x73,0x20,0x53,0x61,0x66,0x61,
+ 0x72,0x69,0x20,0x2a,0x2f,0x0d,0x0a,0x2f,0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x3d,0x20,0x64,0x6f,
+ 0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x28,0x27,0x64,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x63,0x6c,0x61,0x73,0x73,
+ 0x4e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x27,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,
+ 0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x47,
+ 0x72,0x61,0x70,0x68,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,
+ 0x28,0x27,0x64,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x65,0x64,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,0x6d,0x65,0x20,
+ 0x3d,0x20,0x27,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x61,0x70,0x70,0x65,0x6e,
+ 0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x20,0x3d,0x20,
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,0x61,0x74,0x65,0x45,
+ 0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x27,0x73,0x70,0x61,0x6e,0x27,0x29,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x70,0x63,0x74,0x2e,0x63,0x6c,0x61,0x73,0x73,0x4e,0x61,
+ 0x6d,0x65,0x20,0x3d,0x20,0x27,0x70,0x63,0x74,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,
+ 0x68,0x69,0x6c,0x64,0x28,0x70,0x63,0x74,0x29,0x3b,0x0d,0x0a,0x2a,0x2f,0x0d,0x0a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,0x42,0x61,
+ 0x72,0x2e,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,
+ 0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x0d,0x0a,0x20,0x20,0x73,0x65,0x74,
+ 0x50,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x3a,0x20,0x66,0x75,0x6e,0x63,
+ 0x74,0x69,0x6f,0x6e,0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2c,0x20,0x70,0x65,
+ 0x72,0x63,0x65,0x6e,0x74,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,0x70,0x65,0x72,0x63,0x65,0x6e,
+ 0x74,0x61,0x67,0x65,0x20,0x3d,0x20,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,0x61,0x67,
+ 0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x50,0x72,0x6f,0x67,0x72,0x65,0x73,0x73,
+ 0x42,0x61,0x72,0x2e,0x5f,0x75,0x70,0x64,0x61,0x74,0x65,0x28,0x65,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x7d,0x2c,0x0d,0x0a,0x20,0x20,0x5f,
+ 0x75,0x70,0x64,0x61,0x74,0x65,0x3a,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,
+ 0x28,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x20,0x3d,0x20,
+ 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,
+ 0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x64,0x69,
+ 0x76,0x27,0x29,0x2e,0x69,0x74,0x65,0x6d,0x28,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x65,0x64,0x20,0x3d,0x20,
+ 0x70,0x63,0x74,0x47,0x72,0x61,0x70,0x68,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,
+ 0x65,0x6e,0x74,0x73,0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x64,
+ 0x69,0x76,0x27,0x29,0x2e,0x69,0x74,0x65,0x6d,0x28,0x30,0x29,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x63,0x74,0x20,0x3d,0x20,0x65,0x6c,0x65,
+ 0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,
+ 0x42,0x79,0x54,0x61,0x67,0x4e,0x61,0x6d,0x65,0x28,0x27,0x73,0x70,0x61,0x6e,0x27,
+ 0x29,0x2e,0x69,0x74,0x65,0x6d,0x28,0x30,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x70,0x63,0x74,0x2e,0x69,0x6e,0x6e,0x65,0x72,0x48,0x54,0x4d,0x4c,0x20,0x3d,0x20,
+ 0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,0x70,0x65,0x72,0x63,0x65,0x6e,0x74,
+ 0x61,0x67,0x65,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x20,0x2b,
+ 0x20,0x27,0x25,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x76,0x65,0x72,
+ 0x65,0x64,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x77,0x69,0x64,0x74,0x68,0x20,0x3d,
+ 0x20,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x2e,0x5f,0x70,0x65,0x72,0x63,0x65,0x6e,
+ 0x74,0x61,0x67,0x65,0x20,0x2b,0x20,0x27,0x70,0x78,0x27,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x7d,0x3b,0x0d,0x0a,0x0d,0x0a,0x2f,0x2f,0x20,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,
+ 0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x0d,0x0a,0x2f,0x2f,0x20,0x72,0x65,
+ 0x70,0x6f,0x72,0x74,0x73,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x70,0x61,0x64,
+ 0x28,0x73,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x30,0x30,0x30,0x30,0x27,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x73,0x2e,
+ 0x6c,0x65,0x6e,0x67,0x74,0x68,0x29,0x20,0x2b,0x20,0x73,0x3b,0x0d,0x0a,0x7d,0x0d,
+ 0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x71,0x75,0x6f,0x74,0x65,0x28,0x73,0x29,0x20,
+ 0x7b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x22,0x27,0x20,
+ 0x2b,0x20,0x73,0x2e,0x72,0x65,0x70,0x6c,0x61,0x63,0x65,0x28,0x2f,0x5b,0x5c,0x75,
+ 0x30,0x30,0x30,0x30,0x2d,0x5c,0x75,0x30,0x30,0x31,0x66,0x22,0x5c,0x5c,0x5c,0x75,
+ 0x30,0x30,0x37,0x66,0x2d,0x5c,0x75,0x66,0x66,0x66,0x66,0x5d,0x2f,0x67,0x2c,0x20,
+ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x63,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x73,0x77,0x69,0x74,0x63,0x68,0x20,0x28,0x63,0x29,0x20,0x7b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x62,0x27,0x3a,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,
+ 0x5c,0x5c,0x62,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x5c,0x66,0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,
+ 0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x66,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x6e,0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x6e,0x27,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x72,0x27,0x3a,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,
+ 0x5c,0x72,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,
+ 0x5c,0x74,0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,
+ 0x72,0x6e,0x20,0x27,0x5c,0x5c,0x74,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2f,0x20,0x49,0x45,0x20,0x64,0x6f,0x65,0x73,0x6e,0x27,0x74,0x20,0x73,0x75,0x70,
+ 0x70,0x6f,0x72,0x74,0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2f,
+ 0x2a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x76,0x27,
+ 0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x5c,0x5c,0x76,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x2a,0x2f,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x22,0x27,0x3a,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x22,
+ 0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x5c,
+ 0x27,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
+ 0x20,0x27,0x5c,0x5c,0x5c,0x5c,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x64,0x65,
+ 0x66,0x61,0x75,0x6c,0x74,0x3a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,
+ 0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x75,0x27,0x20,0x2b,0x20,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x70,0x61,0x64,0x28,0x63,0x2e,0x63,0x68,
+ 0x61,0x72,0x43,0x6f,0x64,0x65,0x41,0x74,0x28,0x30,0x29,0x2e,0x74,0x6f,0x53,0x74,
+ 0x72,0x69,0x6e,0x67,0x28,0x31,0x36,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x29,0x20,0x2b,0x20,0x27,0x22,0x27,0x3b,0x0d,0x0a,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,
+ 0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x72,0x69,0x61,0x6c,0x69,
+ 0x7a,0x65,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x54,0x6f,0x4a,0x53,0x4f,0x4e,
+ 0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6a,0x73,0x6f,0x6e,
+ 0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x66,0x6f,0x72,0x20,0x28,0x76,
+ 0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,0x5f,0x24,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,0x20,0x5f,
+ 0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,0x6c,0x65,
+ 0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x61,0x72,0x72,0x61,
+ 0x79,0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,
+ 0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,
+ 0x30,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,
+ 0x3b,0x20,0x6c,0x69,0x6e,0x65,0x2b,0x2b,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6c,0x69,0x6e,0x65,0x5d,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x76,0x61,0x6c,0x75,0x65,0x20,
+ 0x3d,0x3d,0x3d,0x20,0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x20,0x7c,0x7c,
+ 0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,0x6c,0x6c,0x29,
+ 0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x6c,0x75,
+ 0x65,0x20,0x3d,0x20,0x27,0x6e,0x75,0x6c,0x6c,0x27,0x3b,0x0d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x61,0x72,0x72,0x61,
+ 0x79,0x2e,0x70,0x75,0x73,0x68,0x28,0x76,0x61,0x6c,0x75,0x65,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x6a,0x73,0x6f,0x6e,0x2e,
+ 0x70,0x75,0x73,0x68,0x28,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x71,0x75,0x6f,0x74,0x65,0x28,0x66,0x69,0x6c,0x65,0x29,0x20,0x2b,0x20,0x27,0x3a,
+ 0x5b,0x27,0x20,0x2b,0x20,0x61,0x72,0x72,0x61,0x79,0x2e,0x6a,0x6f,0x69,0x6e,0x28,
+ 0x27,0x2c,0x27,0x29,0x20,0x2b,0x20,0x27,0x5d,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x7b,0x27,0x20,
+ 0x2b,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6a,0x6f,0x69,0x6e,0x28,0x27,0x2c,0x27,0x29,
+ 0x20,0x2b,0x20,0x27,0x7d,0x27,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x66,0x75,
+ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x73,0x74,0x6f,0x72,0x65,0x42,0x75,0x74,0x74,0x6f,0x6e,0x5f,0x63,0x6c,
+ 0x69,0x63,0x6b,0x28,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x69,0x66,0x20,0x28,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x69,0x6e,0x4c,0x65,0x6e,0x67,
+ 0x74,0x68,0x79,0x4f,0x70,0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x29,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x7d,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x62,0x65,0x67,0x69,0x6e,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,
+ 0x65,0x72,0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x76,0x61,
+ 0x72,0x20,0x69,0x6d,0x67,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,
+ 0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,
+ 0x27,0x73,0x74,0x6f,0x72,0x65,0x49,0x6d,0x67,0x27,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x69,0x6d,0x67,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,0x76,0x69,0x73,0x69,0x62,0x69,
+ 0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x76,0x69,0x73,0x69,0x62,0x6c,0x65,0x27,
+ 0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x72,0x65,0x71,0x75,0x65,
+ 0x73,0x74,0x20,0x3d,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,
+ 0x63,0x72,0x65,0x61,0x74,0x65,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,0x70,0x65,0x6e,
+ 0x28,0x27,0x50,0x4f,0x53,0x54,0x27,0x2c,0x20,0x27,0x2f,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x2d,0x73,0x74,0x6f,0x72,0x65,0x27,0x2c,0x20,0x74,0x72,
+ 0x75,0x65,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,
+ 0x6f,0x6e,0x72,0x65,0x61,0x64,0x79,0x73,0x74,0x61,0x74,0x65,0x63,0x68,0x61,0x6e,
+ 0x67,0x65,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x65,
+ 0x76,0x65,0x6e,0x74,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x61,0x64,0x79,0x53,0x74,
+ 0x61,0x74,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x34,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x72,0x79,0x20,0x7b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,0x65,0x71,0x75,0x65,
+ 0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x21,0x3d,0x3d,0x20,0x32,0x30,
+ 0x30,0x20,0x26,0x26,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,
+ 0x74,0x75,0x73,0x20,0x21,0x3d,0x3d,0x20,0x32,0x30,0x31,0x20,0x26,0x26,0x20,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x21,0x3d,
+ 0x3d,0x20,0x32,0x30,0x34,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x65,
+ 0x73,0x73,0x61,0x67,0x65,0x20,0x3d,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,
+ 0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,0x65,0x54,0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,
+ 0x74,0x63,0x68,0x20,0x28,0x65,0x29,0x20,0x7b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x65,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,
+ 0x67,0x28,0x29,0x2e,0x73,0x65,0x61,0x72,0x63,0x68,0x28,0x2f,0x5e,0x5c,0x64,0x7b,
+ 0x33,0x7d,0x24,0x2f,0x29,0x20,0x3d,0x3d,0x3d,0x20,0x30,0x29,0x20,0x7b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,
+ 0x65,0x20,0x3d,0x20,0x65,0x20,0x2b,0x20,0x27,0x3a,0x20,0x27,0x20,0x2b,0x20,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,0x65,0x54,
+ 0x65,0x78,0x74,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6d,0x65,0x73,0x73,0x61,
+ 0x67,0x65,0x20,0x3d,0x20,0x27,0x43,0x6f,0x75,0x6c,0x64,0x20,0x6e,0x6f,0x74,0x20,
+ 0x63,0x6f,0x6e,0x6e,0x65,0x63,0x74,0x20,0x74,0x6f,0x20,0x73,0x65,0x72,0x76,0x65,
+ 0x72,0x3a,0x20,0x27,0x20,0x2b,0x20,0x65,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x0d,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,
+ 0x65,0x5f,0x65,0x6e,0x64,0x4c,0x65,0x6e,0x67,0x74,0x68,0x79,0x4f,0x70,0x65,0x72,
+ 0x61,0x74,0x69,0x6f,0x6e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x69,0x6d,0x67,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x74,0x6f,0x72,0x65,0x49,0x6d,0x67,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x6d,0x67,0x2e,0x73,0x74,0x79,0x6c,0x65,0x2e,
+ 0x76,0x69,0x73,0x69,0x62,0x69,0x6c,0x69,0x74,0x79,0x20,0x3d,0x20,0x27,0x68,0x69,
+ 0x64,0x64,0x65,0x6e,0x27,0x3b,0x0d,0x0a,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x72,0x20,0x64,0x69,0x76,0x20,0x3d,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,
+ 0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,
+ 0x64,0x28,0x27,0x73,0x74,0x6f,0x72,0x65,0x44,0x69,0x76,0x27,0x29,0x3b,0x0d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,
+ 0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,
+ 0x72,0x65,0x61,0x74,0x65,0x54,0x65,0x78,0x74,0x4e,0x6f,0x64,0x65,0x28,0x6e,0x65,
+ 0x77,0x20,0x44,0x61,0x74,0x65,0x28,0x29,0x20,0x2b,0x20,0x27,0x3a,0x20,0x27,0x20,
+ 0x2b,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x64,0x69,0x76,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,
+ 0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x63,0x72,0x65,
+ 0x61,0x74,0x65,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x28,0x27,0x62,0x72,0x27,0x29,
+ 0x29,0x3b,0x0d,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0d,0x0a,0x20,0x20,0x7d,0x3b,0x0d,
+ 0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x74,0x52,0x65,
+ 0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,0x64,0x65,0x72,0x28,0x27,0x43,0x6f,0x6e,
+ 0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x27,0x2c,0x20,0x27,0x61,0x70,0x70,
+ 0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,0x6a,0x73,0x6f,0x6e,0x27,0x29,0x3b,
+ 0x0d,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x73,0x65,0x72,0x69,0x61,0x6c,
+ 0x69,0x7a,0x65,0x43,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x54,0x6f,0x4a,0x53,0x4f,
+ 0x4e,0x28,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,
+ 0x73,0x65,0x74,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,0x64,0x65,0x72,
+ 0x28,0x27,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,
+ 0x27,0x2c,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x2e,0x74,
+ 0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x29,0x3b,0x0d,0x0a,0x20,0x20,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x6e,0x64,0x28,0x6a,0x73,0x6f,0x6e,
+ 0x29,0x3b,0x0d,0x0a,0x7d,0x0d,0x0a,
+};
+const unsigned char RESOURCE12_[] = {
+
+ 0x69,0x66,0x20,0x28,0x21,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6a,0x73,0x63,
+ 0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x70,0x6f,0x72,0x74,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x5f,0x72,0x65,0x70,0x6f,0x72,0x74,0x20,0x3d,0x20,0x66,
+ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x5f,0x72,0x65,0x70,0x6f,0x72,0x74,0x28,0x64,0x69,0x72,0x29,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x72,0x65,0x61,0x74,0x65,0x52,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,
+ 0x6e,0x20,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,
+ 0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x58,0x4d,0x4c,0x48,0x74,0x74,0x70,0x52,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x65,0x77,0x20,0x58,0x4d,0x4c,
+ 0x48,0x74,0x74,0x70,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,
+ 0x65,0x20,0x69,0x66,0x20,0x28,0x77,0x69,0x6e,0x64,0x6f,0x77,0x2e,0x41,0x63,0x74,
+ 0x69,0x76,0x65,0x58,0x4f,0x62,0x6a,0x65,0x63,0x74,0x29,0x20,0x7b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x65,0x77,
+ 0x20,0x41,0x63,0x74,0x69,0x76,0x65,0x58,0x4f,0x62,0x6a,0x65,0x63,0x74,0x28,0x22,
+ 0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x2e,0x58,0x4d,0x4c,0x48,0x54,0x54,
+ 0x50,0x22,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x70,0x61,0x64,
+ 0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x73,0x29,0x20,
+ 0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,
+ 0x30,0x30,0x30,0x30,0x27,0x2e,0x73,0x75,0x62,0x73,0x74,0x72,0x28,0x73,0x2e,0x6c,
+ 0x65,0x6e,0x67,0x74,0x68,0x29,0x20,0x2b,0x20,0x73,0x3b,0x0a,0x20,0x20,0x20,0x20,
+ 0x7d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x71,0x75,0x6f,0x74,
+ 0x65,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x73,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,
+ 0x27,0x22,0x27,0x20,0x2b,0x20,0x73,0x2e,0x72,0x65,0x70,0x6c,0x61,0x63,0x65,0x28,
+ 0x2f,0x5b,0x5c,0x75,0x30,0x30,0x30,0x30,0x2d,0x5c,0x75,0x30,0x30,0x31,0x66,0x22,
+ 0x5c,0x5c,0x5c,0x75,0x30,0x30,0x37,0x66,0x2d,0x5c,0x75,0x66,0x66,0x66,0x66,0x5d,
+ 0x2f,0x67,0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x63,0x29,
+ 0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x73,0x77,0x69,0x74,0x63,
+ 0x68,0x20,0x28,0x63,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x62,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x62,
+ 0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x5c,0x66,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x66,0x27,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x6e,0x27,0x3a,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
+ 0x6e,0x20,0x27,0x5c,0x5c,0x6e,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x72,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,
+ 0x72,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,
+ 0x20,0x27,0x5c,0x74,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x74,0x27,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2f,0x20,0x49,0x45,0x20,0x64,0x6f,0x65,
+ 0x73,0x6e,0x27,0x74,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x74,0x68,0x69,
+ 0x73,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x2f,0x2a,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x76,0x27,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
+ 0x20,0x27,0x5c,0x5c,0x76,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x2a,0x2f,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,
+ 0x27,0x22,0x27,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,
+ 0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x22,0x27,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x63,0x61,0x73,0x65,0x20,0x27,0x5c,0x5c,0x27,0x3a,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,
+ 0x20,0x27,0x5c,0x5c,0x5c,0x5c,0x27,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x3a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x27,0x5c,0x5c,0x75,0x27,
+ 0x20,0x2b,0x20,0x70,0x61,0x64,0x28,0x63,0x2e,0x63,0x68,0x61,0x72,0x43,0x6f,0x64,
+ 0x65,0x41,0x74,0x28,0x30,0x29,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,
+ 0x31,0x36,0x29,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x29,0x20,0x2b,0x20,0x27,0x22,0x27,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
+ 0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x66,0x69,0x6c,0x65,0x20,0x69,0x6e,0x20,
+ 0x74,0x6f,0x70,0x2e,0x5f,0x24,0x6a,0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,
+ 0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x63,0x6f,
+ 0x76,0x65,0x72,0x61,0x67,0x65,0x20,0x3d,0x20,0x74,0x6f,0x70,0x2e,0x5f,0x24,0x6a,
+ 0x73,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x66,0x69,0x6c,0x65,0x5d,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x61,0x72,0x72,0x61,0x79,
+ 0x20,0x3d,0x20,0x5b,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,
+ 0x20,0x6c,0x65,0x6e,0x67,0x74,0x68,0x20,0x3d,0x20,0x63,0x6f,0x76,0x65,0x72,0x61,
+ 0x67,0x65,0x2e,0x6c,0x65,0x6e,0x67,0x74,0x68,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x66,0x6f,0x72,0x20,0x28,0x76,0x61,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,
+ 0x20,0x30,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3c,0x20,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x3b,0x20,0x6c,0x69,0x6e,0x65,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,
+ 0x20,0x63,0x6f,0x76,0x65,0x72,0x61,0x67,0x65,0x5b,0x6c,0x69,0x6e,0x65,0x5d,0x3b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x76,0x61,0x6c,
+ 0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x75,0x6e,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,
+ 0x20,0x7c,0x7c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x3d,0x3d,0x20,0x6e,0x75,
+ 0x6c,0x6c,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x27,0x6e,0x75,0x6c,0x6c,0x27,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x61,0x72,0x72,0x61,0x79,0x2e,0x70,0x75,0x73,0x68,0x28,0x76,0x61,0x6c,
+ 0x75,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x70,0x75,0x73,0x68,0x28,0x71,0x75,0x6f,
+ 0x74,0x65,0x28,0x66,0x69,0x6c,0x65,0x29,0x20,0x2b,0x20,0x27,0x3a,0x5b,0x27,0x20,
+ 0x2b,0x20,0x61,0x72,0x72,0x61,0x79,0x2e,0x6a,0x6f,0x69,0x6e,0x28,0x27,0x2c,0x27,
+ 0x29,0x20,0x2b,0x20,0x27,0x5d,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,
+ 0x20,0x20,0x20,0x20,0x6a,0x73,0x6f,0x6e,0x20,0x3d,0x20,0x27,0x7b,0x27,0x20,0x2b,
+ 0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6a,0x6f,0x69,0x6e,0x28,0x27,0x2c,0x27,0x29,0x20,
+ 0x2b,0x20,0x27,0x7d,0x27,0x3b,0x0a,0x0a,0x20,0x20,0x20,0x20,0x76,0x61,0x72,0x20,
+ 0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x20,0x3d,0x20,0x63,0x72,0x65,0x61,0x74,0x65,
+ 0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x76,
+ 0x61,0x72,0x20,0x75,0x72,0x6c,0x20,0x3d,0x20,0x27,0x2f,0x6a,0x73,0x63,0x6f,0x76,
+ 0x65,0x72,0x61,0x67,0x65,0x2d,0x73,0x74,0x6f,0x72,0x65,0x27,0x3b,0x0a,0x20,0x20,
+ 0x20,0x20,0x69,0x66,0x20,0x28,0x64,0x69,0x72,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x75,0x72,0x6c,0x20,0x2b,0x3d,0x20,0x27,0x2f,0x27,0x20,0x2b,0x20,
+ 0x65,0x6e,0x63,0x6f,0x64,0x65,0x55,0x52,0x49,0x43,0x6f,0x6d,0x70,0x6f,0x6e,0x65,
+ 0x6e,0x74,0x28,0x64,0x69,0x72,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x6f,0x70,0x65,0x6e,0x28,
+ 0x27,0x50,0x4f,0x53,0x54,0x27,0x2c,0x20,0x75,0x72,0x6c,0x2c,0x20,0x66,0x61,0x6c,
+ 0x73,0x65,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,
+ 0x2e,0x73,0x65,0x74,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,0x64,0x65,
+ 0x72,0x28,0x27,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x27,
+ 0x2c,0x20,0x27,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2f,0x6a,
+ 0x73,0x6f,0x6e,0x27,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,
+ 0x73,0x74,0x2e,0x73,0x65,0x74,0x52,0x65,0x71,0x75,0x65,0x73,0x74,0x48,0x65,0x61,
+ 0x64,0x65,0x72,0x28,0x27,0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,
+ 0x67,0x74,0x68,0x27,0x2c,0x20,0x6a,0x73,0x6f,0x6e,0x2e,0x6c,0x65,0x6e,0x67,0x74,
+ 0x68,0x2e,0x74,0x6f,0x53,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x29,0x3b,0x0a,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x65,0x6e,0x64,0x28,
+ 0x6a,0x73,0x6f,0x6e,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x69,0x66,0x20,0x28,0x72,
+ 0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x3d,0x3d,
+ 0x3d,0x20,0x32,0x30,0x30,0x20,0x7c,0x7c,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,
+ 0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x20,0x3d,0x3d,0x3d,0x20,0x32,0x30,0x31,0x20,
+ 0x7c,0x7c,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,
+ 0x73,0x20,0x3d,0x3d,0x3d,0x20,0x32,0x30,0x34,0x29,0x20,0x7b,0x0a,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65,0x71,0x75,0x65,0x73,
+ 0x74,0x2e,0x72,0x65,0x73,0x70,0x6f,0x6e,0x73,0x65,0x54,0x65,0x78,0x74,0x3b,0x0a,
+ 0x20,0x20,0x20,0x20,0x7d,0x0a,0x20,0x20,0x20,0x20,0x65,0x6c,0x73,0x65,0x20,0x7b,
+ 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x72,0x6f,0x77,0x20,0x72,0x65,0x71,
+ 0x75,0x65,0x73,0x74,0x2e,0x73,0x74,0x61,0x74,0x75,0x73,0x3b,0x0a,0x20,0x20,0x20,
+ 0x20,0x7d,0x0a,0x20,0x20,0x7d,0x3b,0x0a,0x7d,0x0a,
+};
+const unsigned char RESOURCE13_[] = {
+
+ 0x47,0x49,0x46,0x38,0x39,0x61,0x07,0x00,0x07,0x00,0xe3,0x0b,0x00,0x00,0x00,0x00,
+ 0x05,0x05,0x05,0x20,0x20,0x20,0x3e,0x3e,0x3e,0x40,0x40,0x40,0x60,0x60,0x60,0x7d,
+ 0x7d,0x7d,0x80,0x80,0x80,0xa0,0xa0,0xa0,0xc0,0xc0,0xc0,0xe0,0xe0,0xe0,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x21,0xff,0x0b,
+ 0x4e,0x45,0x54,0x53,0x43,0x41,0x50,0x45,0x32,0x2e,0x30,0x03,0x01,0x00,0x00,0x00,
+ 0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,
+ 0x00,0x00,0x04,0x16,0xf0,0x49,0x20,0xa5,0x78,0x54,0xd5,0xab,0x1f,0x21,0x55,0x92,
+ 0x48,0xc5,0x83,0x54,0xe5,0x61,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,
+ 0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,0xf0,
+ 0x49,0x21,0x25,0x79,0x14,0xd4,0xab,0x5f,0x29,0x95,0xa2,0x48,0xc7,0x93,0x54,0x25,
+ 0x62,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,
+ 0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,0xf0,0x49,0x22,0x65,0x79,0x54,
+ 0xd4,0xab,0xdf,0x39,0x15,0x00,0x48,0xc8,0xa3,0x54,0x65,0x62,0x56,0x8f,0x2a,0x45,
+ 0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,
+ 0x07,0x00,0x00,0x04,0x16,0xf0,0xc9,0x22,0xe5,0x79,0x94,0xd4,0xab,0x1f,0x42,0x95,
+ 0x20,0x48,0xc9,0x03,0x54,0xa5,0x62,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,
+ 0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,
+ 0xf0,0xc9,0x23,0x25,0x7a,0xb4,0xd4,0xab,0x5f,0x4a,0x15,0x41,0x48,0xca,0x23,0x54,
+ 0x25,0x60,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,
+ 0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,0x16,0xf0,0x49,0x24,0x65,0x7a,
+ 0xf4,0xd4,0xab,0x9f,0x52,0x55,0x51,0x48,0xc0,0x43,0x54,0xa5,0x60,0x56,0x8f,0x2a,
+ 0x45,0x00,0x21,0xf9,0x04,0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,
+ 0x00,0x07,0x00,0x00,0x04,0x16,0xf0,0xc9,0x24,0xa5,0x7a,0x14,0xd5,0xab,0x1f,0x00,
+ 0xd5,0x71,0x48,0xc2,0x53,0x54,0x25,0x61,0x56,0x8f,0x2a,0x45,0x00,0x21,0xf9,0x04,
+ 0x01,0x0a,0x00,0x0f,0x00,0x2c,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x00,0x04,
+ 0x16,0xf0,0x49,0x25,0x25,0x78,0x34,0xd5,0xab,0x9f,0x10,0x15,0x82,0x48,0xc4,0x73,
+ 0x54,0x65,0x61,0x56,0x8f,0x2a,0x45,0x00,0x3b,
+};
+const struct Resource RESOURCES[] = {
+ {
+ "jscoverage-help.txt",
+ RESOURCE1_,
+ sizeof(RESOURCE1_)
+ },
+ {
+ "jscoverage-server-help.txt",
+ RESOURCE2_,
+ sizeof(RESOURCE2_)
+ },
+ {
+ "jscoverage.jsm",
+ RESOURCE3_,
+ sizeof(RESOURCE3_)
+ },
+ {
+ "jscoverage.manifest",
+ RESOURCE4_,
+ sizeof(RESOURCE4_)
+ },
+ {
+ "jscoverage.xul",
+ RESOURCE5_,
+ sizeof(RESOURCE5_)
+ },
+ {
+ "jscoverage-overlay.js",
+ RESOURCE6_,
+ sizeof(RESOURCE6_)
+ },
+ {
+ "jscoverage.html",
+ RESOURCE7_,
+ sizeof(RESOURCE7_)
+ },
+ {
+ "jscoverage.css",
+ RESOURCE8_,
+ sizeof(RESOURCE8_)
+ },
+ {
+ "jscoverage-ie.css",
+ RESOURCE9_,
+ sizeof(RESOURCE9_)
+ },
+ {
+ "jscoverage-highlight.css",
+ RESOURCE10_,
+ sizeof(RESOURCE10_)
+ },
+ {
+ "jscoverage.js",
+ RESOURCE11_,
+ sizeof(RESOURCE11_)
+ },
+ {
+ "report.js",
+ RESOURCE12_,
+ sizeof(RESOURCE12_)
+ },
+ {
+ "jscoverage-throbber.gif",
+ RESOURCE13_,
+ sizeof(RESOURCE13_)
+ },
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/stamp-h1 b/tools/node_modules/expresso/deps/jscoverage/stamp-h1
new file mode 100644
index 0000000..4547fe1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/stamp-h1
@@ -0,0 +1 @@
+timestamp for config.h
diff --git a/tools/node_modules/expresso/deps/jscoverage/stream.c b/tools/node_modules/expresso/deps/jscoverage/stream.c
new file mode 100644
index 0000000..cc6adc0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/stream.c
@@ -0,0 +1,129 @@
+/*
+ stream.c - `Stream' object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define _GNU_SOURCE
+
+#include <config.h>
+
+#include "stream.h"
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "util.h"
+
+Stream * Stream_new(size_t capacity) {
+ Stream * result = xmalloc(sizeof(Stream));
+ result->length = 0;
+ if (capacity == 0) {
+ capacity = 8192;
+ }
+ result->capacity = capacity;
+ result->data = xmalloc(capacity);
+ return result;
+}
+
+void Stream_write(Stream * stream, const void * p, size_t size) {
+ size_t stream_length = stream->length;
+ size_t stream_capacity = stream->capacity;
+ if (stream_capacity - stream_length < size) {
+ if (SIZE_MAX - size < stream_length) {
+ fatal("out of memory");
+ }
+
+ if (SIZE_MAX / 2 < stream_capacity) {
+ stream_capacity = SIZE_MAX;
+ }
+ else {
+ stream_capacity *= 2;
+ }
+
+ size_t new_length = stream_length + size;
+ if (stream_capacity < new_length) {
+ stream_capacity = new_length;
+ }
+
+ stream->data = xrealloc(stream->data, stream_capacity);
+ stream->capacity = stream_capacity;
+ memcpy(stream->data + stream_length, p, size);
+ stream->length = new_length;
+ }
+ else {
+ memcpy(stream->data + stream_length, p, size);
+ stream->length = stream_length + size;
+ }
+}
+
+void Stream_write_string(Stream * stream, const char * s) {
+ Stream_write(stream, s, strlen(s));
+}
+
+void Stream_write_char(Stream * stream, char c) {
+ size_t stream_length = stream->length;
+ if (stream_length == stream->capacity) {
+ if (stream->capacity == SIZE_MAX) {
+ fatal("out of memory");
+ }
+
+ if (SIZE_MAX / 2 < stream->capacity) {
+ stream->capacity = SIZE_MAX;
+ }
+ else {
+ stream->capacity *= 2;
+ }
+
+ stream->data = xrealloc(stream->data, stream->capacity);
+ }
+ stream->data[stream_length] = c;
+ stream->length = stream_length + 1;
+}
+
+void Stream_printf(Stream * stream, const char * format, ...) {
+ va_list a;
+ va_start(a, format);
+
+ char * s = NULL;
+ /* note that size does not include the NUL character */
+ int size = vasprintf(&s, format, a);
+ if (size < 0) {
+ fatal("out of memory");
+ }
+ Stream_write(stream, s, size);
+ free(s);
+
+ va_end(a);
+}
+
+void Stream_write_file_contents(Stream * stream, FILE * f) {
+ char buffer[8192];
+ size_t bytes_read;
+ while ((bytes_read = fread(buffer, 1, 8192, f)) > 0) {
+ Stream_write(stream, buffer, bytes_read);
+ }
+}
+
+void Stream_delete(Stream * stream) {
+ free(stream->data);
+ free(stream);
+}
+
+void Stream_reset(Stream * stream) {
+ stream->length = 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/stream.h b/tools/node_modules/expresso/deps/jscoverage/stream.h
new file mode 100644
index 0000000..41c376f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/stream.h
@@ -0,0 +1,57 @@
+/*
+ stream.h - `Stream' object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef STREAM_H_
+#define STREAM_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct Stream {
+ uint8_t * data;
+ size_t length;
+ size_t capacity;
+} Stream;
+
+Stream * Stream_new(size_t capacity);
+
+void Stream_write(Stream * stream, const void * p, size_t size);
+
+void Stream_write_string(Stream * stream, const char * s);
+
+void Stream_write_char(Stream * stream, char c);
+
+void Stream_printf(Stream * stream, const char * format, ...) __attribute__((format(printf, 2, 3)));
+
+void Stream_write_file_contents(Stream * stream, FILE * f);
+
+void Stream_reset(Stream * stream);
+
+void Stream_delete(Stream * stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STREAM_H_ */
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/asprintf.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encoding.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/encodings.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/gethostbyname.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/highlight.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-body.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-bad-url.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-client-close-after-request.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-host.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-body.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-bad-headers.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-charset.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-chunked.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-server-close-immediately.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/http-url.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/instrument-js.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/json.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/mkdirs.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/recursive-dir-list.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/resource-manager.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/stream.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/streams.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po
new file mode 100644
index 0000000..9ce06a8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/.deps/util.Po
@@ -0,0 +1 @@
+# dummy
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/Makefile b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile
new file mode 100644
index 0000000..9f6d1fc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile
@@ -0,0 +1,846 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# tests/Makefile. Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+# Makefile.am - build tests
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+pkgdatadir = $(datadir)/jscoverage
+pkglibdir = $(libdir)/jscoverage
+pkgincludedir = $(includedir)/jscoverage
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = x86_64-unknown-linux-gnu
+host_triplet = x86_64-unknown-linux-gnu
+noinst_PROGRAMS = asprintf$(EXEEXT) encodings$(EXEEXT) \
+ gethostbyname$(EXEEXT) http-client-bad-body$(EXEEXT) \
+ http-client-bad-url$(EXEEXT) \
+ http-client-close-after-request$(EXEEXT) \
+ http-server-bad-body$(EXEEXT) http-server-bad-headers$(EXEEXT) \
+ http-server-charset$(EXEEXT) http-server-chunked$(EXEEXT) \
+ http-server-close-immediately$(EXEEXT) json$(EXEEXT) \
+ mkdirs$(EXEEXT) recursive-dir-list$(EXEEXT) streams$(EXEEXT)
+subdir = tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_asprintf_OBJECTS = asprintf.$(OBJEXT) util.$(OBJEXT)
+asprintf_OBJECTS = $(am_asprintf_OBJECTS)
+asprintf_LDADD = $(LDADD)
+am_encodings_OBJECTS = encodings.$(OBJEXT) encoding.$(OBJEXT) \
+ util.$(OBJEXT)
+encodings_OBJECTS = $(am_encodings_OBJECTS)
+encodings_DEPENDENCIES =
+am_gethostbyname_OBJECTS = gethostbyname.$(OBJEXT) http-host.$(OBJEXT) \
+ util.$(OBJEXT)
+gethostbyname_OBJECTS = $(am_gethostbyname_OBJECTS)
+gethostbyname_DEPENDENCIES =
+am_http_client_bad_body_OBJECTS = http-client-bad-body.$(OBJEXT) \
+ http-url.$(OBJEXT) util.$(OBJEXT)
+http_client_bad_body_OBJECTS = $(am_http_client_bad_body_OBJECTS)
+http_client_bad_body_DEPENDENCIES =
+am_http_client_bad_url_OBJECTS = http-client-bad-url.$(OBJEXT) \
+ util.$(OBJEXT)
+http_client_bad_url_OBJECTS = $(am_http_client_bad_url_OBJECTS)
+http_client_bad_url_DEPENDENCIES =
+http_client_close_after_request_SOURCES = \
+ http-client-close-after-request.c
+http_client_close_after_request_OBJECTS = \
+ http-client-close-after-request.$(OBJEXT)
+http_client_close_after_request_DEPENDENCIES =
+http_server_bad_body_SOURCES = http-server-bad-body.c
+http_server_bad_body_OBJECTS = http-server-bad-body.$(OBJEXT)
+http_server_bad_body_DEPENDENCIES =
+http_server_bad_headers_SOURCES = http-server-bad-headers.c
+http_server_bad_headers_OBJECTS = http-server-bad-headers.$(OBJEXT)
+http_server_bad_headers_DEPENDENCIES =
+am_http_server_charset_OBJECTS = http-server-charset.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_charset_OBJECTS = $(am_http_server_charset_OBJECTS)
+http_server_charset_DEPENDENCIES =
+am_http_server_chunked_OBJECTS = http-server-chunked.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_chunked_OBJECTS = $(am_http_server_chunked_OBJECTS)
+http_server_chunked_DEPENDENCIES =
+http_server_close_immediately_SOURCES = \
+ http-server-close-immediately.c
+http_server_close_immediately_OBJECTS = \
+ http-server-close-immediately.$(OBJEXT)
+http_server_close_immediately_DEPENDENCIES =
+am_json_OBJECTS = json.$(OBJEXT) encoding.$(OBJEXT) \
+ highlight.$(OBJEXT) instrument-js.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+json_OBJECTS = $(am_json_OBJECTS)
+json_DEPENDENCIES = ../js/obj/libjs.a
+am_mkdirs_OBJECTS = mkdirs.$(OBJEXT) util.$(OBJEXT)
+mkdirs_OBJECTS = $(am_mkdirs_OBJECTS)
+mkdirs_LDADD = $(LDADD)
+am_recursive_dir_list_OBJECTS = recursive-dir-list.$(OBJEXT) \
+ util.$(OBJEXT)
+recursive_dir_list_OBJECTS = $(am_recursive_dir_list_OBJECTS)
+recursive_dir_list_LDADD = $(LDADD)
+am_streams_OBJECTS = streams.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+streams_OBJECTS = $(am_streams_OBJECTS)
+streams_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+DIST_SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run aclocal-1.10
+AMTAR = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run tar
+AUTOCONF = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoconf
+AUTOHEADER = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run autoheader
+AUTOMAKE = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run automake-1.10
+AWK = gawk
+CC = gcc -std=gnu99
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2
+CPP = gcc -std=gnu99 -E
+CPPFLAGS =
+CXX = g++
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C =
+ECHO_N = -n
+ECHO_T =
+EGREP = /bin/grep -E
+EXEEXT =
+EXTRA_SOCKET_LIBS =
+EXTRA_THREAD_LIBS = -lpthread
+EXTRA_TIMER_LIBS =
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS =
+LIBICONV =
+LIBOBJS =
+LIBS =
+LTLIBICONV =
+LTLIBOBJS =
+MAKEINFO = ${SHELL} /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = jscoverage
+PACKAGE_BUGREPORT =
+PACKAGE_NAME = jscoverage
+PACKAGE_STRING = jscoverage 0.4
+PACKAGE_TARNAME = jscoverage
+PACKAGE_VERSION = 0.4
+PATH_SEPARATOR = :
+SET_MAKE =
+SHELL = /bin/sh
+STRIP =
+VERSION = 0.4
+XP_DEF = -DXP_UNIX
+abs_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/tests
+abs_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/tests
+abs_top_builddir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+abs_top_srcdir = /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote =
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = x86_64-unknown-linux-gnu
+build_alias =
+build_cpu = x86_64
+build_os = linux-gnu
+build_vendor = unknown
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = x86_64-unknown-linux-gnu
+host_alias =
+host_cpu = x86_64
+host_os = linux-gnu
+host_vendor = unknown
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = $(SHELL) /scratch/oe/oe-admin/tools/node_modules/expresso/deps/jscoverage/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target_alias =
+top_builddir = ..
+top_srcdir = ..
+AM_CFLAGS = -DXP_UNIX -I../js -I../js/obj
+AM_CXXFLAGS = -DXP_UNIX -I../js -I../js/obj
+asprintf_SOURCES = asprintf.c ../util.c
+encodings_SOURCES = encodings.c ../encoding.c ../util.c
+encodings_LDADD =
+gethostbyname_SOURCES = gethostbyname.c ../http-host.c ../util.c
+gethostbyname_LDADD =
+http_client_bad_body_SOURCES = http-client-bad-body.c ../http-url.c ../util.c
+http_client_bad_body_LDADD =
+http_client_bad_url_SOURCES = http-client-bad-url.c ../util.c
+http_client_bad_url_LDADD =
+http_client_close_after_request_LDADD =
+http_server_bad_body_LDADD =
+http_server_bad_headers_LDADD =
+http_server_charset_SOURCES = http-server-charset.c ../stream.c ../util.c
+http_server_charset_LDADD =
+http_server_chunked_SOURCES = http-server-chunked.c ../stream.c ../util.c
+http_server_chunked_LDADD =
+http_server_close_immediately_LDADD =
+json_SOURCES = json.c ../encoding.c ../highlight.c ../instrument-js.cpp ../resource-manager.c ../stream.c ../util.c
+json_LDADD = ../js/obj/libjs.a -lm
+mkdirs_SOURCES = mkdirs.c ../util.c
+recursive_dir_list_SOURCES = recursive-dir-list.c ../util.c
+streams_SOURCES = streams.c ../stream.c ../util.c
+TESTS = encodings.sh \
+ fatal.sh \
+ help.sh \
+ invalid-option.sh \
+ javascript.sh \
+ javascript-ignore.sh \
+ javascript-utf-8.sh \
+ no-arguments.sh \
+ recursive.sh \
+ recursive-crlf.sh \
+ recursive-exclude.sh \
+ recursive-fatal.sh \
+ recursive-no-instrument.sh \
+ same-directory.sh \
+ version.sh \
+ asprintf.sh \
+ mkdirs.sh \
+ recursive-dir-list.sh \
+ streams.sh \
+ charset.sh \
+ chunked.sh \
+ gethostbyname.sh \
+ json.sh \
+ proxy.sh \
+ proxy-bad-request-body.sh \
+ proxy-bad-response-body.sh \
+ proxy-bad-response-body-javascript.sh \
+ proxy-bad-response-headers.sh \
+ proxy-no-server.sh \
+ proxy-url.sh \
+ server.sh \
+ server-bad-requests.sh \
+ server-close-after-request.sh \
+ server-content-types.sh \
+ server-directory-listing.sh \
+ server-directory-redirect.sh \
+ server-encoded-url.sh \
+ server-error.sh \
+ server-help.sh \
+ server-ip-address.sh \
+ server-shutdown.sh \
+ server-shutdown-bad-method.sh \
+ server-special-file.sh \
+ server-unreadable-directory.sh \
+ server-unreadable-file.sh \
+ server-verbose.sh \
+ server-version.sh \
+ store.sh \
+ store-bad-json.sh \
+ store-bad-request-body.sh \
+ store-bad-response-headers.sh \
+ store-escaped-characters.sh \
+ store-server-bad-body.sh \
+ store-server-closes-immediately.sh \
+ store-source-not-found.sh \
+ store-unreadable-json.sh \
+ store-unwritable-json.sh
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+asprintf$(EXEEXT): $(asprintf_OBJECTS) $(asprintf_DEPENDENCIES)
+ @rm -f asprintf$(EXEEXT)
+ $(LINK) $(asprintf_OBJECTS) $(asprintf_LDADD) $(LIBS)
+encodings$(EXEEXT): $(encodings_OBJECTS) $(encodings_DEPENDENCIES)
+ @rm -f encodings$(EXEEXT)
+ $(LINK) $(encodings_OBJECTS) $(encodings_LDADD) $(LIBS)
+gethostbyname$(EXEEXT): $(gethostbyname_OBJECTS) $(gethostbyname_DEPENDENCIES)
+ @rm -f gethostbyname$(EXEEXT)
+ $(LINK) $(gethostbyname_OBJECTS) $(gethostbyname_LDADD) $(LIBS)
+http-client-bad-body$(EXEEXT): $(http_client_bad_body_OBJECTS) $(http_client_bad_body_DEPENDENCIES)
+ @rm -f http-client-bad-body$(EXEEXT)
+ $(LINK) $(http_client_bad_body_OBJECTS) $(http_client_bad_body_LDADD) $(LIBS)
+http-client-bad-url$(EXEEXT): $(http_client_bad_url_OBJECTS) $(http_client_bad_url_DEPENDENCIES)
+ @rm -f http-client-bad-url$(EXEEXT)
+ $(LINK) $(http_client_bad_url_OBJECTS) $(http_client_bad_url_LDADD) $(LIBS)
+http-client-close-after-request$(EXEEXT): $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_DEPENDENCIES)
+ @rm -f http-client-close-after-request$(EXEEXT)
+ $(LINK) $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_LDADD) $(LIBS)
+http-server-bad-body$(EXEEXT): $(http_server_bad_body_OBJECTS) $(http_server_bad_body_DEPENDENCIES)
+ @rm -f http-server-bad-body$(EXEEXT)
+ $(LINK) $(http_server_bad_body_OBJECTS) $(http_server_bad_body_LDADD) $(LIBS)
+http-server-bad-headers$(EXEEXT): $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_DEPENDENCIES)
+ @rm -f http-server-bad-headers$(EXEEXT)
+ $(LINK) $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_LDADD) $(LIBS)
+http-server-charset$(EXEEXT): $(http_server_charset_OBJECTS) $(http_server_charset_DEPENDENCIES)
+ @rm -f http-server-charset$(EXEEXT)
+ $(LINK) $(http_server_charset_OBJECTS) $(http_server_charset_LDADD) $(LIBS)
+http-server-chunked$(EXEEXT): $(http_server_chunked_OBJECTS) $(http_server_chunked_DEPENDENCIES)
+ @rm -f http-server-chunked$(EXEEXT)
+ $(LINK) $(http_server_chunked_OBJECTS) $(http_server_chunked_LDADD) $(LIBS)
+http-server-close-immediately$(EXEEXT): $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_DEPENDENCIES)
+ @rm -f http-server-close-immediately$(EXEEXT)
+ $(LINK) $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_LDADD) $(LIBS)
+json$(EXEEXT): $(json_OBJECTS) $(json_DEPENDENCIES)
+ @rm -f json$(EXEEXT)
+ $(CXXLINK) $(json_OBJECTS) $(json_LDADD) $(LIBS)
+mkdirs$(EXEEXT): $(mkdirs_OBJECTS) $(mkdirs_DEPENDENCIES)
+ @rm -f mkdirs$(EXEEXT)
+ $(LINK) $(mkdirs_OBJECTS) $(mkdirs_LDADD) $(LIBS)
+recursive-dir-list$(EXEEXT): $(recursive_dir_list_OBJECTS) $(recursive_dir_list_DEPENDENCIES)
+ @rm -f recursive-dir-list$(EXEEXT)
+ $(LINK) $(recursive_dir_list_OBJECTS) $(recursive_dir_list_LDADD) $(LIBS)
+streams$(EXEEXT): $(streams_OBJECTS) $(streams_DEPENDENCIES)
+ @rm -f streams$(EXEEXT)
+ $(LINK) $(streams_OBJECTS) $(streams_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+include ./$(DEPDIR)/asprintf.Po
+include ./$(DEPDIR)/encoding.Po
+include ./$(DEPDIR)/encodings.Po
+include ./$(DEPDIR)/gethostbyname.Po
+include ./$(DEPDIR)/highlight.Po
+include ./$(DEPDIR)/http-client-bad-body.Po
+include ./$(DEPDIR)/http-client-bad-url.Po
+include ./$(DEPDIR)/http-client-close-after-request.Po
+include ./$(DEPDIR)/http-host.Po
+include ./$(DEPDIR)/http-server-bad-body.Po
+include ./$(DEPDIR)/http-server-bad-headers.Po
+include ./$(DEPDIR)/http-server-charset.Po
+include ./$(DEPDIR)/http-server-chunked.Po
+include ./$(DEPDIR)/http-server-close-immediately.Po
+include ./$(DEPDIR)/http-url.Po
+include ./$(DEPDIR)/instrument-js.Po
+include ./$(DEPDIR)/json.Po
+include ./$(DEPDIR)/mkdirs.Po
+include ./$(DEPDIR)/recursive-dir-list.Po
+include ./$(DEPDIR)/resource-manager.Po
+include ./$(DEPDIR)/stream.Po
+include ./$(DEPDIR)/streams.Po
+include ./$(DEPDIR)/util.Po
+
+.c.o:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c $<
+
+.c.obj:
+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+util.o: ../util.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.o -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+# source='../util.c' object='util.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+
+util.obj: ../util.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.obj -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+# source='../util.c' object='util.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+
+encoding.o: ../encoding.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.o -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+# source='../encoding.c' object='encoding.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+
+encoding.obj: ../encoding.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.obj -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+# source='../encoding.c' object='encoding.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+
+http-host.o: ../http-host.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.o -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+# source='../http-host.c' object='http-host.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+
+http-host.obj: ../http-host.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.obj -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+# source='../http-host.c' object='http-host.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+
+http-url.o: ../http-url.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.o -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+# source='../http-url.c' object='http-url.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+
+http-url.obj: ../http-url.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.obj -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+# source='../http-url.c' object='http-url.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+
+stream.o: ../stream.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.o -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+# source='../stream.c' object='stream.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+
+stream.obj: ../stream.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.obj -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+# source='../stream.c' object='stream.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+
+highlight.o: ../highlight.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.o -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+# source='../highlight.c' object='highlight.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+
+highlight.obj: ../highlight.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.obj -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+# source='../highlight.c' object='highlight.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+
+resource-manager.o: ../resource-manager.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.o -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+# source='../resource-manager.c' object='resource-manager.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+
+resource-manager.obj: ../resource-manager.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.obj -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+# source='../resource-manager.c' object='resource-manager.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+# $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+
+.cpp.o:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+# source='$<' object='$@' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+instrument-js.o: ../instrument-js.cpp
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.o -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+# source='../instrument-js.cpp' object='instrument-js.o' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+
+instrument-js.obj: ../instrument-js.cpp
+ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.obj -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+# source='../instrument-js.cpp' object='instrument-js.obj' libtool=no \
+# DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+# $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am
new file mode 100644
index 0000000..c58d2a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.am
@@ -0,0 +1,130 @@
+# Makefile.am - build tests
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+noinst_PROGRAMS = asprintf \
+ encodings \
+ gethostbyname \
+ http-client-bad-body \
+ http-client-bad-url \
+ http-client-close-after-request \
+ http-server-bad-body \
+ http-server-bad-headers \
+ http-server-charset \
+ http-server-chunked \
+ http-server-close-immediately \
+ json \
+ mkdirs \
+ recursive-dir-list \
+ streams
+
+AM_CFLAGS = @XP_DEF@ -I../js -I../js/obj
+AM_CXXFLAGS = @XP_DEF@ -I../js -I../js/obj
+
+asprintf_SOURCES = asprintf.c ../util.c
+
+encodings_SOURCES = encodings.c ../encoding.c ../util.c
+encodings_LDADD = @LIBICONV@
+
+gethostbyname_SOURCES = gethostbyname.c ../http-host.c ../util.c
+gethostbyname_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_client_bad_body_SOURCES = http-client-bad-body.c ../http-url.c ../util.c
+http_client_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_client_bad_url_SOURCES = http-client-bad-url.c ../util.c
+http_client_bad_url_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_client_close_after_request_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_bad_headers_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_charset_SOURCES = http-server-charset.c ../stream.c ../util.c
+http_server_charset_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_chunked_SOURCES = http-server-chunked.c ../stream.c ../util.c
+http_server_chunked_LDADD = @EXTRA_SOCKET_LIBS@
+
+http_server_close_immediately_LDADD = @EXTRA_SOCKET_LIBS@
+
+json_SOURCES = json.c ../encoding.c ../highlight.c ../instrument-js.cpp ../resource-manager.c ../stream.c ../util.c
+json_LDADD = ../js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+
+mkdirs_SOURCES = mkdirs.c ../util.c
+
+recursive_dir_list_SOURCES = recursive-dir-list.c ../util.c
+
+streams_SOURCES = streams.c ../stream.c ../util.c
+
+TESTS = encodings.sh \
+ fatal.sh \
+ help.sh \
+ invalid-option.sh \
+ javascript.sh \
+ javascript-ignore.sh \
+ javascript-utf-8.sh \
+ no-arguments.sh \
+ recursive.sh \
+ recursive-crlf.sh \
+ recursive-exclude.sh \
+ recursive-fatal.sh \
+ recursive-no-instrument.sh \
+ same-directory.sh \
+ version.sh \
+ asprintf.sh \
+ mkdirs.sh \
+ recursive-dir-list.sh \
+ streams.sh \
+ charset.sh \
+ chunked.sh \
+ gethostbyname.sh \
+ json.sh \
+ proxy.sh \
+ proxy-bad-request-body.sh \
+ proxy-bad-response-body.sh \
+ proxy-bad-response-body-javascript.sh \
+ proxy-bad-response-headers.sh \
+ proxy-no-server.sh \
+ proxy-url.sh \
+ server.sh \
+ server-bad-requests.sh \
+ server-close-after-request.sh \
+ server-content-types.sh \
+ server-directory-listing.sh \
+ server-directory-redirect.sh \
+ server-encoded-url.sh \
+ server-error.sh \
+ server-help.sh \
+ server-ip-address.sh \
+ server-shutdown.sh \
+ server-shutdown-bad-method.sh \
+ server-special-file.sh \
+ server-unreadable-directory.sh \
+ server-unreadable-file.sh \
+ server-verbose.sh \
+ server-version.sh \
+ store.sh \
+ store-bad-json.sh \
+ store-bad-request-body.sh \
+ store-bad-response-headers.sh \
+ store-escaped-characters.sh \
+ store-server-bad-body.sh \
+ store-server-closes-immediately.sh \
+ store-source-not-found.sh \
+ store-unreadable-json.sh \
+ store-unwritable-json.sh
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in
new file mode 100644
index 0000000..bbe0402
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/Makefile.in
@@ -0,0 +1,846 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - build tests
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = asprintf$(EXEEXT) encodings$(EXEEXT) \
+ gethostbyname$(EXEEXT) http-client-bad-body$(EXEEXT) \
+ http-client-bad-url$(EXEEXT) \
+ http-client-close-after-request$(EXEEXT) \
+ http-server-bad-body$(EXEEXT) http-server-bad-headers$(EXEEXT) \
+ http-server-charset$(EXEEXT) http-server-chunked$(EXEEXT) \
+ http-server-close-immediately$(EXEEXT) json$(EXEEXT) \
+ mkdirs$(EXEEXT) recursive-dir-list$(EXEEXT) streams$(EXEEXT)
+subdir = tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
+ $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_asprintf_OBJECTS = asprintf.$(OBJEXT) util.$(OBJEXT)
+asprintf_OBJECTS = $(am_asprintf_OBJECTS)
+asprintf_LDADD = $(LDADD)
+am_encodings_OBJECTS = encodings.$(OBJEXT) encoding.$(OBJEXT) \
+ util.$(OBJEXT)
+encodings_OBJECTS = $(am_encodings_OBJECTS)
+encodings_DEPENDENCIES =
+am_gethostbyname_OBJECTS = gethostbyname.$(OBJEXT) http-host.$(OBJEXT) \
+ util.$(OBJEXT)
+gethostbyname_OBJECTS = $(am_gethostbyname_OBJECTS)
+gethostbyname_DEPENDENCIES =
+am_http_client_bad_body_OBJECTS = http-client-bad-body.$(OBJEXT) \
+ http-url.$(OBJEXT) util.$(OBJEXT)
+http_client_bad_body_OBJECTS = $(am_http_client_bad_body_OBJECTS)
+http_client_bad_body_DEPENDENCIES =
+am_http_client_bad_url_OBJECTS = http-client-bad-url.$(OBJEXT) \
+ util.$(OBJEXT)
+http_client_bad_url_OBJECTS = $(am_http_client_bad_url_OBJECTS)
+http_client_bad_url_DEPENDENCIES =
+http_client_close_after_request_SOURCES = \
+ http-client-close-after-request.c
+http_client_close_after_request_OBJECTS = \
+ http-client-close-after-request.$(OBJEXT)
+http_client_close_after_request_DEPENDENCIES =
+http_server_bad_body_SOURCES = http-server-bad-body.c
+http_server_bad_body_OBJECTS = http-server-bad-body.$(OBJEXT)
+http_server_bad_body_DEPENDENCIES =
+http_server_bad_headers_SOURCES = http-server-bad-headers.c
+http_server_bad_headers_OBJECTS = http-server-bad-headers.$(OBJEXT)
+http_server_bad_headers_DEPENDENCIES =
+am_http_server_charset_OBJECTS = http-server-charset.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_charset_OBJECTS = $(am_http_server_charset_OBJECTS)
+http_server_charset_DEPENDENCIES =
+am_http_server_chunked_OBJECTS = http-server-chunked.$(OBJEXT) \
+ stream.$(OBJEXT) util.$(OBJEXT)
+http_server_chunked_OBJECTS = $(am_http_server_chunked_OBJECTS)
+http_server_chunked_DEPENDENCIES =
+http_server_close_immediately_SOURCES = \
+ http-server-close-immediately.c
+http_server_close_immediately_OBJECTS = \
+ http-server-close-immediately.$(OBJEXT)
+http_server_close_immediately_DEPENDENCIES =
+am_json_OBJECTS = json.$(OBJEXT) encoding.$(OBJEXT) \
+ highlight.$(OBJEXT) instrument-js.$(OBJEXT) \
+ resource-manager.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+json_OBJECTS = $(am_json_OBJECTS)
+json_DEPENDENCIES = ../js/obj/libjs.a
+am_mkdirs_OBJECTS = mkdirs.$(OBJEXT) util.$(OBJEXT)
+mkdirs_OBJECTS = $(am_mkdirs_OBJECTS)
+mkdirs_LDADD = $(LDADD)
+am_recursive_dir_list_OBJECTS = recursive-dir-list.$(OBJEXT) \
+ util.$(OBJEXT)
+recursive_dir_list_OBJECTS = $(am_recursive_dir_list_OBJECTS)
+recursive_dir_list_LDADD = $(LDADD)
+am_streams_OBJECTS = streams.$(OBJEXT) stream.$(OBJEXT) util.$(OBJEXT)
+streams_OBJECTS = $(am_streams_OBJECTS)
+streams_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+DIST_SOURCES = $(asprintf_SOURCES) $(encodings_SOURCES) \
+ $(gethostbyname_SOURCES) $(http_client_bad_body_SOURCES) \
+ $(http_client_bad_url_SOURCES) \
+ http-client-close-after-request.c http-server-bad-body.c \
+ http-server-bad-headers.c $(http_server_charset_SOURCES) \
+ $(http_server_chunked_SOURCES) http-server-close-immediately.c \
+ $(json_SOURCES) $(mkdirs_SOURCES) \
+ $(recursive_dir_list_SOURCES) $(streams_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_SOCKET_LIBS = @EXTRA_SOCKET_LIBS@
+EXTRA_THREAD_LIBS = @EXTRA_THREAD_LIBS@
+EXTRA_TIMER_LIBS = @EXTRA_TIMER_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBICONV = @LIBICONV@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBICONV = @LTLIBICONV@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XP_DEF = @XP_DEF@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = @XP_DEF@ -I../js -I../js/obj
+AM_CXXFLAGS = @XP_DEF@ -I../js -I../js/obj
+asprintf_SOURCES = asprintf.c ../util.c
+encodings_SOURCES = encodings.c ../encoding.c ../util.c
+encodings_LDADD = @LIBICONV@
+gethostbyname_SOURCES = gethostbyname.c ../http-host.c ../util.c
+gethostbyname_LDADD = @EXTRA_SOCKET_LIBS@
+http_client_bad_body_SOURCES = http-client-bad-body.c ../http-url.c ../util.c
+http_client_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+http_client_bad_url_SOURCES = http-client-bad-url.c ../util.c
+http_client_bad_url_LDADD = @EXTRA_SOCKET_LIBS@
+http_client_close_after_request_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_bad_body_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_bad_headers_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_charset_SOURCES = http-server-charset.c ../stream.c ../util.c
+http_server_charset_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_chunked_SOURCES = http-server-chunked.c ../stream.c ../util.c
+http_server_chunked_LDADD = @EXTRA_SOCKET_LIBS@
+http_server_close_immediately_LDADD = @EXTRA_SOCKET_LIBS@
+json_SOURCES = json.c ../encoding.c ../highlight.c ../instrument-js.cpp ../resource-manager.c ../stream.c ../util.c
+json_LDADD = ../js/obj/libjs.a -lm @LIBICONV@ @EXTRA_TIMER_LIBS@
+mkdirs_SOURCES = mkdirs.c ../util.c
+recursive_dir_list_SOURCES = recursive-dir-list.c ../util.c
+streams_SOURCES = streams.c ../stream.c ../util.c
+TESTS = encodings.sh \
+ fatal.sh \
+ help.sh \
+ invalid-option.sh \
+ javascript.sh \
+ javascript-ignore.sh \
+ javascript-utf-8.sh \
+ no-arguments.sh \
+ recursive.sh \
+ recursive-crlf.sh \
+ recursive-exclude.sh \
+ recursive-fatal.sh \
+ recursive-no-instrument.sh \
+ same-directory.sh \
+ version.sh \
+ asprintf.sh \
+ mkdirs.sh \
+ recursive-dir-list.sh \
+ streams.sh \
+ charset.sh \
+ chunked.sh \
+ gethostbyname.sh \
+ json.sh \
+ proxy.sh \
+ proxy-bad-request-body.sh \
+ proxy-bad-response-body.sh \
+ proxy-bad-response-body-javascript.sh \
+ proxy-bad-response-headers.sh \
+ proxy-no-server.sh \
+ proxy-url.sh \
+ server.sh \
+ server-bad-requests.sh \
+ server-close-after-request.sh \
+ server-content-types.sh \
+ server-directory-listing.sh \
+ server-directory-redirect.sh \
+ server-encoded-url.sh \
+ server-error.sh \
+ server-help.sh \
+ server-ip-address.sh \
+ server-shutdown.sh \
+ server-shutdown-bad-method.sh \
+ server-special-file.sh \
+ server-unreadable-directory.sh \
+ server-unreadable-file.sh \
+ server-verbose.sh \
+ server-version.sh \
+ store.sh \
+ store-bad-json.sh \
+ store-bad-request-body.sh \
+ store-bad-response-headers.sh \
+ store-escaped-characters.sh \
+ store-server-bad-body.sh \
+ store-server-closes-immediately.sh \
+ store-source-not-found.sh \
+ store-unreadable-json.sh \
+ store-unwritable-json.sh
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tests/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --foreign tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+clean-noinstPROGRAMS:
+ -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS)
+asprintf$(EXEEXT): $(asprintf_OBJECTS) $(asprintf_DEPENDENCIES)
+ @rm -f asprintf$(EXEEXT)
+ $(LINK) $(asprintf_OBJECTS) $(asprintf_LDADD) $(LIBS)
+encodings$(EXEEXT): $(encodings_OBJECTS) $(encodings_DEPENDENCIES)
+ @rm -f encodings$(EXEEXT)
+ $(LINK) $(encodings_OBJECTS) $(encodings_LDADD) $(LIBS)
+gethostbyname$(EXEEXT): $(gethostbyname_OBJECTS) $(gethostbyname_DEPENDENCIES)
+ @rm -f gethostbyname$(EXEEXT)
+ $(LINK) $(gethostbyname_OBJECTS) $(gethostbyname_LDADD) $(LIBS)
+http-client-bad-body$(EXEEXT): $(http_client_bad_body_OBJECTS) $(http_client_bad_body_DEPENDENCIES)
+ @rm -f http-client-bad-body$(EXEEXT)
+ $(LINK) $(http_client_bad_body_OBJECTS) $(http_client_bad_body_LDADD) $(LIBS)
+http-client-bad-url$(EXEEXT): $(http_client_bad_url_OBJECTS) $(http_client_bad_url_DEPENDENCIES)
+ @rm -f http-client-bad-url$(EXEEXT)
+ $(LINK) $(http_client_bad_url_OBJECTS) $(http_client_bad_url_LDADD) $(LIBS)
+http-client-close-after-request$(EXEEXT): $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_DEPENDENCIES)
+ @rm -f http-client-close-after-request$(EXEEXT)
+ $(LINK) $(http_client_close_after_request_OBJECTS) $(http_client_close_after_request_LDADD) $(LIBS)
+http-server-bad-body$(EXEEXT): $(http_server_bad_body_OBJECTS) $(http_server_bad_body_DEPENDENCIES)
+ @rm -f http-server-bad-body$(EXEEXT)
+ $(LINK) $(http_server_bad_body_OBJECTS) $(http_server_bad_body_LDADD) $(LIBS)
+http-server-bad-headers$(EXEEXT): $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_DEPENDENCIES)
+ @rm -f http-server-bad-headers$(EXEEXT)
+ $(LINK) $(http_server_bad_headers_OBJECTS) $(http_server_bad_headers_LDADD) $(LIBS)
+http-server-charset$(EXEEXT): $(http_server_charset_OBJECTS) $(http_server_charset_DEPENDENCIES)
+ @rm -f http-server-charset$(EXEEXT)
+ $(LINK) $(http_server_charset_OBJECTS) $(http_server_charset_LDADD) $(LIBS)
+http-server-chunked$(EXEEXT): $(http_server_chunked_OBJECTS) $(http_server_chunked_DEPENDENCIES)
+ @rm -f http-server-chunked$(EXEEXT)
+ $(LINK) $(http_server_chunked_OBJECTS) $(http_server_chunked_LDADD) $(LIBS)
+http-server-close-immediately$(EXEEXT): $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_DEPENDENCIES)
+ @rm -f http-server-close-immediately$(EXEEXT)
+ $(LINK) $(http_server_close_immediately_OBJECTS) $(http_server_close_immediately_LDADD) $(LIBS)
+json$(EXEEXT): $(json_OBJECTS) $(json_DEPENDENCIES)
+ @rm -f json$(EXEEXT)
+ $(CXXLINK) $(json_OBJECTS) $(json_LDADD) $(LIBS)
+mkdirs$(EXEEXT): $(mkdirs_OBJECTS) $(mkdirs_DEPENDENCIES)
+ @rm -f mkdirs$(EXEEXT)
+ $(LINK) $(mkdirs_OBJECTS) $(mkdirs_LDADD) $(LIBS)
+recursive-dir-list$(EXEEXT): $(recursive_dir_list_OBJECTS) $(recursive_dir_list_DEPENDENCIES)
+ @rm -f recursive-dir-list$(EXEEXT)
+ $(LINK) $(recursive_dir_list_OBJECTS) $(recursive_dir_list_LDADD) $(LIBS)
+streams$(EXEEXT): $(streams_OBJECTS) $(streams_DEPENDENCIES)
+ @rm -f streams$(EXEEXT)
+ $(LINK) $(streams_OBJECTS) $(streams_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asprintf.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encodings.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gethostbyname.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/highlight.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client-bad-body.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client-bad-url.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-client-close-after-request.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-host.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-bad-body.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-bad-headers.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-charset.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-chunked.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-server-close-immediately.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http-url.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instrument-js.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/json.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkdirs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recursive-dir-list.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/resource-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/streams.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+util.o: ../util.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.o -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../util.c' object='util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.o `test -f '../util.c' || echo '$(srcdir)/'`../util.c
+
+util.obj: ../util.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT util.obj -MD -MP -MF $(DEPDIR)/util.Tpo -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/util.Tpo $(DEPDIR)/util.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../util.c' object='util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o util.obj `if test -f '../util.c'; then $(CYGPATH_W) '../util.c'; else $(CYGPATH_W) '$(srcdir)/../util.c'; fi`
+
+encoding.o: ../encoding.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.o -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../encoding.c' object='encoding.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.o `test -f '../encoding.c' || echo '$(srcdir)/'`../encoding.c
+
+encoding.obj: ../encoding.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT encoding.obj -MD -MP -MF $(DEPDIR)/encoding.Tpo -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/encoding.Tpo $(DEPDIR)/encoding.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../encoding.c' object='encoding.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o encoding.obj `if test -f '../encoding.c'; then $(CYGPATH_W) '../encoding.c'; else $(CYGPATH_W) '$(srcdir)/../encoding.c'; fi`
+
+http-host.o: ../http-host.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.o -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-host.c' object='http-host.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.o `test -f '../http-host.c' || echo '$(srcdir)/'`../http-host.c
+
+http-host.obj: ../http-host.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-host.obj -MD -MP -MF $(DEPDIR)/http-host.Tpo -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-host.Tpo $(DEPDIR)/http-host.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-host.c' object='http-host.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-host.obj `if test -f '../http-host.c'; then $(CYGPATH_W) '../http-host.c'; else $(CYGPATH_W) '$(srcdir)/../http-host.c'; fi`
+
+http-url.o: ../http-url.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.o -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-url.c' object='http-url.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.o `test -f '../http-url.c' || echo '$(srcdir)/'`../http-url.c
+
+http-url.obj: ../http-url.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT http-url.obj -MD -MP -MF $(DEPDIR)/http-url.Tpo -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/http-url.Tpo $(DEPDIR)/http-url.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../http-url.c' object='http-url.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o http-url.obj `if test -f '../http-url.c'; then $(CYGPATH_W) '../http-url.c'; else $(CYGPATH_W) '$(srcdir)/../http-url.c'; fi`
+
+stream.o: ../stream.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.o -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../stream.c' object='stream.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.o `test -f '../stream.c' || echo '$(srcdir)/'`../stream.c
+
+stream.obj: ../stream.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stream.obj -MD -MP -MF $(DEPDIR)/stream.Tpo -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/stream.Tpo $(DEPDIR)/stream.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../stream.c' object='stream.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stream.obj `if test -f '../stream.c'; then $(CYGPATH_W) '../stream.c'; else $(CYGPATH_W) '$(srcdir)/../stream.c'; fi`
+
+highlight.o: ../highlight.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.o -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../highlight.c' object='highlight.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.o `test -f '../highlight.c' || echo '$(srcdir)/'`../highlight.c
+
+highlight.obj: ../highlight.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT highlight.obj -MD -MP -MF $(DEPDIR)/highlight.Tpo -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/highlight.Tpo $(DEPDIR)/highlight.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../highlight.c' object='highlight.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o highlight.obj `if test -f '../highlight.c'; then $(CYGPATH_W) '../highlight.c'; else $(CYGPATH_W) '$(srcdir)/../highlight.c'; fi`
+
+resource-manager.o: ../resource-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.o -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../resource-manager.c' object='resource-manager.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.o `test -f '../resource-manager.c' || echo '$(srcdir)/'`../resource-manager.c
+
+resource-manager.obj: ../resource-manager.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT resource-manager.obj -MD -MP -MF $(DEPDIR)/resource-manager.Tpo -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/resource-manager.Tpo $(DEPDIR)/resource-manager.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../resource-manager.c' object='resource-manager.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o resource-manager.obj `if test -f '../resource-manager.c'; then $(CYGPATH_W) '../resource-manager.c'; else $(CYGPATH_W) '$(srcdir)/../resource-manager.c'; fi`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+instrument-js.o: ../instrument-js.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.o -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../instrument-js.cpp' object='instrument-js.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.o `test -f '../instrument-js.cpp' || echo '$(srcdir)/'`../instrument-js.cpp
+
+instrument-js.obj: ../instrument-js.cpp
+@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT instrument-js.obj -MD -MP -MF $(DEPDIR)/instrument-js.Tpo -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/instrument-js.Tpo $(DEPDIR)/instrument-js.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='../instrument-js.cpp' object='instrument-js.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o instrument-js.obj `if test -f '../instrument-js.cpp'; then $(CYGPATH_W) '../instrument-js.cpp'; else $(CYGPATH_W) '$(srcdir)/../instrument-js.cpp'; fi`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; ws='[ ]'; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ echo "XPASS: $$tst"; \
+ ;; \
+ *) \
+ echo "PASS: $$tst"; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *$$ws$$tst$$ws*) \
+ xfail=`expr $$xfail + 1`; \
+ echo "XFAIL: $$tst"; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ echo "FAIL: $$tst"; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ echo "SKIP: $$tst"; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="All $$all tests behaved as expected ($$xfail expected failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all tests failed"; \
+ else \
+ banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ skipped="($$skip tests were not run)"; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-noinstPROGRAMS ctags distclean \
+ distclean-compile distclean-generic distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c
new file mode 100644
index 0000000..7f8246b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.c
@@ -0,0 +1,42 @@
+/*
+ asprintf.c - test `asprintf' function
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+int main(void) {
+ int result;
+ char * s;
+
+ result = asprintf(&s, "%s %d %c", "abc", 123, 'x');
+ assert(result == 9);
+ assert(strcmp("abc 123 x", s) == 0);
+ free(s);
+
+ char * long_string = "abcdefghijklmnopqrstuvwxyz";
+ result = asprintf(&s, "%s %s %s %s", long_string, long_string, long_string, long_string);
+ assert(result == 107);
+ assert(strcmp("abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz", s) == 0);
+ free(s);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh
new file mode 100755
index 0000000..c7843e4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/asprintf.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# asprintf.sh - test `asprintf' function
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./asprintf
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/charset.sh b/tools/node_modules/expresso/deps/jscoverage/tests/charset.sh
new file mode 100755
index 0000000..9fb07eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/charset.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+# charset.sh - test jscoverage-server with different charset values
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+cleanup() {
+ shutdown
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+$VALGRIND jscoverage-server --proxy --no-highlight > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+./http-server-charset &
+origin_server_pid=$!
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ cat ../report.js > EXPECTED
+ cat javascript-utf-8.expected/javascript-utf-8.js | sed 's/javascript-utf-8.js/http:\/\/127.0.0.1:8000\/utf-8.js/g' >> EXPECTED
+ curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/utf-8.js > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/utf-8.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+shutdown
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ cat ../report.js > EXPECTED
+ cat javascript.expected/javascript-iso-8859-1.js | sed 's/javascript-iso-8859-1.js/http:\/\/127.0.0.1:8000\/iso-8859-1.js/g' >> EXPECTED
+ curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/iso-8859-1.js > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/iso-8859-1.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+# bogus charset
+echo 500 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/bogus.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# malformed encoding
+case "$character_encoding_support" in
+ yes)
+ status=502
+ ;;
+ *)
+ status=500
+ ;;
+esac
+echo $status > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/malformed.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/chunked.sh b/tools/node_modules/expresso/deps/jscoverage/tests/chunked.sh
new file mode 100755
index 0000000..2986552
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/chunked.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+# chunked.sh - test jscoverage-server with Transfer-Encoding: chunked
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+cleanup() {
+ shutdown
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+./http-server-chunked &
+origin_server_pid=$!
+
+sleep $delay
+
+echo 'hello world' > EXPECTED
+curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/lower > ACTUAL
+diff EXPECTED ACTUAL
+
+echo 'HELLO WORLD' > EXPECTED
+curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/upper > ACTUAL
+diff EXPECTED ACTUAL
+
+# curl doesn't understand trailers ???
+# echo 'hello world' > EXPECTED
+# curl -s -x 127.0.0.1:8080 http://127.0.0.1:8000/trailer > ACTUAL
+# diff EXPECTED ACTUAL
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/overflow 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -o /dev/null -x 127.0.0.1:8080 http://127.0.0.1:8000/javascript 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -o /dev/null -x 127.0.0.1:8080 http://127.0.0.1:8000/multiple 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/common.sh b/tools/node_modules/expresso/deps/jscoverage/tests/common.sh
new file mode 100644
index 0000000..e55b342
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/common.sh
@@ -0,0 +1,7 @@
+export PATH=.:..:../js/obj:$PATH
+
+json_cmp() {
+ echo 'EXPECTED = ' | cat - $1 > EXPECTED
+ echo 'ACTUAL = ' | cat - $2 > ACTUAL
+ js -f EXPECTED -f ACTUAL -f json-cmp.js
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err
new file mode 100644
index 0000000..8a59e6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-existing-directory.expected.err
@@ -0,0 +1,2 @@
+jscoverage: refusing to overwrite directory: bar
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err
new file mode 100644
index 0000000..bb3778d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/destination-is-file.expected.err
@@ -0,0 +1,2 @@
+jscoverage: not a directory: bar
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err
new file mode 100644
index 0000000..4b3fd0c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/encoding-requires-argument.expected.err
@@ -0,0 +1,2 @@
+jscoverage: --encoding: option requires an argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/encodings.c b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.c
new file mode 100644
index 0000000..26f8707
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.c
@@ -0,0 +1,223 @@
+/*
+ encodings.c - test handling different character encodings
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "encoding.h"
+#include "stream.h"
+
+int main(void) {
+ jschar * characters;
+ size_t num_characters;
+ int result;
+
+ /* e, e grave, e acute, e circumflex */
+ uint8_t utf8[] = {
+ 'e',
+ 0xc3,
+ 0xa8,
+ 0xc3,
+ 0xa9,
+ 0xc3,
+ 0xaa,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-8", utf8, 7, &characters, &num_characters);
+
+#if HAVE_ICONV || HAVE_MULTIBYTETOWIDECHAR
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ /*
+ BOM is 0xfeff
+ = 1111 1110 1111 1111
+ UTF: 1110---- 10------ 10------
+ = 11101111 10111011 10111111
+ = EF BB BF
+ */
+ uint8_t utf8_with_bom[] = {
+ 0xef,
+ 0xbb,
+ 0xbf,
+ 'e',
+ 0xc3,
+ 0xa8,
+ 0xc3,
+ 0xa9,
+ 0xc3,
+ 0xaa,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-8", utf8_with_bom, 10, &characters, &num_characters);
+
+#if HAVE_ICONV || HAVE_MULTIBYTETOWIDECHAR
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16be[] = {
+ 0, 'e',
+ 0, 0xe8,
+ 0, 0xe9,
+ 0, 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16BE", utf16be, 8, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16be_with_bom[] = {
+ 0xfe, 0xff,
+ 0, 'e',
+ 0, 0xe8,
+ 0, 0xe9,
+ 0, 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16BE", utf16be_with_bom, 10, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16le[] = {
+ 'e', 0,
+ 0xe8, 0,
+ 0xe9, 0,
+ 0xea, 0,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16LE", utf16le, 8, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ uint8_t utf16le_with_bom[] = {
+ 0xff, 0xfe,
+ 'e', 0,
+ 0xe8, 0,
+ 0xe9, 0,
+ 0xea, 0,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-16LE", utf16le_with_bom, 10, &characters, &num_characters);
+
+#ifdef HAVE_ICONV
+ assert(result == 0);
+ assert(num_characters == 4);
+ assert(characters[0] == 'e');
+ assert(characters[1] == 0xe8);
+ assert(characters[2] == 0xe9);
+ assert(characters[3] == 0xea);
+
+ free(characters);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ /* bogus encoding */
+ uint8_t bogus[] = {'b', 'o', 'g', 'u', 's'};
+
+ result = jscoverage_bytes_to_characters("BOGUS", bogus, 5, &characters, &num_characters);
+
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+
+#ifdef HAVE_ICONV
+ /* malformed US-ASCII */
+ /* NOTE: Windows simply discards the high bit */
+ uint8_t malformed_ascii[] = {
+ 'e',
+ 0xe8,
+ 0xe9,
+ 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("US-ASCII", malformed_ascii, 4, &characters, &num_characters);
+
+ assert(result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE);
+#endif
+
+ /* malformed UTF-8 */
+ uint8_t malformed_utf8[] = {
+ 'e',
+ 0xe8,
+ 0xe9,
+ 0xea,
+ };
+
+ result = jscoverage_bytes_to_characters("UTF-8", malformed_utf8, 4, &characters, &num_characters);
+
+#if HAVE_ICONV || HAVE_MULTIBYTETOWIDECHAR
+ assert(result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE);
+#else
+ assert(result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED);
+#endif
+
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/encodings.sh b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.sh
new file mode 100755
index 0000000..5db0f13
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/encodings.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# encodings.sh - test handling different character encodings
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./encodings
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err
new file mode 100644
index 0000000..6feb597
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/exclude-requires-argument.expected.err
@@ -0,0 +1,2 @@
+jscoverage: --exclude: option requires an argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/fatal.sh b/tools/node_modules/expresso/deps/jscoverage/tests/fatal.sh
new file mode 100755
index 0000000..90b8d94
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/fatal.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+# fatal.sh - test various fatal errors
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR DIR2 OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR DIR2
+
+$VALGRIND jscoverage javascript-xml DIR > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr javascript-xml.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage javascript-invalid DIR > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr javascript-invalid.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage javascript-setter DIR > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr javascript-setter.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage 1 2 3 > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr too-many-arguments.expected.err ERR
+
+rm -fr DIR
+
+$VALGRIND jscoverage --no-instrument > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr no-instrument-requires-argument.expected.err ERR
+
+$VALGRIND jscoverage --exclude > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr exclude-requires-argument.expected.err ERR
+
+$VALGRIND jscoverage --encoding > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr encoding-requires-argument.expected.err ERR
+
+# first arg does not exist
+rm -f foo
+$VALGRIND jscoverage foo bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr source-does-not-exist.expected.err ERR
+
+# first arg is file
+touch foo
+$VALGRIND jscoverage foo bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr source-is-file.expected.err ERR
+rm foo
+
+# second arg is file
+rm -fr bar
+touch bar
+$VALGRIND jscoverage javascript bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr destination-is-file.expected.err ERR
+rm bar
+
+# second arg is directory, but not from previous run
+rm -fr bar
+mkdir bar
+touch bar/foo
+$VALGRIND jscoverage javascript bar > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+# diff --strip-trailing-cr destination-is-existing-directory.expected.err ERR
+rm -fr bar
+
+# huge JavaScript file
+mkdir -p DIR
+perl -e 'for (1 .. 65536) {print "x = $_\n";}' > DIR/big.js
+$VALGRIND jscoverage DIR DIR2 > OUT 2> ERR && exit 1
+echo 'jscoverage: file big.js contains more than 65,535 lines' | diff --strip-trailing-cr - ERR
+
+rm -fr DIR DIR2 OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c
new file mode 100644
index 0000000..ef5d7b3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.c
@@ -0,0 +1,53 @@
+/*
+ gethostbyname.c - test host lookup
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "http-server.h"
+
+int main(int argc, char ** argv) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ if (argc < 2) {
+ exit(EXIT_FAILURE);
+ }
+
+ struct in_addr a;
+ if (xgethostbyname(argv[1], &a) != 0) {
+ exit(EXIT_FAILURE);
+ }
+ char * result = inet_ntoa(a);
+ printf("%s\n", result);
+
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh
new file mode 100755
index 0000000..eae74e3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/gethostbyname.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# gethostbyname.sh - test host lookup
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+echo 127.0.0.1 > EXPECTED
+./gethostbyname localhost > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+! ./gethostbyname foo
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/help.sh b/tools/node_modules/expresso/deps/jscoverage/tests/help.sh
new file mode 100755
index 0000000..5aaa31a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/help.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+# help.sh - test `--help' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage --help > OUT 2> ERR
+test -s OUT
+test ! -s ERR
+diff --strip-trailing-cr ../jscoverage-help.txt OUT
+
+$VALGRIND jscoverage -h > OUT 2> ERR
+test -s OUT
+test ! -s ERR
+diff --strip-trailing-cr ../jscoverage-help.txt OUT
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c
new file mode 100644
index 0000000..9985c62
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-body.c
@@ -0,0 +1,98 @@
+/*
+ http-client-bad-body.c - HTTP client that outputs a bad body
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#include <unistd.h>
+
+#include "http-server.h"
+#include "util.h"
+
+int main(int argc, char ** argv) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ int result;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s PORT URL\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ uint16_t connect_port = atoi(argv[1]);
+ char * url = argv[2];
+ char * host;
+ uint16_t port;
+ char * abs_path;
+ char * query;
+ result = URL_parse(url, &host, &port, &abs_path, &query);
+ assert(result == 0);
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(connect_port);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ result = connect(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ /* send request */
+ char * message;
+ xasprintf(&message, "POST %s HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\nHello\n", url);
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(s, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ /* read response */
+ for (;;) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(s, buffer, 8192, 0);
+ assert(bytes_read >= 0);
+ if (bytes_read == 0) {
+ break;
+ }
+ }
+
+ closesocket(s);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c
new file mode 100644
index 0000000..fdb917b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-bad-url.c
@@ -0,0 +1,77 @@
+/*
+ http-client-bad-url.c - HTTP client that sends bad URLs
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "http-server.h"
+#include "util.h"
+
+int main(int argc, char ** argv) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ int result;
+
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s PORT URL\n", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ uint16_t connect_port = atoi(argv[1]);
+ char * url = argv[2];
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(connect_port);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ result = connect(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ /* send request */
+ char * message;
+ xasprintf(&message, "GET %s HTTP/1.1\r\nConnection: close\r\n\r\n", url);
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(s, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ /* read response */
+ for (;;) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(s, buffer, 8192, 0);
+ assert(bytes_read >= 0);
+ if (bytes_read == 0) {
+ break;
+ }
+ }
+
+ closesocket(s);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c
new file mode 100644
index 0000000..e67431a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-client-close-after-request.c
@@ -0,0 +1,57 @@
+/*
+ http-client-close-after-request.c - HTTP client that closes connection after sending request
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ int result;
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ result = connect(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ /* send request */
+ char * message = "GET http://127.0.0.1:8000/ HTTP/1.1\r\nConnection: close\r\nHost: 127.0.0.1:8000\r\n\r\n";
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(s, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(s);
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c
new file mode 100644
index 0000000..f8c362d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-body.c
@@ -0,0 +1,97 @@
+/*
+ http-server-bad-body.c - HTTP server that outputs a bad body
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ }
+ }
+ }
+
+ /* send response */
+ char * message = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-type: text/html\r\nTransfer-Encoding: chunked\r\n\r\nHello\n";
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c
new file mode 100644
index 0000000..bbef80f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-bad-headers.c
@@ -0,0 +1,97 @@
+/*
+ http-server-bad-headers.c - HTTP server that outputs bad headers
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ }
+ }
+ }
+
+ /* send response */
+ char * message = "HTTP/1.1 200 OK\r\nHere is some bogosity!\r\nConnection: close\r\nContent-type: text/html\r\n\r\nHello\n";
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c
new file mode 100644
index 0000000..7ea7bb8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-charset.c
@@ -0,0 +1,144 @@
+/*
+ http-server-charset.c - HTTP server that outputs different charset values
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+#include "stream.h"
+#include "util.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ Stream * stream = Stream_new(0);
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ Stream_write(stream, buffer, bytes_read);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ char * method;
+ char * url;
+ char * request_line = (char *) stream->data;
+ char * first_space = strchr(request_line, ' ');
+ assert(first_space != NULL);
+ char * second_space = strchr(first_space + 1, ' ');
+ assert(second_space != NULL);
+ method = xstrndup(request_line, first_space - request_line);
+ url = xstrndup(first_space + 1, second_space - (first_space + 1));
+
+ /* send response */
+ char * message;
+ if (strcmp(url, "http://127.0.0.1:8000/utf-8.js") == 0 || strcmp(url, "/utf-8.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=UTF-8\r\n"
+ "\r\n"
+ "var s = 'eèéê';\n"
+ "var r = /eèéê/;\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/iso-8859-1.js") == 0 || strcmp(url, "/iso-8859-1.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=ISO-8859-1\r\n"
+ "\r\n"
+ "var s = 'eèéê';\n"
+ "var r = /eèéê/;\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/bogus.js") == 0 || strcmp(url, "/bogus.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=BOGUS\r\n"
+ "\r\n"
+ "var s = 'eèéê';\n"
+ "var r = /eèéê/;\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/malformed.js") == 0 || strcmp(url, "/malformed.js") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/javascript; charset=UTF-8\r\n"
+ "\r\n"
+ "var s = 'eèéê';\n"
+ "var r = /eèéê/;\n";
+ }
+ else {
+ abort();
+ }
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c
new file mode 100644
index 0000000..909cb07
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-chunked.c
@@ -0,0 +1,196 @@
+/*
+ http-server-chunked.c - HTTP server that outputs chunked response
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include "http-server.h"
+#include "stream.h"
+#include "util.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+
+ /* read request */
+ Stream * stream = Stream_new(0);
+ int state = 0;
+ while (state != 2) {
+ uint8_t buffer[8192];
+ ssize_t bytes_read = recv(client_socket, buffer, 8192, 0);
+ assert(bytes_read > 0);
+ Stream_write(stream, buffer, bytes_read);
+ for (int i = 0; i < bytes_read && state != 2; i++) {
+ uint8_t byte = buffer[i];
+ switch (state) {
+ case 0:
+ if (byte == '\n') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ case 1:
+ if (byte == '\n') {
+ state = 2;
+ }
+ else if (byte == '\r') {
+ state = 1;
+ }
+ else {
+ state = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ char * method;
+ char * url;
+ char * request_line = (char *) stream->data;
+ char * first_space = strchr(request_line, ' ');
+ assert(first_space != NULL);
+ char * second_space = strchr(first_space + 1, ' ');
+ assert(second_space != NULL);
+ method = xstrndup(request_line, first_space - request_line);
+ url = xstrndup(first_space + 1, second_space - (first_space + 1));
+
+ /* send response */
+ char * message;
+ if (strcmp(url, "http://127.0.0.1:8000/lower") == 0 || strcmp(url, "/lower") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "b\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/upper") == 0 || strcmp(url, "/upper") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "B\r\n"
+ "HELLO WORLD\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/javascript") == 0 || strcmp(url, "/javascript") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-Type: text/javascript\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "B\r\n"
+ "hello = 10;\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/trailer") == 0 || strcmp(url, "/trailer") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "b\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "X-Foo: bar\r\n"
+ "X-Bar: foo\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/overflow") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: chunked\r\n"
+ "\r\n"
+ "100000000\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else if (strcmp(url, "http://127.0.0.1:8000/multiple") == 0) {
+ message = "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Content-type: text/html\r\n"
+ "Transfer-Encoding: foo; foo = bar, bar; foo = \"bar\"\r\n"
+ "Transfer-Encoding: foobar; foo = \"\\\"bar\\\"\", chunked\r\n"
+ "\r\n"
+ "b\r\n"
+ "hello world\r\n"
+ "1\r\n"
+ "\n\r\n"
+ "0\r\n"
+ "\r\n";
+ }
+ else {
+ abort();
+ }
+ size_t message_length = strlen(message);
+ ssize_t bytes_sent = send(client_socket, message, message_length, 0);
+ assert(bytes_sent == (ssize_t) message_length);
+
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c
new file mode 100644
index 0000000..b8c7176
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/http-server-close-immediately.c
@@ -0,0 +1,60 @@
+/*
+ http-server-close-immediately.c - HTTP server that closes connection immediately
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "http-server.h"
+
+int main(void) {
+#ifdef __MINGW32__
+ WSADATA data;
+ if (WSAStartup(MAKEWORD(1, 1), &data) != 0) {
+ return 1;
+ }
+#endif
+
+ SOCKET s = socket(PF_INET, SOCK_STREAM, 0);
+ assert(s != INVALID_SOCKET);
+
+ int optval = 1;
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *) &optval, sizeof(optval));
+
+ struct sockaddr_in a;
+ a.sin_family = AF_INET;
+ a.sin_port = htons(8000);
+ a.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ int result = bind(s, (struct sockaddr *) &a, sizeof(a));
+ assert(result == 0);
+
+ result = listen(s, 5);
+ assert(result == 0);
+
+ for (;;) {
+ struct sockaddr_in client_address;
+ size_t size = sizeof(client_address);
+ int client_socket = accept(s, (struct sockaddr *) &client_address, &size);
+ assert(client_socket > 0);
+ closesocket(client_socket);
+ }
+ return 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err
new file mode 100644
index 0000000..91538d9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.expected.err
@@ -0,0 +1,2 @@
+jscoverage: unrecognized option `--foo'
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh
new file mode 100755
index 0000000..bf9607c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/invalid-option.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# invalid-option.sh - test invalid option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage --foo > OUT 2> ERR && exit 1
+test ! -s OUT
+diff --strip-trailing-cr invalid-option.expected.err ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js
new file mode 100644
index 0000000..824f204
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.expected/ignore.js
@@ -0,0 +1,106 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['ignore.js']) {
+ _$jscoverage['ignore.js'] = [];
+ _$jscoverage['ignore.js'][1] = 0;
+ _$jscoverage['ignore.js'][3] = 0;
+ _$jscoverage['ignore.js'][4] = 0;
+ _$jscoverage['ignore.js'][6] = 0;
+ _$jscoverage['ignore.js'][7] = 0;
+ _$jscoverage['ignore.js'][10] = 0;
+ _$jscoverage['ignore.js'][14] = 0;
+ _$jscoverage['ignore.js'][16] = 0;
+ _$jscoverage['ignore.js'][17] = 0;
+ _$jscoverage['ignore.js'][22] = 0;
+ _$jscoverage['ignore.js'][23] = 0;
+ _$jscoverage['ignore.js'][27] = 0;
+ _$jscoverage['ignore.js'][32] = 0;
+ _$jscoverage['ignore.js'][34] = 0;
+ _$jscoverage['ignore.js'][35] = 0;
+ _$jscoverage['ignore.js'][37] = 0;
+ _$jscoverage['ignore.js'][38] = 0;
+ _$jscoverage['ignore.js'][42] = 0;
+ _$jscoverage['ignore.js'][43] = 0;
+ _$jscoverage['ignore.js'][44] = 0;
+}
+_$jscoverage['ignore.js'].conditionals = [];
+_$jscoverage['ignore.js'][1]++;
+function createRequest() {
+ _$jscoverage['ignore.js'][3]++;
+ if (window.XMLHttpRequest) {
+ _$jscoverage['ignore.js'].conditionals[6] = 11;
+ _$jscoverage['ignore.js'][4]++;
+ return new XMLHttpRequest();
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[4] = 5;
+ _$jscoverage['ignore.js'][6]++;
+ if (window.ActiveXObject) {
+ _$jscoverage['ignore.js'].conditionals[9] = 11;
+ _$jscoverage['ignore.js'][7]++;
+ return new ActiveXObject("Msxml2.XMLHTTP");
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[7] = 8;
+ _$jscoverage['ignore.js'][10]++;
+ throw "no XMLHttpRequest implementation available";
+ }
+ }
+}
+_$jscoverage['ignore.js'][14]++;
+function createRequest2() {
+ _$jscoverage['ignore.js'][16]++;
+ if (window.XMLHttpRequest) {
+ _$jscoverage['ignore.js'][17]++;
+ return new XMLHttpRequest();
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[17] = 18;
+ }
+ _$jscoverage['ignore.js'][22]++;
+ if (window.ActiveXObject) {
+ _$jscoverage['ignore.js'][23]++;
+ return new ActiveXObject("Msxml2.XMLHTTP");
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[23] = 24;
+ }
+ _$jscoverage['ignore.js'][27]++;
+ throw "no XMLHttpRequest implementation available";
+}
+_$jscoverage['ignore.js'][32]++;
+function log(s) {
+ _$jscoverage['ignore.js'][34]++;
+ if (window.console && window.console.log) {
+ _$jscoverage['ignore.js'].conditionals[37] = 39;
+ _$jscoverage['ignore.js'][35]++;
+ console.log(s);
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[35] = 36;
+ _$jscoverage['ignore.js'][37]++;
+ if (window.opera && window.opera.postError) {
+ _$jscoverage['ignore.js'][38]++;
+ opera.postError(s);
+ }
+ else {
+ _$jscoverage['ignore.js'].conditionals[38] = 39;
+ }
+ }
+}
+_$jscoverage['ignore.js'][42]++;
+var request = createRequest();
+_$jscoverage['ignore.js'][43]++;
+var request2 = createRequest2();
+_$jscoverage['ignore.js'][44]++;
+log("created requests");
+if (!( 0)) {
+ _$jscoverage['ignore.js'].conditionals[26] = 28;
+}
+if (!( ! window.XMLHttpRequest)) {
+ _$jscoverage['ignore.js'].conditionals[20] = 29;
+}
+_$jscoverage['ignore.js'].source = ["function createRequest() {","//#JSCOVERAGE_IF"," if (window.XMLHttpRequest) {"," return new XMLHttpRequest();"," }"," else if (window.ActiveXObject) {"," return new ActiveXObject('Msxml2.XMLHTTP');"," }"," else {"," throw 'no XMLHttpRequest implementation available';"," }","}","","function createRequest2() {","//#JSCOVERAGE_IF"," if (window.XMLHttpRequest) {"," return new XMLHttpRequest();"," }","","//#JSCOVERAGE_IF ! window.XMLHttpRequest","//#JSCOVERAGE_IF"," if (window.ActiveXObject) {"," return new ActiveXObject('Msxml2.XMLHTTP');"," }","","//#JSCOVERAGE_IF 0"," throw 'no XMLHttpRequest implementation available';","//#JSCOVERAGE_ENDIF","//#JSCOVERAGE_ENDIF","}","","function log(s) {","//#JSCOVERAGE_IF"," if (window.console &amp;&amp; window.console.log) {"," console.log(s);"," }"," else if (window.opera &amp;&amp; window.opera.postError) {"," opera.postError(s);"," }","}","","var request = createRequest();","var request2 = createRequest2();","log('created requests');"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh
new file mode 100755
index 0000000..ec1edbd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# javascript-ignore.sh - test ignoring lines of code
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+$VALGRIND jscoverage --no-highlight javascript-ignore DIR
+diff -u --strip-trailing-cr javascript-ignore.expected/ignore.js DIR/ignore.js
+rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js
new file mode 100644
index 0000000..8579ff0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-ignore/ignore.js
@@ -0,0 +1,44 @@
+function createRequest() {
+//#JSCOVERAGE_IF
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+ else if (window.ActiveXObject) {
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ }
+ else {
+ throw 'no XMLHttpRequest implementation available';
+ }
+}
+
+function createRequest2() {
+//#JSCOVERAGE_IF
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+
+//#JSCOVERAGE_IF ! window.XMLHttpRequest
+//#JSCOVERAGE_IF
+ if (window.ActiveXObject) {
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ }
+
+//#JSCOVERAGE_IF 0
+ throw 'no XMLHttpRequest implementation available';
+//#JSCOVERAGE_ENDIF
+//#JSCOVERAGE_ENDIF
+}
+
+function log(s) {
+//#JSCOVERAGE_IF
+ if (window.console && window.console.log) {
+ console.log(s);
+ }
+ else if (window.opera && window.opera.postError) {
+ opera.postError(s);
+ }
+}
+
+var request = createRequest();
+var request2 = createRequest2();
+log('created requests');
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err
new file mode 100644
index 0000000..bd39cb1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid.expected.err
@@ -0,0 +1,2 @@
+jscoverage:javascript-invalid.js:1: SyntaxError: missing ; before statement
+jscoverage: parse error in file javascript-invalid.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js
new file mode 100644
index 0000000..74b863c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-invalid/javascript-invalid.js
@@ -0,0 +1 @@
+x y
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err
new file mode 100644
index 0000000..d353089
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter.expected.err
@@ -0,0 +1 @@
+jscoverage:javascript-setter.js:2: expected function
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js
new file mode 100644
index 0000000..715bc1e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-setter/javascript-setter.js
@@ -0,0 +1,3 @@
+var obj = {
+ x setter: 3
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js
new file mode 100644
index 0000000..fa04a2c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.expected/javascript-utf-8.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-utf-8.js']) {
+ _$jscoverage['javascript-utf-8.js'] = [];
+ _$jscoverage['javascript-utf-8.js'][1] = 0;
+ _$jscoverage['javascript-utf-8.js'][2] = 0;
+}
+_$jscoverage['javascript-utf-8.js'][1]++;
+var s = "e\u00e8\u00e9\u00ea";
+_$jscoverage['javascript-utf-8.js'][2]++;
+var r = /e\u00e8\u00e9\u00ea/;
+_$jscoverage['javascript-utf-8.js'].source = ["var s = 'e&#232;&#233;&#234;';","var r = /e&#232;&#233;&#234;/;"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh
new file mode 100755
index 0000000..bada1bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+# javascript-utf-8.sh - test a JavaScript file with UTF-8 encoding
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+rm -fr DIR
+case "$character_encoding_support" in
+ yes)
+ $VALGRIND jscoverage --no-highlight --encoding=UTF-8 javascript-utf-8 DIR
+ diff -u --strip-trailing-cr javascript-utf-8.expected/javascript-utf-8.js DIR/javascript-utf-8.js
+ ;;
+ *)
+ ! $VALGRIND jscoverage --no-highlight --encoding=UTF-8 javascript-utf-8 DIR > OUT 2> ERR
+ echo "jscoverage: encoding UTF-8 not supported" | diff - ERR
+ ;;
+esac
+rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js
new file mode 100644
index 0000000..799cd6e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-utf-8/javascript-utf-8.js
@@ -0,0 +1,2 @@
+var s = 'eèéê';
+var r = /eèéê/;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err
new file mode 100644
index 0000000..017c45e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml.expected.err
@@ -0,0 +1 @@
+jscoverage:javascript-xml.js:3: unsupported node type (75)
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js
new file mode 100644
index 0000000..a802d93
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript-xml/javascript-xml.js
@@ -0,0 +1,8 @@
+// ECMA 357 11.1.4
+// an XML object representing a person with a name and age
+var person = <person><name>John</name><age>25</age></person>;
+// a variable containing an XML object representing two employees
+var e = <employees>
+ <employee id="1"><name>Joe</name><age>20</age></employee>
+ <employee id="2"><name>Sue</name><age>30</age></employee>
+</employees>;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js
new file mode 100644
index 0000000..4ecdc1f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-array-comprehension.js
@@ -0,0 +1,32 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-array-comprehension.js']) {
+ _$jscoverage['javascript-array-comprehension.js'] = [];
+ _$jscoverage['javascript-array-comprehension.js'][3] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][4] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][5] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][8] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][9] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][12] = 0;
+ _$jscoverage['javascript-array-comprehension.js'][14] = 0;
+}
+_$jscoverage['javascript-array-comprehension.js'][3]++;
+function range(begin, end) {
+ _$jscoverage['javascript-array-comprehension.js'][4]++;
+ for (let i = begin; i < end; ++i) {
+ _$jscoverage['javascript-array-comprehension.js'][5]++;
+ yield i;
+}
+}
+_$jscoverage['javascript-array-comprehension.js'][8]++;
+var ten_squares = [i * i for each (i in range(0, 10))];
+_$jscoverage['javascript-array-comprehension.js'][9]++;
+var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
+_$jscoverage['javascript-array-comprehension.js'][12]++;
+var optimized = [1 for each (i in x) if (0)];
+_$jscoverage['javascript-array-comprehension.js'][14]++;
+[i for each (a in x) for each (b in y)];
+_$jscoverage['javascript-array-comprehension.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"k\">function</span> range<span class=\"k\">(</span>begin<span class=\"k\">,</span> end<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">let</span> i <span class=\"k\">=</span> begin<span class=\"k\">;</span> i <span class=\"k\">&lt;</span> end<span class=\"k\">;</span> <span class=\"k\">++</span>i<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">yield</span> i<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","<span class=\"k\">var</span> ten_squares <span class=\"k\">=</span> <span class=\"k\">[</span>i <span class=\"k\">*</span> i <span class=\"k\">for</span> each <span class=\"k\">(</span>i <span class=\"k\">in</span> range<span class=\"k\">(</span><span class=\"s\">0</span><span class=\"k\">,</span> <span class=\"s\">10</span><span class=\"k\">))];</span>","<span class=\"k\">var</span> evens <span class=\"k\">=</span> <span class=\"k\">[</span>i <span class=\"k\">for</span> each <span class=\"k\">(</span>i <span class=\"k\">in</span> range<span class=\"k\">(</span><span class=\"s\">0</span><span class=\"k\">,</span> <span class=\"s\">21</span><span class=\"k\">))</span> <span class=\"k\">if</span> <span class=\"k\">(</span>i <span class=\"k\">%</span> <span class=\"s\">2</span> <span class=\"k\">==</span> <span class=\"s\">0</span><span class=\"k\">)];</span>","","<span class=\"c\">// test optimization</span>","<span class=\"k\">var</span> optimized <span class=\"k\">=</span> <span class=\"k\">[</span>i <span class=\"k\">for</span> each <span class=\"k\">(</span>i <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"s\">0</span><span class=\"k\">)];</span>","","<span class=\"k\">[</span>i <span class=\"k\">for</span> each <span class=\"k\">(</span>a <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">for</span> each <span class=\"k\">(</span>b <span class=\"k\">in</span> y<span class=\"k\">)]</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js
new file mode 100644
index 0000000..fc3a7ec
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-assign.js
@@ -0,0 +1,51 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-assign.js']) {
+ _$jscoverage['javascript-assign.js'] = [];
+ _$jscoverage['javascript-assign.js'][1] = 0;
+ _$jscoverage['javascript-assign.js'][2] = 0;
+ _$jscoverage['javascript-assign.js'][3] = 0;
+ _$jscoverage['javascript-assign.js'][4] = 0;
+ _$jscoverage['javascript-assign.js'][5] = 0;
+ _$jscoverage['javascript-assign.js'][6] = 0;
+ _$jscoverage['javascript-assign.js'][7] = 0;
+ _$jscoverage['javascript-assign.js'][8] = 0;
+ _$jscoverage['javascript-assign.js'][9] = 0;
+ _$jscoverage['javascript-assign.js'][10] = 0;
+ _$jscoverage['javascript-assign.js'][11] = 0;
+ _$jscoverage['javascript-assign.js'][12] = 0;
+ _$jscoverage['javascript-assign.js'][13] = 0;
+ _$jscoverage['javascript-assign.js'][14] = 0;
+}
+_$jscoverage['javascript-assign.js'][1]++;
+var x = 1;
+_$jscoverage['javascript-assign.js'][2]++;
+var y = 1;
+_$jscoverage['javascript-assign.js'][3]++;
+x = y;
+_$jscoverage['javascript-assign.js'][4]++;
+x += y;
+_$jscoverage['javascript-assign.js'][5]++;
+x -= y;
+_$jscoverage['javascript-assign.js'][6]++;
+x *= y;
+_$jscoverage['javascript-assign.js'][7]++;
+x %= y;
+_$jscoverage['javascript-assign.js'][8]++;
+x <<= y;
+_$jscoverage['javascript-assign.js'][9]++;
+x >>= y;
+_$jscoverage['javascript-assign.js'][10]++;
+x >>>= y;
+_$jscoverage['javascript-assign.js'][11]++;
+x &= y;
+_$jscoverage['javascript-assign.js'][12]++;
+x |= y;
+_$jscoverage['javascript-assign.js'][13]++;
+x ^= y;
+_$jscoverage['javascript-assign.js'][14]++;
+x /= y;
+_$jscoverage['javascript-assign.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","<span class=\"k\">var</span> y <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> y<span class=\"k\">;</span>","x <span class=\"k\">+=</span> y<span class=\"k\">;</span>","x <span class=\"k\">-=</span> y<span class=\"k\">;</span>","x <span class=\"k\">*=</span> y<span class=\"k\">;</span>","x <span class=\"k\">%=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&lt;&lt;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&gt;&gt;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&gt;&gt;&gt;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">&amp;=</span> y<span class=\"k\">;</span>","x <span class=\"k\">|=</span> y<span class=\"k\">;</span>","x <span class=\"k\">^=</span> y<span class=\"k\">;</span>","x <span class=\"k\">/=</span> y<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js
new file mode 100644
index 0000000..c99da2b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-colon.js
@@ -0,0 +1,24 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-colon.js']) {
+ _$jscoverage['javascript-colon.js'] = [];
+ _$jscoverage['javascript-colon.js'][1] = 0;
+ _$jscoverage['javascript-colon.js'][4] = 0;
+ _$jscoverage['javascript-colon.js'][5] = 0;
+ _$jscoverage['javascript-colon.js'][6] = 0;
+}
+_$jscoverage['javascript-colon.js'][1]++;
+x:
+y = 0;
+_$jscoverage['javascript-colon.js'][4]++;
+y:
+{
+ _$jscoverage['javascript-colon.js'][5]++;
+ let y = 1;
+ _$jscoverage['javascript-colon.js'][6]++;
+ print(y);
+}
+_$jscoverage['javascript-colon.js'].source = ["x<span class=\"k\">:</span>"," y <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","y<span class=\"k\">:</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> y <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"," print<span class=\"k\">(</span>y<span class=\"k\">);</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js
new file mode 100644
index 0000000..5912427
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-comma.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-comma.js']) {
+ _$jscoverage['javascript-comma.js'] = [];
+ _$jscoverage['javascript-comma.js'][1] = 0;
+}
+_$jscoverage['javascript-comma.js'][1]++;
+x = y, y = x;
+_$jscoverage['javascript-comma.js'].source = ["x <span class=\"k\">=</span> y<span class=\"k\">,</span> y <span class=\"k\">=</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js
new file mode 100644
index 0000000..38d52fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-cr.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-cr.js']) {
+ _$jscoverage['javascript-cr.js'] = [];
+ _$jscoverage['javascript-cr.js'][4] = 0;
+}
+_$jscoverage['javascript-cr.js'][4]++;
+var x = 1;
+_$jscoverage['javascript-cr.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">This file has CR line endings.</span>","<span class=\"c\">*/</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js
new file mode 100644
index 0000000..82a2d12
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-crlf.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-crlf.js']) {
+ _$jscoverage['javascript-crlf.js'] = [];
+ _$jscoverage['javascript-crlf.js'][4] = 0;
+}
+_$jscoverage['javascript-crlf.js'][4]++;
+var x = 1;
+_$jscoverage['javascript-crlf.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">This file has CRLF line endings.</span>","<span class=\"c\">*/</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js
new file mode 100644
index 0000000..a78516e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-debugger.js
@@ -0,0 +1,21 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-debugger.js']) {
+ _$jscoverage['javascript-debugger.js'] = [];
+ _$jscoverage['javascript-debugger.js'][1] = 0;
+ _$jscoverage['javascript-debugger.js'][2] = 0;
+ _$jscoverage['javascript-debugger.js'][5] = 0;
+}
+_$jscoverage['javascript-debugger.js'][1]++;
+try {
+ _$jscoverage['javascript-debugger.js'][2]++;
+ f();
+}
+catch (e) {
+ _$jscoverage['javascript-debugger.js'][5]++;
+ debugger;
+}
+_$jscoverage['javascript-debugger.js'].source = ["<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">debugger</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js
new file mode 100644
index 0000000..4ba2323
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dec.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-dec.js']) {
+ _$jscoverage['javascript-dec.js'] = [];
+ _$jscoverage['javascript-dec.js'][1] = 0;
+ _$jscoverage['javascript-dec.js'][2] = 0;
+}
+_$jscoverage['javascript-dec.js'][1]++;
+x--;
+_$jscoverage['javascript-dec.js'][2]++;
+--x;
+_$jscoverage['javascript-dec.js'].source = ["x<span class=\"k\">--;</span>","<span class=\"k\">--</span>x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js
new file mode 100644
index 0000000..bc96a8f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-delete.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-delete.js']) {
+ _$jscoverage['javascript-delete.js'] = [];
+ _$jscoverage['javascript-delete.js'][1] = 0;
+}
+_$jscoverage['javascript-delete.js'][1]++;
+delete x;
+_$jscoverage['javascript-delete.js'].source = ["<span class=\"k\">delete</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js
new file mode 100644
index 0000000..ac3d0eb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-destructuring.js
@@ -0,0 +1,96 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-destructuring.js']) {
+ _$jscoverage['javascript-destructuring.js'] = [];
+ _$jscoverage['javascript-destructuring.js'][3] = 0;
+ _$jscoverage['javascript-destructuring.js'][5] = 0;
+ _$jscoverage['javascript-destructuring.js'][6] = 0;
+ _$jscoverage['javascript-destructuring.js'][8] = 0;
+ _$jscoverage['javascript-destructuring.js'][10] = 0;
+ _$jscoverage['javascript-destructuring.js'][11] = 0;
+ _$jscoverage['javascript-destructuring.js'][12] = 0;
+ _$jscoverage['javascript-destructuring.js'][15] = 0;
+ _$jscoverage['javascript-destructuring.js'][16] = 0;
+ _$jscoverage['javascript-destructuring.js'][17] = 0;
+ _$jscoverage['javascript-destructuring.js'][20] = 0;
+ _$jscoverage['javascript-destructuring.js'][21] = 0;
+ _$jscoverage['javascript-destructuring.js'][23] = 0;
+ _$jscoverage['javascript-destructuring.js'][24] = 0;
+ _$jscoverage['javascript-destructuring.js'][25] = 0;
+ _$jscoverage['javascript-destructuring.js'][26] = 0;
+ _$jscoverage['javascript-destructuring.js'][27] = 0;
+ _$jscoverage['javascript-destructuring.js'][30] = 0;
+ _$jscoverage['javascript-destructuring.js'][31] = 0;
+ _$jscoverage['javascript-destructuring.js'][32] = 0;
+ _$jscoverage['javascript-destructuring.js'][35] = 0;
+ _$jscoverage['javascript-destructuring.js'][37] = 0;
+ _$jscoverage['javascript-destructuring.js'][38] = 0;
+ _$jscoverage['javascript-destructuring.js'][39] = 0;
+ _$jscoverage['javascript-destructuring.js'][40] = 0;
+ _$jscoverage['javascript-destructuring.js'][41] = 0;
+}
+_$jscoverage['javascript-destructuring.js'][3]++;
+[a, b] = [b, a];
+_$jscoverage['javascript-destructuring.js'][5]++;
+function f() {
+ _$jscoverage['javascript-destructuring.js'][6]++;
+ return [1, 2];
+}
+_$jscoverage['javascript-destructuring.js'][8]++;
+[a, b] = f();
+_$jscoverage['javascript-destructuring.js'][10]++;
+for (let [name, value] in Iterator(obj)) {
+ _$jscoverage['javascript-destructuring.js'][11]++;
+ print(name);
+ _$jscoverage['javascript-destructuring.js'][12]++;
+ print(value);
+}
+_$jscoverage['javascript-destructuring.js'][15]++;
+for each (let {name: n, family: {father: f}} in people) {
+ _$jscoverage['javascript-destructuring.js'][16]++;
+ print(n);
+ _$jscoverage['javascript-destructuring.js'][17]++;
+ print(f);
+}
+_$jscoverage['javascript-destructuring.js'][20]++;
+var [a, , b] = f();
+_$jscoverage['javascript-destructuring.js'][21]++;
+[, , ,] = f();
+_$jscoverage['javascript-destructuring.js'][23]++;
+function g() {
+ _$jscoverage['javascript-destructuring.js'][24]++;
+ var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
+ _$jscoverage['javascript-destructuring.js'][25]++;
+ if (! parsedURL) {
+ _$jscoverage['javascript-destructuring.js'][26]++;
+ return null;
+ }
+ _$jscoverage['javascript-destructuring.js'][27]++;
+ var [, protocol, fullhost, fullpath] = parsedURL;
+}
+_$jscoverage['javascript-destructuring.js'][30]++;
+function h(a, [b, c], {foo: d, "bar": e}) {
+ _$jscoverage['javascript-destructuring.js'][31]++;
+ f();
+ _$jscoverage['javascript-destructuring.js'][32]++;
+ g();
+}
+_$jscoverage['javascript-destructuring.js'][35]++;
+x = (function ([a, b]) {
+ return a + b;
+});
+_$jscoverage['javascript-destructuring.js'][37]++;
+({x: x0, y: y0}) = point;
+_$jscoverage['javascript-destructuring.js'][38]++;
+var {x: x0, y: y0} = point;
+_$jscoverage['javascript-destructuring.js'][39]++;
+let ({x: x0, y: y0} = point) {
+ _$jscoverage['javascript-destructuring.js'][40]++;
+ print(x0);
+ _$jscoverage['javascript-destructuring.js'][41]++;
+ print(y0);
+}
+_$jscoverage['javascript-destructuring.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"k\">[</span>a<span class=\"k\">,</span> b<span class=\"k\">]</span> <span class=\"k\">=</span> <span class=\"k\">[</span>b<span class=\"k\">,</span> a<span class=\"k\">];</span>","","<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">return</span> <span class=\"k\">[</span><span class=\"s\">1</span><span class=\"k\">,</span> <span class=\"s\">2</span><span class=\"k\">];</span>","<span class=\"k\">}</span>","<span class=\"k\">[</span>a<span class=\"k\">,</span> b<span class=\"k\">]</span> <span class=\"k\">=</span> f<span class=\"k\">();</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">let</span> <span class=\"k\">[</span>name<span class=\"k\">,</span> value<span class=\"k\">]</span> <span class=\"k\">in</span> Iterator<span class=\"k\">(</span>obj<span class=\"k\">))</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>name<span class=\"k\">);</span>"," print<span class=\"k\">(</span>value<span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> each <span class=\"k\">(</span><span class=\"k\">let</span> <span class=\"k\">{</span>name<span class=\"k\">:</span> n<span class=\"k\">,</span> family<span class=\"k\">:</span> <span class=\"k\">{</span> father<span class=\"k\">:</span> f <span class=\"k\">}</span> <span class=\"k\">}</span> <span class=\"k\">in</span> people<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>n<span class=\"k\">);</span>"," print<span class=\"k\">(</span>f<span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">var</span> <span class=\"k\">[</span>a<span class=\"k\">,</span> <span class=\"k\">,</span> b<span class=\"k\">]</span> <span class=\"k\">=</span> f<span class=\"k\">();</span>","<span class=\"k\">[,,,]</span> <span class=\"k\">=</span> f<span class=\"k\">();</span>","","<span class=\"k\">function</span> g<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> parsedURL <span class=\"k\">=</span> <span class=\"s\">/^(\\w+)\\:\\/\\/([^\\/]+)\\/(.*)$/</span><span class=\"k\">.</span>exec<span class=\"k\">(</span>url<span class=\"k\">);</span>"," <span class=\"k\">if</span> <span class=\"k\">(!</span>parsedURL<span class=\"k\">)</span>"," <span class=\"k\">return</span> <span class=\"k\">null</span><span class=\"k\">;</span>"," <span class=\"k\">var</span> <span class=\"k\">[,</span> protocol<span class=\"k\">,</span> fullhost<span class=\"k\">,</span> fullpath<span class=\"k\">]</span> <span class=\"k\">=</span> parsedURL<span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> h<span class=\"k\">(</span>a<span class=\"k\">,</span> <span class=\"k\">[</span>b<span class=\"k\">,</span> c<span class=\"k\">],</span> <span class=\"k\">{</span>foo<span class=\"k\">:</span> d<span class=\"k\">,</span> <span class=\"s\">'bar'</span><span class=\"k\">:</span> e<span class=\"k\">}</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>"," g<span class=\"k\">();</span>","<span class=\"k\">}</span>","","x <span class=\"k\">=</span> <span class=\"k\">function</span><span class=\"k\">([</span>a<span class=\"k\">,</span> b<span class=\"k\">])</span> a <span class=\"k\">+</span> b<span class=\"k\">;</span>","","<span class=\"k\">(</span><span class=\"k\">{</span>x<span class=\"k\">:</span> x0<span class=\"k\">,</span> y<span class=\"k\">:</span> y0<span class=\"k\">}</span><span class=\"k\">)</span> <span class=\"k\">=</span> point<span class=\"k\">;</span>","<span class=\"k\">var</span> <span class=\"k\">{</span>x<span class=\"k\">:</span> x0<span class=\"k\">,</span> y<span class=\"k\">:</span> y0<span class=\"k\">}</span> <span class=\"k\">=</span> point<span class=\"k\">;</span>","<span class=\"k\">let</span> <span class=\"k\">(</span><span class=\"k\">{</span>x<span class=\"k\">:</span> x0<span class=\"k\">,</span> y<span class=\"k\">:</span> y0<span class=\"k\">}</span> <span class=\"k\">=</span> point<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>x0<span class=\"k\">);</span>"," print<span class=\"k\">(</span>y0<span class=\"k\">);</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js
new file mode 100644
index 0000000..23d4557
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-do.js
@@ -0,0 +1,28 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-do.js']) {
+ _$jscoverage['javascript-do.js'] = [];
+ _$jscoverage['javascript-do.js'][1] = 0;
+ _$jscoverage['javascript-do.js'][3] = 0;
+ _$jscoverage['javascript-do.js'][4] = 0;
+ _$jscoverage['javascript-do.js'][8] = 0;
+ _$jscoverage['javascript-do.js'][9] = 0;
+}
+_$jscoverage['javascript-do.js'][1]++;
+var x;
+_$jscoverage['javascript-do.js'][3]++;
+do {
+ _$jscoverage['javascript-do.js'][4]++;
+ x = false;
+}
+while (x);
+_$jscoverage['javascript-do.js'][8]++;
+do {
+ _$jscoverage['javascript-do.js'][9]++;
+ x = false;
+}
+while (x);
+_$jscoverage['javascript-do.js'].source = ["<span class=\"k\">var</span> x<span class=\"k\">;</span>","","<span class=\"k\">do</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"k\">false</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">);</span>","","<span class=\"k\">do</span>"," x <span class=\"k\">=</span> <span class=\"k\">false</span><span class=\"k\">;</span>","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js
new file mode 100644
index 0000000..ca91faa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-dot.js
@@ -0,0 +1,30 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-dot.js']) {
+ _$jscoverage['javascript-dot.js'] = [];
+ _$jscoverage['javascript-dot.js'][1] = 0;
+ _$jscoverage['javascript-dot.js'][2] = 0;
+ _$jscoverage['javascript-dot.js'][3] = 0;
+ _$jscoverage['javascript-dot.js'][4] = 0;
+ _$jscoverage['javascript-dot.js'][5] = 0;
+ _$jscoverage['javascript-dot.js'][7] = 0;
+ _$jscoverage['javascript-dot.js'][8] = 0;
+}
+_$jscoverage['javascript-dot.js'][1]++;
+x.y = y.x;
+_$jscoverage['javascript-dot.js'][2]++;
+x.y = y.x;
+_$jscoverage['javascript-dot.js'][3]++;
+x[y] = y[x];
+_$jscoverage['javascript-dot.js'][4]++;
+x["2y"] = y["var"];
+_$jscoverage['javascript-dot.js'][5]++;
+x[""] = y[""];
+_$jscoverage['javascript-dot.js'][7]++;
+print((123).toString());
+_$jscoverage['javascript-dot.js'][8]++;
+({}).toString();
+_$jscoverage['javascript-dot.js'].source = ["x<span class=\"k\">.</span>y <span class=\"k\">=</span> y<span class=\"k\">.</span>x<span class=\"k\">;</span>","x<span class=\"k\">[</span><span class=\"s\">\"y\"</span><span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span><span class=\"s\">\"x\"</span><span class=\"k\">];</span>","x<span class=\"k\">[</span>y<span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span>x<span class=\"k\">];</span>","x<span class=\"k\">[</span><span class=\"s\">'2y'</span><span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span><span class=\"s\">'var'</span><span class=\"k\">];</span>","x<span class=\"k\">[</span><span class=\"s\">''</span><span class=\"k\">]</span> <span class=\"k\">=</span> y<span class=\"k\">[</span><span class=\"s\">\"\"</span><span class=\"k\">];</span>","","print<span class=\"k\">(</span><span class=\"s\">123.0</span><span class=\"k\">.</span>toString<span class=\"k\">());</span>","<span class=\"k\">(</span><span class=\"k\">{}</span><span class=\"k\">.</span>toString<span class=\"k\">());</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js
new file mode 100644
index 0000000..646be4b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-empty.js
@@ -0,0 +1,9 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-empty.js']) {
+ _$jscoverage['javascript-empty.js'] = [];
+}
+_$jscoverage['javascript-empty.js'].source = [];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js
new file mode 100644
index 0000000..07b9fc2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-for.js
@@ -0,0 +1,51 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-for.js']) {
+ _$jscoverage['javascript-for.js'] = [];
+ _$jscoverage['javascript-for.js'][1] = 0;
+ _$jscoverage['javascript-for.js'][2] = 0;
+ _$jscoverage['javascript-for.js'][5] = 0;
+ _$jscoverage['javascript-for.js'][6] = 0;
+ _$jscoverage['javascript-for.js'][9] = 0;
+ _$jscoverage['javascript-for.js'][10] = 0;
+ _$jscoverage['javascript-for.js'][13] = 0;
+ _$jscoverage['javascript-for.js'][14] = 0;
+ _$jscoverage['javascript-for.js'][17] = 0;
+ _$jscoverage['javascript-for.js'][18] = 0;
+ _$jscoverage['javascript-for.js'][20] = 0;
+ _$jscoverage['javascript-for.js'][21] = 0;
+}
+_$jscoverage['javascript-for.js'][1]++;
+for (i in x) {
+ _$jscoverage['javascript-for.js'][2]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][5]++;
+for (var i in x) {
+ _$jscoverage['javascript-for.js'][6]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][9]++;
+for (i = 0; i < x; i++) {
+ _$jscoverage['javascript-for.js'][10]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][13]++;
+for (var j = 0; j < x; j++) {
+ _$jscoverage['javascript-for.js'][14]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][17]++;
+for (i in x) {
+ _$jscoverage['javascript-for.js'][18]++;
+ x();
+}
+_$jscoverage['javascript-for.js'][20]++;
+for (i.value in x) {
+ _$jscoverage['javascript-for.js'][21]++;
+ x();
+}
+_$jscoverage['javascript-for.js'].source = ["<span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">var</span> i <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span> i <span class=\"k\">&lt;</span> x<span class=\"k\">;</span> i<span class=\"k\">++)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">var</span> j <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span> j <span class=\"k\">&lt;</span> x<span class=\"k\">;</span> j<span class=\"k\">++)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">in</span> x<span class=\"k\">)</span>"," x<span class=\"k\">();</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span>i<span class=\"k\">.</span>value <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js
new file mode 100644
index 0000000..2c63a81
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-foreach.js
@@ -0,0 +1,16 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-foreach.js']) {
+ _$jscoverage['javascript-foreach.js'] = [];
+ _$jscoverage['javascript-foreach.js'][6] = 0;
+ _$jscoverage['javascript-foreach.js'][7] = 0;
+}
+_$jscoverage['javascript-foreach.js'][6]++;
+for each (var item in obj) {
+ _$jscoverage['javascript-foreach.js'][7]++;
+ sum += item;
+}
+_$jscoverage['javascript-foreach.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Object_Manipulation_Statements</span>","<span class=\"c\">https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in</span>","<span class=\"c\">*/</span>","","<span class=\"k\">for</span> each <span class=\"k\">(</span><span class=\"k\">var</span> item <span class=\"k\">in</span> obj<span class=\"k\">)</span> <span class=\"k\">{</span>"," sum <span class=\"k\">+=</span> item<span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js
new file mode 100644
index 0000000..5adada1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-function.js
@@ -0,0 +1,79 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-function.js']) {
+ _$jscoverage['javascript-function.js'] = [];
+ _$jscoverage['javascript-function.js'][1] = 0;
+ _$jscoverage['javascript-function.js'][3] = 0;
+ _$jscoverage['javascript-function.js'][4] = 0;
+ _$jscoverage['javascript-function.js'][7] = 0;
+ _$jscoverage['javascript-function.js'][8] = 0;
+ _$jscoverage['javascript-function.js'][9] = 0;
+ _$jscoverage['javascript-function.js'][12] = 0;
+ _$jscoverage['javascript-function.js'][13] = 0;
+ _$jscoverage['javascript-function.js'][16] = 0;
+ _$jscoverage['javascript-function.js'][17] = 0;
+ _$jscoverage['javascript-function.js'][20] = 0;
+ _$jscoverage['javascript-function.js'][21] = 0;
+ _$jscoverage['javascript-function.js'][24] = 0;
+ _$jscoverage['javascript-function.js'][25] = 0;
+ _$jscoverage['javascript-function.js'][28] = 0;
+ _$jscoverage['javascript-function.js'][29] = 0;
+ _$jscoverage['javascript-function.js'][32] = 0;
+ _$jscoverage['javascript-function.js'][33] = 0;
+ _$jscoverage['javascript-function.js'][36] = 0;
+ _$jscoverage['javascript-function.js'][37] = 0;
+}
+_$jscoverage['javascript-function.js'][1]++;
+function x() {
+}
+_$jscoverage['javascript-function.js'][3]++;
+function x() {
+ _$jscoverage['javascript-function.js'][4]++;
+ ;
+}
+_$jscoverage['javascript-function.js'][7]++;
+function x() {
+ _$jscoverage['javascript-function.js'][8]++;
+ x();
+ _$jscoverage['javascript-function.js'][9]++;
+ return "x";
+}
+_$jscoverage['javascript-function.js'][12]++;
+function x(a) {
+ _$jscoverage['javascript-function.js'][13]++;
+ x();
+}
+_$jscoverage['javascript-function.js'][16]++;
+function x(a, b) {
+ _$jscoverage['javascript-function.js'][17]++;
+ x();
+}
+_$jscoverage['javascript-function.js'][20]++;
+x = (function () {
+ _$jscoverage['javascript-function.js'][21]++;
+ x();
+});
+_$jscoverage['javascript-function.js'][24]++;
+(function () {
+ _$jscoverage['javascript-function.js'][25]++;
+ print("x");
+})();
+_$jscoverage['javascript-function.js'][28]++;
+(function (a) {
+ _$jscoverage['javascript-function.js'][29]++;
+ print("x");
+})(1);
+_$jscoverage['javascript-function.js'][32]++;
+(function (a, b) {
+ _$jscoverage['javascript-function.js'][33]++;
+ print("x");
+})(1, 2);
+_$jscoverage['javascript-function.js'][36]++;
+(function () {
+ _$jscoverage['javascript-function.js'][37]++;
+ print("x");
+}).call(window);
+_$jscoverage['javascript-function.js'].source = ["<span class=\"k\">function</span> x<span class=\"k\">()</span> <span class=\"k\">{}</span>","","<span class=\"k\">function</span> x<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> x<span class=\"k\">()</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>"," <span class=\"k\">return</span> <span class=\"s\">'x'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> x<span class=\"k\">(</span>a<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> x<span class=\"k\">(</span>a<span class=\"k\">,</span> b<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","x <span class=\"k\">=</span> <span class=\"k\">function</span><span class=\"k\">()</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span><span class=\"k\">;</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">()</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">)();</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">(</span>a<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">)(</span><span class=\"s\">1</span><span class=\"k\">);</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">(</span>a<span class=\"k\">,</span> b<span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">)(</span><span class=\"s\">1</span><span class=\"k\">,</span> <span class=\"s\">2</span><span class=\"k\">);</span>","","<span class=\"k\">(</span><span class=\"k\">function</span> <span class=\"k\">()</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span><span class=\"s\">'x'</span><span class=\"k\">);</span>","<span class=\"k\">}</span><span class=\"k\">).</span>call<span class=\"k\">(</span>window<span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js
new file mode 100644
index 0000000..6ef1f11
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator-expression.js
@@ -0,0 +1,45 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-generator-expression.js']) {
+ _$jscoverage['javascript-generator-expression.js'] = [];
+ _$jscoverage['javascript-generator-expression.js'][3] = 0;
+ _$jscoverage['javascript-generator-expression.js'][4] = 0;
+ _$jscoverage['javascript-generator-expression.js'][5] = 0;
+ _$jscoverage['javascript-generator-expression.js'][6] = 0;
+ _$jscoverage['javascript-generator-expression.js'][9] = 0;
+ _$jscoverage['javascript-generator-expression.js'][12] = 0;
+ _$jscoverage['javascript-generator-expression.js'][13] = 0;
+ _$jscoverage['javascript-generator-expression.js'][14] = 0;
+ _$jscoverage['javascript-generator-expression.js'][16] = 0;
+ _$jscoverage['javascript-generator-expression.js'][18] = 0;
+}
+_$jscoverage['javascript-generator-expression.js'][3]++;
+var it = (i + 3 for (i in someObj));
+_$jscoverage['javascript-generator-expression.js'][4]++;
+try {
+ _$jscoverage['javascript-generator-expression.js'][5]++;
+ while (true) {
+ _$jscoverage['javascript-generator-expression.js'][6]++;
+ document.write(it.next() + "<br>\n");
+}
+}
+catch (err if err instanceof StopIteration) {
+ _$jscoverage['javascript-generator-expression.js'][9]++;
+ document.write("End of record.<br>\n");
+}
+_$jscoverage['javascript-generator-expression.js'][12]++;
+function handleResults(results) {
+ _$jscoverage['javascript-generator-expression.js'][13]++;
+ for (let i in results) {
+ _$jscoverage['javascript-generator-expression.js'][14]++;
+ ;
+}
+}
+_$jscoverage['javascript-generator-expression.js'][16]++;
+handleResults((i for (i in obj) if (i > 3)));
+_$jscoverage['javascript-generator-expression.js'][18]++;
+it = (1 for (a in x) for (b in y));
+_$jscoverage['javascript-generator-expression.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.8</span>","","<span class=\"k\">let</span> it <span class=\"k\">=</span> <span class=\"k\">(</span>i <span class=\"k\">+</span> <span class=\"s\">3</span> <span class=\"k\">for</span> <span class=\"k\">(</span>i <span class=\"k\">in</span> someObj<span class=\"k\">));</span>","<span class=\"k\">try</span> <span class=\"k\">{</span>"," <span class=\"k\">while</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span>it<span class=\"k\">.</span>next<span class=\"k\">()</span> <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span> <span class=\"k\">catch</span> <span class=\"k\">(</span>err <span class=\"k\">if</span> err <span class=\"k\">instanceof</span> StopIteration<span class=\"k\">)</span> <span class=\"k\">{</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span><span class=\"s\">\"End of record.&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> handleResults<span class=\"k\">(</span> results <span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">for</span> <span class=\"k\">(</span> <span class=\"k\">let</span> i <span class=\"k\">in</span> results <span class=\"k\">)</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>","handleResults<span class=\"k\">(</span> i <span class=\"k\">for</span> <span class=\"k\">(</span> i <span class=\"k\">in</span> obj <span class=\"k\">)</span> <span class=\"k\">if</span> <span class=\"k\">(</span> i <span class=\"k\">&gt;</span> <span class=\"s\">3</span> <span class=\"k\">)</span> <span class=\"k\">);</span>","","it <span class=\"k\">=</span> <span class=\"k\">(</span><span class=\"s\">1</span> <span class=\"k\">for</span><span class=\"k\">(</span>a <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">for</span><span class=\"k\">(</span>b <span class=\"k\">in</span> y<span class=\"k\">));</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js
new file mode 100644
index 0000000..fa9cece
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-generator.js
@@ -0,0 +1,32 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-generator.js']) {
+ _$jscoverage['javascript-generator.js'] = [];
+ _$jscoverage['javascript-generator.js'][3] = 0;
+ _$jscoverage['javascript-generator.js'][4] = 0;
+ _$jscoverage['javascript-generator.js'][5] = 0;
+ _$jscoverage['javascript-generator.js'][6] = 0;
+ _$jscoverage['javascript-generator.js'][7] = 0;
+ _$jscoverage['javascript-generator.js'][8] = 0;
+ _$jscoverage['javascript-generator.js'][9] = 0;
+}
+_$jscoverage['javascript-generator.js'][3]++;
+function fib() {
+ _$jscoverage['javascript-generator.js'][4]++;
+ var i = 0, j = 1;
+ _$jscoverage['javascript-generator.js'][5]++;
+ while (true) {
+ _$jscoverage['javascript-generator.js'][6]++;
+ yield i;
+ _$jscoverage['javascript-generator.js'][7]++;
+ var t = i;
+ _$jscoverage['javascript-generator.js'][8]++;
+ i = j;
+ _$jscoverage['javascript-generator.js'][9]++;
+ j += t;
+}
+}
+_$jscoverage['javascript-generator.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"k\">function</span> fib<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> i <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">,</span> j <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"," <span class=\"k\">while</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">yield</span> i<span class=\"k\">;</span>"," <span class=\"k\">var</span> t <span class=\"k\">=</span> i<span class=\"k\">;</span>"," i <span class=\"k\">=</span> j<span class=\"k\">;</span>"," j <span class=\"k\">+=</span> t<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js
new file mode 100644
index 0000000..cffc83f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-getter-setter.js
@@ -0,0 +1,31 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-getter-setter.js']) {
+ _$jscoverage['javascript-getter-setter.js'] = [];
+ _$jscoverage['javascript-getter-setter.js'][1] = 0;
+ _$jscoverage['javascript-getter-setter.js'][4] = 0;
+ _$jscoverage['javascript-getter-setter.js'][7] = 0;
+ _$jscoverage['javascript-getter-setter.js'][11] = 0;
+ _$jscoverage['javascript-getter-setter.js'][14] = 0;
+ _$jscoverage['javascript-getter-setter.js'][17] = 0;
+}
+_$jscoverage['javascript-getter-setter.js'][1]++;
+var o = {_x: 123, get x () {
+ _$jscoverage['javascript-getter-setter.js'][4]++;
+ return this._x;
+}, set x (value) {
+ _$jscoverage['javascript-getter-setter.js'][7]++;
+ this._x = value;
+}};
+_$jscoverage['javascript-getter-setter.js'][11]++;
+o = {_x: 123, get x get_x() {
+ _$jscoverage['javascript-getter-setter.js'][14]++;
+ return this._x;
+}, set x set_x(value) {
+ _$jscoverage['javascript-getter-setter.js'][17]++;
+ this._x = value;
+}};
+_$jscoverage['javascript-getter-setter.js'].source = ["<span class=\"k\">var</span> o <span class=\"k\">=</span> <span class=\"k\">{</span>"," _x<span class=\"k\">:</span> <span class=\"s\">123</span><span class=\"k\">,</span>"," get x<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">return</span> <span class=\"k\">this</span><span class=\"k\">.</span>_x<span class=\"k\">;</span>"," <span class=\"k\">}</span><span class=\"k\">,</span>"," set x<span class=\"k\">(</span>value<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">this</span><span class=\"k\">.</span>_x <span class=\"k\">=</span> value<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span><span class=\"k\">;</span>","","o <span class=\"k\">=</span> <span class=\"k\">{</span>"," _x<span class=\"k\">:</span> <span class=\"s\">123</span><span class=\"k\">,</span>"," get x get_x<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">return</span> <span class=\"k\">this</span><span class=\"k\">.</span>_x<span class=\"k\">;</span>"," <span class=\"k\">}</span><span class=\"k\">,</span>"," set x set_x<span class=\"k\">(</span>value<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">this</span><span class=\"k\">.</span>_x <span class=\"k\">=</span> value<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js
new file mode 100644
index 0000000..08f33d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-hook.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-hook.js']) {
+ _$jscoverage['javascript-hook.js'] = [];
+ _$jscoverage['javascript-hook.js'][1] = 0;
+ _$jscoverage['javascript-hook.js'][2] = 0;
+}
+_$jscoverage['javascript-hook.js'][1]++;
+var x = 1;
+_$jscoverage['javascript-hook.js'][2]++;
+var y = x === 1? "x": "y";
+_$jscoverage['javascript-hook.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","<span class=\"k\">var</span> y <span class=\"k\">=</span> x <span class=\"k\">===</span> <span class=\"s\">1</span><span class=\"k\">?</span> <span class=\"s\">\"x\"</span><span class=\"k\">:</span> <span class=\"s\">\"y\"</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js
new file mode 100644
index 0000000..8559e59
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-if.js
@@ -0,0 +1,71 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-if.js']) {
+ _$jscoverage['javascript-if.js'] = [];
+ _$jscoverage['javascript-if.js'][1] = 0;
+ _$jscoverage['javascript-if.js'][3] = 0;
+ _$jscoverage['javascript-if.js'][4] = 0;
+ _$jscoverage['javascript-if.js'][6] = 0;
+ _$jscoverage['javascript-if.js'][7] = 0;
+ _$jscoverage['javascript-if.js'][10] = 0;
+ _$jscoverage['javascript-if.js'][11] = 0;
+ _$jscoverage['javascript-if.js'][13] = 0;
+ _$jscoverage['javascript-if.js'][15] = 0;
+ _$jscoverage['javascript-if.js'][16] = 0;
+ _$jscoverage['javascript-if.js'][19] = 0;
+ _$jscoverage['javascript-if.js'][22] = 0;
+ _$jscoverage['javascript-if.js'][23] = 0;
+ _$jscoverage['javascript-if.js'][25] = 0;
+ _$jscoverage['javascript-if.js'][26] = 0;
+ _$jscoverage['javascript-if.js'][29] = 0;
+}
+_$jscoverage['javascript-if.js'][1]++;
+var x = 0;
+_$jscoverage['javascript-if.js'][3]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][4]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][6]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][7]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][10]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][11]++;
+ x = 0;
+}
+else {
+ _$jscoverage['javascript-if.js'][13]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][15]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][16]++;
+ x = 0;
+}
+else {
+ _$jscoverage['javascript-if.js'][19]++;
+ x = 0;
+}
+_$jscoverage['javascript-if.js'][22]++;
+if (x) {
+ _$jscoverage['javascript-if.js'][23]++;
+ x = 0;
+}
+else {
+ _$jscoverage['javascript-if.js'][25]++;
+ if (x) {
+ _$jscoverage['javascript-if.js'][26]++;
+ x = 0;
+ }
+ else {
+ _$jscoverage['javascript-if.js'][29]++;
+ x = 0;
+ }
+}
+_$jscoverage['javascript-if.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">else</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">else</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">else</span> <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">else</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js
new file mode 100644
index 0000000..5f6b35a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-in.js
@@ -0,0 +1,19 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-in.js']) {
+ _$jscoverage['javascript-in.js'] = [];
+ _$jscoverage['javascript-in.js'][1] = 0;
+ _$jscoverage['javascript-in.js'][2] = 0;
+ _$jscoverage['javascript-in.js'][3] = 0;
+}
+_$jscoverage['javascript-in.js'][1]++;
+var x = {};
+_$jscoverage['javascript-in.js'][2]++;
+if ("a" in x) {
+ _$jscoverage['javascript-in.js'][3]++;
+ x = null;
+}
+_$jscoverage['javascript-in.js'].source = ["<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"k\">{}</span><span class=\"k\">;</span>","<span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"s\">'a'</span> <span class=\"k\">in</span> x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x <span class=\"k\">=</span> <span class=\"k\">null</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js
new file mode 100644
index 0000000..7c1730f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-inc.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-inc.js']) {
+ _$jscoverage['javascript-inc.js'] = [];
+ _$jscoverage['javascript-inc.js'][1] = 0;
+ _$jscoverage['javascript-inc.js'][2] = 0;
+}
+_$jscoverage['javascript-inc.js'][1]++;
+x++;
+_$jscoverage['javascript-inc.js'][2]++;
+++x;
+_$jscoverage['javascript-inc.js'].source = ["x<span class=\"k\">++;</span>","<span class=\"k\">++</span>x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js
new file mode 100644
index 0000000..e4650a9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-iso-8859-1.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-iso-8859-1.js']) {
+ _$jscoverage['javascript-iso-8859-1.js'] = [];
+ _$jscoverage['javascript-iso-8859-1.js'][1] = 0;
+ _$jscoverage['javascript-iso-8859-1.js'][2] = 0;
+}
+_$jscoverage['javascript-iso-8859-1.js'][1]++;
+var s = "e\u00e8\u00e9\u00ea";
+_$jscoverage['javascript-iso-8859-1.js'][2]++;
+var r = /e\u00e8\u00e9\u00ea/;
+_$jscoverage['javascript-iso-8859-1.js'].source = ["<span class=\"k\">var</span> s <span class=\"k\">=</span> <span class=\"s\">'e&#232;&#233;&#234;'</span><span class=\"k\">;</span>","<span class=\"k\">var</span> r <span class=\"k\">=</span> <span class=\"s\">/e&#232;&#233;&#234;/</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js
new file mode 100644
index 0000000..9681cd9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lambda.js
@@ -0,0 +1,14 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-lambda.js']) {
+ _$jscoverage['javascript-lambda.js'] = [];
+ _$jscoverage['javascript-lambda.js'][3] = 0;
+}
+_$jscoverage['javascript-lambda.js'][3]++;
+var square = (function (x) {
+ return x * x;
+});
+_$jscoverage['javascript-lambda.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.8</span>","","<span class=\"k\">var</span> square <span class=\"k\">=</span> <span class=\"k\">function</span><span class=\"k\">(</span>x<span class=\"k\">)</span> x <span class=\"k\">*</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js
new file mode 100644
index 0000000..b726ff7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-let.js
@@ -0,0 +1,148 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-let.js']) {
+ _$jscoverage['javascript-let.js'] = [];
+ _$jscoverage['javascript-let.js'][5] = 0;
+ _$jscoverage['javascript-let.js'][6] = 0;
+ _$jscoverage['javascript-let.js'][11] = 0;
+ _$jscoverage['javascript-let.js'][15] = 0;
+ _$jscoverage['javascript-let.js'][16] = 0;
+ _$jscoverage['javascript-let.js'][17] = 0;
+ _$jscoverage['javascript-let.js'][20] = 0;
+ _$jscoverage['javascript-let.js'][22] = 0;
+ _$jscoverage['javascript-let.js'][23] = 0;
+ _$jscoverage['javascript-let.js'][24] = 0;
+ _$jscoverage['javascript-let.js'][26] = 0;
+ _$jscoverage['javascript-let.js'][27] = 0;
+ _$jscoverage['javascript-let.js'][28] = 0;
+ _$jscoverage['javascript-let.js'][30] = 0;
+ _$jscoverage['javascript-let.js'][33] = 0;
+ _$jscoverage['javascript-let.js'][34] = 0;
+ _$jscoverage['javascript-let.js'][35] = 0;
+ _$jscoverage['javascript-let.js'][36] = 0;
+ _$jscoverage['javascript-let.js'][37] = 0;
+ _$jscoverage['javascript-let.js'][39] = 0;
+ _$jscoverage['javascript-let.js'][42] = 0;
+ _$jscoverage['javascript-let.js'][43] = 0;
+ _$jscoverage['javascript-let.js'][45] = 0;
+ _$jscoverage['javascript-let.js'][46] = 0;
+ _$jscoverage['javascript-let.js'][48] = 0;
+ _$jscoverage['javascript-let.js'][51] = 0;
+ _$jscoverage['javascript-let.js'][52] = 0;
+ _$jscoverage['javascript-let.js'][55] = 0;
+ _$jscoverage['javascript-let.js'][56] = 0;
+ _$jscoverage['javascript-let.js'][60] = 0;
+ _$jscoverage['javascript-let.js'][64] = 0;
+ _$jscoverage['javascript-let.js'][65] = 0;
+ _$jscoverage['javascript-let.js'][69] = 0;
+ _$jscoverage['javascript-let.js'][70] = 0;
+ _$jscoverage['javascript-let.js'][71] = 0;
+ _$jscoverage['javascript-let.js'][74] = 0;
+ _$jscoverage['javascript-let.js'][75] = 0;
+ _$jscoverage['javascript-let.js'][76] = 0;
+ _$jscoverage['javascript-let.js'][78] = 0;
+ _$jscoverage['javascript-let.js'][79] = 0;
+}
+_$jscoverage['javascript-let.js'][5]++;
+let (x = x + 10, y = 12) {
+ _$jscoverage['javascript-let.js'][6]++;
+ print(x + y + "\n");
+}
+_$jscoverage['javascript-let.js'][11]++;
+print(let(x = x + 10, y = 12) x + y + "<br>\n");
+_$jscoverage['javascript-let.js'][15]++;
+if (x > y) {
+ {
+ _$jscoverage['javascript-let.js'][16]++;
+ let gamma = 12.7 + y;
+ _$jscoverage['javascript-let.js'][17]++;
+ i = gamma * x;
+ }
+}
+_$jscoverage['javascript-let.js'][20]++;
+var list = document.getElementById("list");
+_$jscoverage['javascript-let.js'][22]++;
+for (var i = 1; i <= 5; i++) {
+ {
+ _$jscoverage['javascript-let.js'][23]++;
+ var item = document.createElement("LI");
+ _$jscoverage['javascript-let.js'][24]++;
+ item.appendChild(document.createTextNode("Item " + i));
+ _$jscoverage['javascript-let.js'][26]++;
+ let j = i;
+ _$jscoverage['javascript-let.js'][27]++;
+ item.onclick = (function (ev) {
+ _$jscoverage['javascript-let.js'][28]++;
+ alert("Item " + j + " is clicked.");
+});
+ _$jscoverage['javascript-let.js'][30]++;
+ list.appendChild(item);
+ }
+}
+_$jscoverage['javascript-let.js'][33]++;
+function varTest() {
+ _$jscoverage['javascript-let.js'][34]++;
+ var x = 31;
+ _$jscoverage['javascript-let.js'][35]++;
+ if (true) {
+ _$jscoverage['javascript-let.js'][36]++;
+ var x = 71;
+ _$jscoverage['javascript-let.js'][37]++;
+ alert(x);
+ }
+ _$jscoverage['javascript-let.js'][39]++;
+ alert(x);
+}
+_$jscoverage['javascript-let.js'][42]++;
+function letTest() {
+ _$jscoverage['javascript-let.js'][43]++;
+ var x = 31;
+ {
+ _$jscoverage['javascript-let.js'][45]++;
+ let x = 71;
+ _$jscoverage['javascript-let.js'][46]++;
+ alert(x);
+ }
+ _$jscoverage['javascript-let.js'][48]++;
+ alert(x);
+}
+_$jscoverage['javascript-let.js'][51]++;
+function letTests() {
+ _$jscoverage['javascript-let.js'][52]++;
+ var x = 10;
+ _$jscoverage['javascript-let.js'][55]++;
+ let (x = x + 20) {
+ _$jscoverage['javascript-let.js'][56]++;
+ alert(x);
+ }
+ _$jscoverage['javascript-let.js'][60]++;
+ alert(let(x = x + 20) x);
+ {
+ _$jscoverage['javascript-let.js'][64]++;
+ let x = x + 20;
+ _$jscoverage['javascript-let.js'][65]++;
+ alert(x);
+ }
+}
+_$jscoverage['javascript-let.js'][69]++;
+var x = "global";
+_$jscoverage['javascript-let.js'][70]++;
+var x = 42;
+_$jscoverage['javascript-let.js'][71]++;
+document.write(this.x + "<br>\n");
+_$jscoverage['javascript-let.js'][74]++;
+var i = 0;
+_$jscoverage['javascript-let.js'][75]++;
+for (let i = i; i < 10; i++) {
+ _$jscoverage['javascript-let.js'][76]++;
+ document.write(i + "<br>\n");
+}
+_$jscoverage['javascript-let.js'][78]++;
+for (let [name, value] in obj) {
+ _$jscoverage['javascript-let.js'][79]++;
+ document.write("Name: " + name + ", Value: " + value + "<br>\n");
+}
+_$jscoverage['javascript-let.js'].source = ["<span class=\"c\">// https://developer.mozilla.org/en/New_in_JavaScript_1.7</span>","","<span class=\"c\">// let statement</span>","","<span class=\"k\">let</span> <span class=\"k\">(</span>x <span class=\"k\">=</span> x<span class=\"k\">+</span><span class=\"s\">10</span><span class=\"k\">,</span> y <span class=\"k\">=</span> <span class=\"s\">12</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," print<span class=\"k\">(</span>x<span class=\"k\">+</span>y <span class=\"k\">+</span> <span class=\"s\">\"</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"c\">// let expressions</span>","","print<span class=\"k\">(</span> <span class=\"k\">let</span><span class=\"k\">(</span>x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">10</span><span class=\"k\">,</span> y <span class=\"k\">=</span> <span class=\"s\">12</span><span class=\"k\">)</span> x<span class=\"k\">+</span>y <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","","<span class=\"c\">// let definitions</span>","","<span class=\"k\">if</span> <span class=\"k\">(</span>x <span class=\"k\">&gt;</span> y<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> gamma <span class=\"k\">=</span> <span class=\"s\">12.7</span> <span class=\"k\">+</span> y<span class=\"k\">;</span>"," i <span class=\"k\">=</span> gamma <span class=\"k\">*</span> x<span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">var</span> list <span class=\"k\">=</span> document<span class=\"k\">.</span>getElementById<span class=\"k\">(</span><span class=\"s\">\"list\"</span><span class=\"k\">);</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span><span class=\"k\">var</span> i <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span> i <span class=\"k\">&lt;=</span> <span class=\"s\">5</span><span class=\"k\">;</span> i<span class=\"k\">++)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> item <span class=\"k\">=</span> document<span class=\"k\">.</span>createElement<span class=\"k\">(</span><span class=\"s\">\"LI\"</span><span class=\"k\">);</span>"," item<span class=\"k\">.</span>appendChild<span class=\"k\">(</span>document<span class=\"k\">.</span>createTextNode<span class=\"k\">(</span><span class=\"s\">\"Item \"</span> <span class=\"k\">+</span> i<span class=\"k\">));</span>",""," <span class=\"k\">let</span> j <span class=\"k\">=</span> i<span class=\"k\">;</span>"," item<span class=\"k\">.</span>onclick <span class=\"k\">=</span> <span class=\"k\">function</span> <span class=\"k\">(</span>ev<span class=\"k\">)</span> <span class=\"k\">{</span>"," alert<span class=\"k\">(</span><span class=\"s\">\"Item \"</span> <span class=\"k\">+</span> j <span class=\"k\">+</span> <span class=\"s\">\" is clicked.\"</span><span class=\"k\">);</span>"," <span class=\"k\">}</span><span class=\"k\">;</span>"," list<span class=\"k\">.</span>appendChild<span class=\"k\">(</span>item<span class=\"k\">);</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> varTest<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">31</span><span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">71</span><span class=\"k\">;</span> <span class=\"c\">// same variable!</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 71</span>"," <span class=\"k\">}</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 71</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> letTest<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">31</span><span class=\"k\">;</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span><span class=\"k\">true</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">71</span><span class=\"k\">;</span> <span class=\"c\">// different variable</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 71</span>"," <span class=\"k\">}</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 31</span>","<span class=\"k\">}</span>","","<span class=\"k\">function</span> letTests<span class=\"k\">()</span> <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">10</span><span class=\"k\">;</span>",""," <span class=\"c\">// let-statement</span>"," <span class=\"k\">let</span> <span class=\"k\">(</span>x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">20</span><span class=\"k\">)</span> <span class=\"k\">{</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// 30</span>"," <span class=\"k\">}</span>",""," <span class=\"c\">// let-expression</span>"," alert<span class=\"k\">(</span><span class=\"k\">let</span> <span class=\"k\">(</span>x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">20</span><span class=\"k\">)</span> x<span class=\"k\">);</span> <span class=\"c\">// 30</span>",""," <span class=\"c\">// let-definition</span>"," <span class=\"k\">{</span>"," <span class=\"k\">let</span> x <span class=\"k\">=</span> x <span class=\"k\">+</span> <span class=\"s\">20</span><span class=\"k\">;</span> <span class=\"c\">// x here evaluates to undefined</span>"," alert<span class=\"k\">(</span>x<span class=\"k\">);</span> <span class=\"c\">// undefined + 20 ==&gt; NaN</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">'global'</span><span class=\"k\">;</span>","<span class=\"k\">let</span> x <span class=\"k\">=</span> <span class=\"s\">42</span><span class=\"k\">;</span>","document<span class=\"k\">.</span>write<span class=\"k\">(</span><span class=\"k\">this</span><span class=\"k\">.</span>x <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","","<span class=\"c\">// let-scoped variables in for loops</span>","<span class=\"k\">var</span> i<span class=\"k\">=</span><span class=\"s\">0</span><span class=\"k\">;</span>","<span class=\"k\">for</span> <span class=\"k\">(</span> <span class=\"k\">let</span> i<span class=\"k\">=</span>i <span class=\"k\">;</span> i <span class=\"k\">&lt;</span> <span class=\"s\">10</span> <span class=\"k\">;</span> i<span class=\"k\">++</span> <span class=\"k\">)</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span>i <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>","","<span class=\"k\">for</span> <span class=\"k\">(</span> <span class=\"k\">let</span> <span class=\"k\">[</span>name<span class=\"k\">,</span>value<span class=\"k\">]</span> <span class=\"k\">in</span> obj <span class=\"k\">)</span>"," document<span class=\"k\">.</span>write<span class=\"k\">(</span><span class=\"s\">\"Name: \"</span> <span class=\"k\">+</span> name <span class=\"k\">+</span> <span class=\"s\">\", Value: \"</span> <span class=\"k\">+</span> value <span class=\"k\">+</span> <span class=\"s\">\"&lt;br&gt;</span><span class=\"t\">\\n</span><span class=\"s\">\"</span><span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js
new file mode 100644
index 0000000..c698ede
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-lf.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-lf.js']) {
+ _$jscoverage['javascript-lf.js'] = [];
+ _$jscoverage['javascript-lf.js'][4] = 0;
+}
+_$jscoverage['javascript-lf.js'][4]++;
+var x = 1;
+_$jscoverage['javascript-lf.js'].source = ["<span class=\"c\">/*</span>","<span class=\"c\">This file has LF line endings.</span>","<span class=\"c\">*/</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js
new file mode 100644
index 0000000..417227a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-new.js
@@ -0,0 +1,22 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-new.js']) {
+ _$jscoverage['javascript-new.js'] = [];
+ _$jscoverage['javascript-new.js'][1] = 0;
+ _$jscoverage['javascript-new.js'][2] = 0;
+ _$jscoverage['javascript-new.js'][3] = 0;
+ _$jscoverage['javascript-new.js'][4] = 0;
+}
+_$jscoverage['javascript-new.js'][1]++;
+function X() {
+}
+_$jscoverage['javascript-new.js'][2]++;
+x = new X();
+_$jscoverage['javascript-new.js'][3]++;
+x = new X(1);
+_$jscoverage['javascript-new.js'][4]++;
+x = new X(1, 2);
+_$jscoverage['javascript-new.js'].source = ["<span class=\"k\">function</span> X<span class=\"k\">()</span> <span class=\"k\">{}</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> X<span class=\"k\">();</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> X<span class=\"k\">(</span><span class=\"s\">1</span><span class=\"k\">);</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> X<span class=\"k\">(</span><span class=\"s\">1</span><span class=\"k\">,</span> <span class=\"s\">2</span><span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js
new file mode 100644
index 0000000..45a9b77
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-number.js
@@ -0,0 +1,57 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-number.js']) {
+ _$jscoverage['javascript-number.js'] = [];
+ _$jscoverage['javascript-number.js'][1] = 0;
+ _$jscoverage['javascript-number.js'][2] = 0;
+ _$jscoverage['javascript-number.js'][3] = 0;
+ _$jscoverage['javascript-number.js'][5] = 0;
+ _$jscoverage['javascript-number.js'][6] = 0;
+ _$jscoverage['javascript-number.js'][8] = 0;
+ _$jscoverage['javascript-number.js'][9] = 0;
+ _$jscoverage['javascript-number.js'][11] = 0;
+ _$jscoverage['javascript-number.js'][12] = 0;
+ _$jscoverage['javascript-number.js'][13] = 0;
+ _$jscoverage['javascript-number.js'][14] = 0;
+ _$jscoverage['javascript-number.js'][15] = 0;
+ _$jscoverage['javascript-number.js'][16] = 0;
+ _$jscoverage['javascript-number.js'][17] = 0;
+ _$jscoverage['javascript-number.js'][18] = 0;
+ _$jscoverage['javascript-number.js'][19] = 0;
+}
+_$jscoverage['javascript-number.js'][1]++;
+x = 1;
+_$jscoverage['javascript-number.js'][2]++;
+y = 2;
+_$jscoverage['javascript-number.js'][3]++;
+z = 10.5;
+_$jscoverage['javascript-number.js'][5]++;
+a = Number.POSITIVE_INFINITY;
+_$jscoverage['javascript-number.js'][6]++;
+a = Number.NEGATIVE_INFINITY;
+_$jscoverage['javascript-number.js'][8]++;
+a = 0;
+_$jscoverage['javascript-number.js'][9]++;
+a = -0;
+_$jscoverage['javascript-number.js'][11]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][12]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][13]++;
+a = 0 / (-0);
+_$jscoverage['javascript-number.js'][14]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][15]++;
+a = (-0) / 0;
+_$jscoverage['javascript-number.js'][16]++;
+a = Number.NaN;
+_$jscoverage['javascript-number.js'][17]++;
+a = -0 / (-0);
+_$jscoverage['javascript-number.js'][18]++;
+a = (-0) / -0;
+_$jscoverage['javascript-number.js'][19]++;
+a = (-0) / (-0);
+_$jscoverage['javascript-number.js'].source = ["x <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","y <span class=\"k\">=</span> <span class=\"s\">2</span><span class=\"k\">;</span>","z <span class=\"k\">=</span> <span class=\"s\">10.5</span><span class=\"k\">;</span>","","a <span class=\"k\">=</span> <span class=\"s\">1</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">1</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","","a <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","","a <span class=\"k\">=</span> <span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">);</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">)</span> <span class=\"k\">/</span> <span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">-</span><span class=\"s\">0</span> <span class=\"k\">/</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">);</span>","a <span class=\"k\">=</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">)</span> <span class=\"k\">/</span> <span class=\"k\">-</span><span class=\"s\">0</span><span class=\"k\">;</span>","a <span class=\"k\">=</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">)</span> <span class=\"k\">/</span> <span class=\"k\">(-</span><span class=\"s\">0</span><span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js
new file mode 100644
index 0000000..b3cf03f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-object.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-object.js']) {
+ _$jscoverage['javascript-object.js'] = [];
+ _$jscoverage['javascript-object.js'][1] = 0;
+ _$jscoverage['javascript-object.js'][2] = 0;
+}
+_$jscoverage['javascript-object.js'][1]++;
+x = /x\(\)\\\//i;
+_$jscoverage['javascript-object.js'][2]++;
+y = /\u0001\u002f/gm;
+_$jscoverage['javascript-object.js'].source = ["x <span class=\"k\">=</span> <span class=\"s\">/x\\(\\)\\\\\\//i</span><span class=\"k\">;</span>","y <span class=\"k\">=</span> <span class=\"s\">/\\u0001\\u002f/gm</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js
new file mode 100644
index 0000000..b6966aa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-op.js
@@ -0,0 +1,108 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-op.js']) {
+ _$jscoverage['javascript-op.js'] = [];
+ _$jscoverage['javascript-op.js'][1] = 0;
+ _$jscoverage['javascript-op.js'][4] = 0;
+ _$jscoverage['javascript-op.js'][5] = 0;
+ _$jscoverage['javascript-op.js'][8] = 0;
+ _$jscoverage['javascript-op.js'][9] = 0;
+ _$jscoverage['javascript-op.js'][11] = 0;
+ _$jscoverage['javascript-op.js'][13] = 0;
+ _$jscoverage['javascript-op.js'][16] = 0;
+ _$jscoverage['javascript-op.js'][17] = 0;
+ _$jscoverage['javascript-op.js'][20] = 0;
+ _$jscoverage['javascript-op.js'][21] = 0;
+ _$jscoverage['javascript-op.js'][24] = 0;
+ _$jscoverage['javascript-op.js'][25] = 0;
+ _$jscoverage['javascript-op.js'][28] = 0;
+ _$jscoverage['javascript-op.js'][29] = 0;
+ _$jscoverage['javascript-op.js'][30] = 0;
+ _$jscoverage['javascript-op.js'][31] = 0;
+ _$jscoverage['javascript-op.js'][34] = 0;
+ _$jscoverage['javascript-op.js'][35] = 0;
+ _$jscoverage['javascript-op.js'][36] = 0;
+ _$jscoverage['javascript-op.js'][37] = 0;
+ _$jscoverage['javascript-op.js'][40] = 0;
+ _$jscoverage['javascript-op.js'][41] = 0;
+ _$jscoverage['javascript-op.js'][42] = 0;
+ _$jscoverage['javascript-op.js'][45] = 0;
+ _$jscoverage['javascript-op.js'][46] = 0;
+ _$jscoverage['javascript-op.js'][47] = 0;
+ _$jscoverage['javascript-op.js'][48] = 0;
+ _$jscoverage['javascript-op.js'][51] = 0;
+ _$jscoverage['javascript-op.js'][52] = 0;
+ _$jscoverage['javascript-op.js'][53] = 0;
+ _$jscoverage['javascript-op.js'][54] = 0;
+ _$jscoverage['javascript-op.js'][55] = 0;
+}
+_$jscoverage['javascript-op.js'][1]++;
+var a = 1, b = 1, c = 1, d = 1;
+_$jscoverage['javascript-op.js'][4]++;
+x = a || b || c;
+_$jscoverage['javascript-op.js'][5]++;
+x = a || b || c || d;
+_$jscoverage['javascript-op.js'][8]++;
+x = a && b && c;
+_$jscoverage['javascript-op.js'][9]++;
+x = a && b && c && d;
+_$jscoverage['javascript-op.js'][11]++;
+x = a && b || c;
+_$jscoverage['javascript-op.js'][13]++;
+x = a || b && c;
+_$jscoverage['javascript-op.js'][16]++;
+x = a | b | c;
+_$jscoverage['javascript-op.js'][17]++;
+x = a | b | c | d;
+_$jscoverage['javascript-op.js'][20]++;
+x = a ^ b ^ c;
+_$jscoverage['javascript-op.js'][21]++;
+x = a ^ b ^ c ^ d;
+_$jscoverage['javascript-op.js'][24]++;
+x = a & b & c;
+_$jscoverage['javascript-op.js'][25]++;
+x = a & b & c & d;
+_$jscoverage['javascript-op.js'][28]++;
+x = a == b;
+_$jscoverage['javascript-op.js'][29]++;
+x = a != b;
+_$jscoverage['javascript-op.js'][30]++;
+x = a === b;
+_$jscoverage['javascript-op.js'][31]++;
+x = a !== b;
+_$jscoverage['javascript-op.js'][34]++;
+x = a < b;
+_$jscoverage['javascript-op.js'][35]++;
+x = a <= b;
+_$jscoverage['javascript-op.js'][36]++;
+x = a > b;
+_$jscoverage['javascript-op.js'][37]++;
+x = a >= b;
+_$jscoverage['javascript-op.js'][40]++;
+x = a << b;
+_$jscoverage['javascript-op.js'][41]++;
+x = a >> b;
+_$jscoverage['javascript-op.js'][42]++;
+x = a >>> b;
+_$jscoverage['javascript-op.js'][45]++;
+x = a + b;
+_$jscoverage['javascript-op.js'][46]++;
+x = a + b + c;
+_$jscoverage['javascript-op.js'][47]++;
+x = a + b + c + d;
+_$jscoverage['javascript-op.js'][48]++;
+x = a - b;
+_$jscoverage['javascript-op.js'][51]++;
+x = a * b;
+_$jscoverage['javascript-op.js'][52]++;
+x = a * b * c;
+_$jscoverage['javascript-op.js'][53]++;
+x = a * b * c * d;
+_$jscoverage['javascript-op.js'][54]++;
+x = a / b;
+_$jscoverage['javascript-op.js'][55]++;
+x = a % b;
+_$jscoverage['javascript-op.js'].source = ["<span class=\"k\">var</span> a <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">,</span> b <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">,</span> c <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">,</span> d <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>","","<span class=\"c\">/* TOK_OR */</span>","x <span class=\"k\">=</span> a <span class=\"k\">||</span> b <span class=\"k\">||</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">||</span> b <span class=\"k\">||</span> c <span class=\"k\">||</span> d<span class=\"k\">;</span>","","<span class=\"c\">/* TOK_AND */</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;&amp;</span> b <span class=\"k\">&amp;&amp;</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;&amp;</span> b <span class=\"k\">&amp;&amp;</span> c <span class=\"k\">&amp;&amp;</span> d<span class=\"k\">;</span>","","x <span class=\"k\">=</span> a <span class=\"k\">&amp;&amp;</span> b <span class=\"k\">||</span> c<span class=\"k\">;</span>","","x <span class=\"k\">=</span> a <span class=\"k\">||</span> b <span class=\"k\">&amp;&amp;</span> c<span class=\"k\">;</span>","","<span class=\"c\">// TOK_BITOR</span>","x <span class=\"k\">=</span> a <span class=\"k\">|</span> b <span class=\"k\">|</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">|</span> b <span class=\"k\">|</span> c <span class=\"k\">|</span> d<span class=\"k\">;</span>","","<span class=\"c\">// TOK_BITXOR</span>","x <span class=\"k\">=</span> a <span class=\"k\">^</span> b <span class=\"k\">^</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">^</span> b <span class=\"k\">^</span> c <span class=\"k\">^</span> d<span class=\"k\">;</span>","","<span class=\"c\">// TOK_BITAND</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;</span> b <span class=\"k\">&amp;</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&amp;</span> b <span class=\"k\">&amp;</span> c <span class=\"k\">&amp;</span> d<span class=\"k\">;</span>","","<span class=\"c\">// TOK_EQUOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">==</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">!=</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">===</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">!==</span> b<span class=\"k\">;</span>","","<span class=\"c\">// TOK_RELOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">&lt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&lt;=</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;=</span> b<span class=\"k\">;</span>","","<span class=\"c\">// TOK_SHOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">&lt;&lt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;&gt;</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">&gt;&gt;&gt;</span> b<span class=\"k\">;</span>","","<span class=\"c\">/* TOK_PLUS, TOK_MINUS */</span>","x <span class=\"k\">=</span> a <span class=\"k\">+</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">+</span> b <span class=\"k\">+</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">+</span> b <span class=\"k\">+</span> c <span class=\"k\">+</span> d<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">-</span> b<span class=\"k\">;</span>","","<span class=\"c\">// TOK_STAR, TOK_DIVOP</span>","x <span class=\"k\">=</span> a <span class=\"k\">*</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">*</span> b <span class=\"k\">*</span> c<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">*</span> b <span class=\"k\">*</span> c <span class=\"k\">*</span> d<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">/</span> b<span class=\"k\">;</span>","x <span class=\"k\">=</span> a <span class=\"k\">%</span> b<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js
new file mode 100644
index 0000000..c6e46d9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-primary.js
@@ -0,0 +1,21 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-primary.js']) {
+ _$jscoverage['javascript-primary.js'] = [];
+ _$jscoverage['javascript-primary.js'][1] = 0;
+ _$jscoverage['javascript-primary.js'][2] = 0;
+ _$jscoverage['javascript-primary.js'][3] = 0;
+ _$jscoverage['javascript-primary.js'][4] = 0;
+}
+_$jscoverage['javascript-primary.js'][1]++;
+x = true;
+_$jscoverage['javascript-primary.js'][2]++;
+x = false;
+_$jscoverage['javascript-primary.js'][3]++;
+x = null;
+_$jscoverage['javascript-primary.js'][4]++;
+x = this;
+_$jscoverage['javascript-primary.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">true</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">false</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">null</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">this</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js
new file mode 100644
index 0000000..df807b1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rb.js
@@ -0,0 +1,24 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-rb.js']) {
+ _$jscoverage['javascript-rb.js'] = [];
+ _$jscoverage['javascript-rb.js'][1] = 0;
+ _$jscoverage['javascript-rb.js'][2] = 0;
+ _$jscoverage['javascript-rb.js'][3] = 0;
+ _$jscoverage['javascript-rb.js'][4] = 0;
+ _$jscoverage['javascript-rb.js'][5] = 0;
+}
+_$jscoverage['javascript-rb.js'][1]++;
+x = [];
+_$jscoverage['javascript-rb.js'][2]++;
+x = [x];
+_$jscoverage['javascript-rb.js'][3]++;
+x = [x, y];
+_$jscoverage['javascript-rb.js'][4]++;
+x = [x, y,];
+_$jscoverage['javascript-rb.js'][5]++;
+x = [x, , y];
+_$jscoverage['javascript-rb.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">[];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">,</span> y<span class=\"k\">];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">,</span> y<span class=\"k\">,];</span>","x <span class=\"k\">=</span> <span class=\"k\">[</span>x<span class=\"k\">,,</span> y<span class=\"k\">];</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js
new file mode 100644
index 0000000..e3108d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rc.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-rc.js']) {
+ _$jscoverage['javascript-rc.js'] = [];
+ _$jscoverage['javascript-rc.js'][1] = 0;
+ _$jscoverage['javascript-rc.js'][4] = 0;
+}
+_$jscoverage['javascript-rc.js'][1]++;
+x = {x: y};
+_$jscoverage['javascript-rc.js'][4]++;
+x = {x: y, y: x};
+_$jscoverage['javascript-rc.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">{</span>"," x<span class=\"k\">:</span> y","<span class=\"k\">}</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">{</span>"," x<span class=\"k\">:</span> y<span class=\"k\">,</span>"," y<span class=\"k\">:</span> x","<span class=\"k\">}</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js
new file mode 100644
index 0000000..47df295
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-rp.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-rp.js']) {
+ _$jscoverage['javascript-rp.js'] = [];
+ _$jscoverage['javascript-rp.js'][1] = 0;
+}
+_$jscoverage['javascript-rp.js'][1]++;
+x = a + (b - c);
+_$jscoverage['javascript-rp.js'].source = ["x <span class=\"k\">=</span> a <span class=\"k\">+</span> <span class=\"k\">(</span>b <span class=\"k\">-</span> c<span class=\"k\">);</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js
new file mode 100644
index 0000000..0154e86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-special-characters.js
@@ -0,0 +1,30 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-special-characters.js']) {
+ _$jscoverage['javascript-special-characters.js'] = [];
+ _$jscoverage['javascript-special-characters.js'][1] = 0;
+ _$jscoverage['javascript-special-characters.js'][2] = 0;
+ _$jscoverage['javascript-special-characters.js'][5] = 0;
+ _$jscoverage['javascript-special-characters.js'][6] = 0;
+ _$jscoverage['javascript-special-characters.js'][9] = 0;
+ _$jscoverage['javascript-special-characters.js'][10] = 0;
+}
+_$jscoverage['javascript-special-characters.js'][1]++;
+function f() {
+ _$jscoverage['javascript-special-characters.js'][2]++;
+ return "'";
+}
+_$jscoverage['javascript-special-characters.js'][5]++;
+function g() {
+ _$jscoverage['javascript-special-characters.js'][6]++;
+ return "\"";
+}
+_$jscoverage['javascript-special-characters.js'][9]++;
+function h() {
+ _$jscoverage['javascript-special-characters.js'][10]++;
+ return "\\";
+}
+_$jscoverage['javascript-special-characters.js'].source = ["<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{</span>","\t<span class=\"k\">return</span> <span class=\"s\">'</span><span class=\"t\">\\'</span><span class=\"s\">'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","&#11;","<span class=\"k\">function</span> g<span class=\"k\">()</span> <span class=\"k\">{</span>","\t<span class=\"k\">return</span> <span class=\"s\">\"</span><span class=\"t\">\\\"</span><span class=\"s\">\"</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","&#12;","<span class=\"k\">function</span> h<span class=\"k\">()</span> <span class=\"k\">{</span>","\t<span class=\"k\">return</span> <span class=\"s\">'</span><span class=\"t\">\\\\</span><span class=\"s\">'</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js
new file mode 100644
index 0000000..3dbacc8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-string.js
@@ -0,0 +1,36 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-string.js']) {
+ _$jscoverage['javascript-string.js'] = [];
+ _$jscoverage['javascript-string.js'][1] = 0;
+ _$jscoverage['javascript-string.js'][2] = 0;
+ _$jscoverage['javascript-string.js'][3] = 0;
+ _$jscoverage['javascript-string.js'][4] = 0;
+ _$jscoverage['javascript-string.js'][5] = 0;
+ _$jscoverage['javascript-string.js'][6] = 0;
+ _$jscoverage['javascript-string.js'][7] = 0;
+ _$jscoverage['javascript-string.js'][8] = 0;
+ _$jscoverage['javascript-string.js'][10] = 0;
+}
+_$jscoverage['javascript-string.js'][1]++;
+x = "";
+_$jscoverage['javascript-string.js'][2]++;
+x = "";
+_$jscoverage['javascript-string.js'][3]++;
+x = "x";
+_$jscoverage['javascript-string.js'][4]++;
+x = "x";
+_$jscoverage['javascript-string.js'][5]++;
+x = "\"";
+_$jscoverage['javascript-string.js'][6]++;
+x = "'";
+_$jscoverage['javascript-string.js'][7]++;
+x = "\b\t\n\u000b\f\r\"'\\";
+_$jscoverage['javascript-string.js'][8]++;
+x = new RegExp("x\\(\\)\\\\\\/");
+_$jscoverage['javascript-string.js'][10]++;
+x = "foobar";
+_$jscoverage['javascript-string.js'].source = ["x <span class=\"k\">=</span> <span class=\"s\">\"\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">''</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">\"x\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">'x'</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">\"</span><span class=\"t\">\\\"</span><span class=\"s\">\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">'</span><span class=\"t\">\\'</span><span class=\"s\">'</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"s\">\"</span><span class=\"t\">\\b\\t\\n\\v\\f\\r\\\"\\'\\\\</span><span class=\"s\">\"</span><span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">new</span> RegExp<span class=\"k\">(</span><span class=\"s\">'x</span><span class=\"t\">\\\\</span><span class=\"s\">(</span><span class=\"t\">\\\\</span><span class=\"s\">)</span><span class=\"t\">\\\\\\\\\\\\</span><span class=\"s\">/'</span><span class=\"k\">);</span>","","x <span class=\"k\">=</span> <span class=\"s\">'foo</span><span class=\"t\">\\</span>","<span class=\"s\">bar'</span><span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js
new file mode 100644
index 0000000..e198d7f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-switch.js
@@ -0,0 +1,55 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-switch.js']) {
+ _$jscoverage['javascript-switch.js'] = [];
+ _$jscoverage['javascript-switch.js'][1] = 0;
+ _$jscoverage['javascript-switch.js'][3] = 0;
+ _$jscoverage['javascript-switch.js'][4] = 0;
+ _$jscoverage['javascript-switch.js'][6] = 0;
+ _$jscoverage['javascript-switch.js'][7] = 0;
+ _$jscoverage['javascript-switch.js'][8] = 0;
+ _$jscoverage['javascript-switch.js'][10] = 0;
+ _$jscoverage['javascript-switch.js'][11] = 0;
+ _$jscoverage['javascript-switch.js'][14] = 0;
+ _$jscoverage['javascript-switch.js'][16] = 0;
+ _$jscoverage['javascript-switch.js'][17] = 0;
+ _$jscoverage['javascript-switch.js'][18] = 0;
+ _$jscoverage['javascript-switch.js'][20] = 0;
+}
+_$jscoverage['javascript-switch.js'][1]++;
+switch (x) {
+case x:
+ _$jscoverage['javascript-switch.js'][3]++;
+ x = 0;
+ _$jscoverage['javascript-switch.js'][4]++;
+ break;
+case y:
+ _$jscoverage['javascript-switch.js'][6]++;
+ x = 0;
+ _$jscoverage['javascript-switch.js'][7]++;
+ y = 0;
+ _$jscoverage['javascript-switch.js'][8]++;
+ break;
+default:
+ _$jscoverage['javascript-switch.js'][10]++;
+ x = 0;
+ _$jscoverage['javascript-switch.js'][11]++;
+ break;
+}
+_$jscoverage['javascript-switch.js'][14]++;
+switch (x) {
+case 1:
+ _$jscoverage['javascript-switch.js'][16]++;
+ let y = 1;
+ _$jscoverage['javascript-switch.js'][17]++;
+ f(y);
+ _$jscoverage['javascript-switch.js'][18]++;
+ break;
+case 2:
+ _$jscoverage['javascript-switch.js'][20]++;
+ break;
+}
+_$jscoverage['javascript-switch.js'].source = ["<span class=\"k\">switch</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>","<span class=\"k\">case</span> x<span class=\"k\">:</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">case</span> y<span class=\"k\">:</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," y <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">default</span><span class=\"k\">:</span>"," x <span class=\"k\">=</span> <span class=\"s\">0</span><span class=\"k\">;</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">switch</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>","<span class=\"k\">case</span> <span class=\"s\">1</span><span class=\"k\">:</span>"," <span class=\"k\">let</span> y <span class=\"k\">=</span> <span class=\"s\">1</span><span class=\"k\">;</span>"," f<span class=\"k\">(</span>y<span class=\"k\">);</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">case</span> <span class=\"s\">2</span><span class=\"k\">:</span>"," <span class=\"k\">break</span><span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js
new file mode 100644
index 0000000..2acaa17
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-throw.js
@@ -0,0 +1,21 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-throw.js']) {
+ _$jscoverage['javascript-throw.js'] = [];
+ _$jscoverage['javascript-throw.js'][1] = 0;
+ _$jscoverage['javascript-throw.js'][2] = 0;
+ _$jscoverage['javascript-throw.js'][5] = 0;
+}
+_$jscoverage['javascript-throw.js'][1]++;
+try {
+ _$jscoverage['javascript-throw.js'][2]++;
+ throw "x";
+}
+catch (e) {
+ _$jscoverage['javascript-throw.js'][5]++;
+ ;
+}
+_$jscoverage['javascript-throw.js'].source = ["<span class=\"k\">try</span> <span class=\"k\">{</span>"," <span class=\"k\">throw</span> <span class=\"s\">\"x\"</span><span class=\"k\">;</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js
new file mode 100644
index 0000000..8111f17
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-try.js
@@ -0,0 +1,66 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-try.js']) {
+ _$jscoverage['javascript-try.js'] = [];
+ _$jscoverage['javascript-try.js'][1] = 0;
+ _$jscoverage['javascript-try.js'][3] = 0;
+ _$jscoverage['javascript-try.js'][4] = 0;
+ _$jscoverage['javascript-try.js'][7] = 0;
+ _$jscoverage['javascript-try.js'][10] = 0;
+ _$jscoverage['javascript-try.js'][11] = 0;
+ _$jscoverage['javascript-try.js'][14] = 0;
+ _$jscoverage['javascript-try.js'][17] = 0;
+ _$jscoverage['javascript-try.js'][18] = 0;
+ _$jscoverage['javascript-try.js'][21] = 0;
+ _$jscoverage['javascript-try.js'][24] = 0;
+ _$jscoverage['javascript-try.js'][25] = 0;
+ _$jscoverage['javascript-try.js'][28] = 0;
+ _$jscoverage['javascript-try.js'][31] = 0;
+}
+_$jscoverage['javascript-try.js'][1]++;
+function f() {
+}
+_$jscoverage['javascript-try.js'][3]++;
+try {
+ _$jscoverage['javascript-try.js'][4]++;
+ f();
+}
+catch (e) {
+ _$jscoverage['javascript-try.js'][7]++;
+ f();
+}
+_$jscoverage['javascript-try.js'][10]++;
+try {
+ _$jscoverage['javascript-try.js'][11]++;
+ f();
+}
+catch (e if e instanceof E) {
+ _$jscoverage['javascript-try.js'][14]++;
+ f();
+}
+_$jscoverage['javascript-try.js'][17]++;
+try {
+ _$jscoverage['javascript-try.js'][18]++;
+ f();
+}
+finally {
+ _$jscoverage['javascript-try.js'][21]++;
+ f();
+}
+_$jscoverage['javascript-try.js'][24]++;
+try {
+ _$jscoverage['javascript-try.js'][25]++;
+ f();
+}
+catch (e) {
+ _$jscoverage['javascript-try.js'][28]++;
+ f();
+}
+finally {
+ _$jscoverage['javascript-try.js'][31]++;
+ f();
+}
+_$jscoverage['javascript-try.js'].source = ["<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e <span class=\"k\">if</span> e <span class=\"k\">instanceof</span> E<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">finally</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">try</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">catch</span> <span class=\"k\">(</span>e<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","<span class=\"k\">finally</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js
new file mode 100644
index 0000000..ca06e39
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-unaryop.js
@@ -0,0 +1,27 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-unaryop.js']) {
+ _$jscoverage['javascript-unaryop.js'] = [];
+ _$jscoverage['javascript-unaryop.js'][1] = 0;
+ _$jscoverage['javascript-unaryop.js'][2] = 0;
+ _$jscoverage['javascript-unaryop.js'][3] = 0;
+ _$jscoverage['javascript-unaryop.js'][4] = 0;
+ _$jscoverage['javascript-unaryop.js'][5] = 0;
+ _$jscoverage['javascript-unaryop.js'][6] = 0;
+}
+_$jscoverage['javascript-unaryop.js'][1]++;
+x = - x;
+_$jscoverage['javascript-unaryop.js'][2]++;
+x = + x;
+_$jscoverage['javascript-unaryop.js'][3]++;
+x = ! x;
+_$jscoverage['javascript-unaryop.js'][4]++;
+x = ~ x;
+_$jscoverage['javascript-unaryop.js'][5]++;
+x = typeof x;
+_$jscoverage['javascript-unaryop.js'][6]++;
+x = void x;
+_$jscoverage['javascript-unaryop.js'].source = ["x <span class=\"k\">=</span> <span class=\"k\">-</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">+</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">!</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">~</span>x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">typeof</span> x<span class=\"k\">;</span>","x <span class=\"k\">=</span> <span class=\"k\">void</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js
new file mode 100644
index 0000000..904bbcf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-var.js
@@ -0,0 +1,15 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-var.js']) {
+ _$jscoverage['javascript-var.js'] = [];
+ _$jscoverage['javascript-var.js'][1] = 0;
+ _$jscoverage['javascript-var.js'][2] = 0;
+}
+_$jscoverage['javascript-var.js'][1]++;
+var x;
+_$jscoverage['javascript-var.js'][2]++;
+var y = x, z = x;
+_$jscoverage['javascript-var.js'].source = ["<span class=\"k\">var</span> x<span class=\"k\">;</span>","<span class=\"k\">var</span> y <span class=\"k\">=</span> x<span class=\"k\">,</span> z <span class=\"k\">=</span> x<span class=\"k\">;</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js
new file mode 100644
index 0000000..b15afa2
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-while.js
@@ -0,0 +1,79 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-while.js']) {
+ _$jscoverage['javascript-while.js'] = [];
+ _$jscoverage['javascript-while.js'][1] = 0;
+ _$jscoverage['javascript-while.js'][2] = 0;
+ _$jscoverage['javascript-while.js'][5] = 0;
+ _$jscoverage['javascript-while.js'][6] = 0;
+ _$jscoverage['javascript-while.js'][9] = 0;
+ _$jscoverage['javascript-while.js'][10] = 0;
+ _$jscoverage['javascript-while.js'][12] = 0;
+ _$jscoverage['javascript-while.js'][13] = 0;
+ _$jscoverage['javascript-while.js'][15] = 0;
+ _$jscoverage['javascript-while.js'][16] = 0;
+ _$jscoverage['javascript-while.js'][17] = 0;
+ _$jscoverage['javascript-while.js'][21] = 0;
+ _$jscoverage['javascript-while.js'][23] = 0;
+ _$jscoverage['javascript-while.js'][24] = 0;
+ _$jscoverage['javascript-while.js'][28] = 0;
+ _$jscoverage['javascript-while.js'][29] = 0;
+ _$jscoverage['javascript-while.js'][30] = 0;
+ _$jscoverage['javascript-while.js'][31] = 0;
+ _$jscoverage['javascript-while.js'][32] = 0;
+}
+_$jscoverage['javascript-while.js'][1]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][2]++;
+ x();
+}
+_$jscoverage['javascript-while.js'][5]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][6]++;
+ ;
+}
+_$jscoverage['javascript-while.js'][9]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][10]++;
+ x();
+}
+_$jscoverage['javascript-while.js'][12]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][13]++;
+ ;
+}
+_$jscoverage['javascript-while.js'][15]++;
+while (x) {
+ _$jscoverage['javascript-while.js'][16]++;
+ if (x) {
+ _$jscoverage['javascript-while.js'][17]++;
+ continue;
+ }
+}
+_$jscoverage['javascript-while.js'][21]++;
+label:
+while (x) {
+ _$jscoverage['javascript-while.js'][23]++;
+ if (x) {
+ _$jscoverage['javascript-while.js'][24]++;
+ continue label;
+ }
+}
+_$jscoverage['javascript-while.js'][28]++;
+label2:
+{
+ _$jscoverage['javascript-while.js'][29]++;
+ f();
+ _$jscoverage['javascript-while.js'][30]++;
+ while (x) {
+ _$jscoverage['javascript-while.js'][31]++;
+ if (x) {
+ _$jscoverage['javascript-while.js'][32]++;
+ break label2;
+ }
+}
+}
+_$jscoverage['javascript-while.js'].source = ["<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," x<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">;</span>","<span class=\"k\">}</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," x<span class=\"k\">();</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," <span class=\"k\">;</span>","","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">continue</span><span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","","label<span class=\"k\">:</span>","<span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">continue</span> label<span class=\"k\">;</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>","","label2<span class=\"k\">:</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>"," <span class=\"k\">while</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">if</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," <span class=\"k\">break</span> label2<span class=\"k\">;</span>"," <span class=\"k\">}</span>"," <span class=\"k\">}</span>","<span class=\"k\">}</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js
new file mode 100644
index 0000000..52aea68
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.expected/javascript-with.js
@@ -0,0 +1,30 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['javascript-with.js']) {
+ _$jscoverage['javascript-with.js'] = [];
+ _$jscoverage['javascript-with.js'][1] = 0;
+ _$jscoverage['javascript-with.js'][2] = 0;
+ _$jscoverage['javascript-with.js'][4] = 0;
+ _$jscoverage['javascript-with.js'][5] = 0;
+ _$jscoverage['javascript-with.js'][8] = 0;
+ _$jscoverage['javascript-with.js'][9] = 0;
+}
+_$jscoverage['javascript-with.js'][1]++;
+function f() {
+}
+_$jscoverage['javascript-with.js'][2]++;
+var x = {};
+_$jscoverage['javascript-with.js'][4]++;
+with (x) {
+ _$jscoverage['javascript-with.js'][5]++;
+ f();
+}
+_$jscoverage['javascript-with.js'][8]++;
+with (x) {
+ _$jscoverage['javascript-with.js'][9]++;
+ f();
+}
+_$jscoverage['javascript-with.js'].source = ["<span class=\"k\">function</span> f<span class=\"k\">()</span> <span class=\"k\">{}</span>","<span class=\"k\">var</span> x <span class=\"k\">=</span> <span class=\"k\">{}</span><span class=\"k\">;</span>","","<span class=\"k\">with</span> <span class=\"k\">(</span>x<span class=\"k\">)</span> <span class=\"k\">{</span>"," f<span class=\"k\">();</span>","<span class=\"k\">}</span>","","<span class=\"k\">with</span> <span class=\"k\">(</span>x<span class=\"k\">)</span>"," f<span class=\"k\">();</span>"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript.sh b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.sh
new file mode 100755
index 0000000..6209a0f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# javascript.sh - test various JavaScript constructs
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+rm -fr DIR
+case "$character_encoding_support" in
+ yes)
+ $VALGRIND jscoverage --js-version 180 --encoding ISO-8859-1 javascript DIR
+ ;;
+ *)
+ $VALGRIND jscoverage --js-version=180 --exclude=javascript-iso-8859-1.js javascript DIR
+ ;;
+esac
+for i in javascript/*.js
+do
+ if [ $character_encoding_support = no -a $i = javascript/javascript-iso-8859-1.js ]
+ then
+ continue
+ fi
+ FILE=${i##javascript/}
+ EXPECTED=javascript.expected/${FILE}
+ ACTUAL=DIR/${FILE}
+ diff -u -r --strip-trailing-cr $EXPECTED $ACTUAL
+done
+
+# rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js
new file mode 100644
index 0000000..2d9b048
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-array-comprehension.js
@@ -0,0 +1,14 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+function range(begin, end) {
+ for (let i = begin; i < end; ++i) {
+ yield i;
+ }
+}
+var ten_squares = [i * i for each (i in range(0, 10))];
+var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
+
+// test optimization
+var optimized = [i for each (i in x) if (0)];
+
+[i for each (a in x) for each (b in y)]
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js
new file mode 100644
index 0000000..d17bdd1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-assign.js
@@ -0,0 +1,14 @@
+var x = 1;
+var y = 1;
+x = y;
+x += y;
+x -= y;
+x *= y;
+x %= y;
+x <<= y;
+x >>= y;
+x >>>= y;
+x &= y;
+x |= y;
+x ^= y;
+x /= y;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js
new file mode 100644
index 0000000..69bade1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-colon.js
@@ -0,0 +1,7 @@
+x:
+ y = 0;
+
+y: {
+ let y = 1;
+ print(y);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js
new file mode 100644
index 0000000..15c162c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-comma.js
@@ -0,0 +1 @@
+x = y, y = x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js
new file mode 100644
index 0000000..fad02c7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-cr.js
@@ -0,0 +1 @@
+/* This file has CR line endings. */ var x = 1; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js
new file mode 100644
index 0000000..53dcd0e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-crlf.js
@@ -0,0 +1,4 @@
+/*
+This file has CRLF line endings.
+*/
+var x = 1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js
new file mode 100644
index 0000000..dc33421
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-debugger.js
@@ -0,0 +1,6 @@
+try {
+ f();
+}
+catch (e) {
+ debugger;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js
new file mode 100644
index 0000000..46d5bc3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dec.js
@@ -0,0 +1,2 @@
+x--;
+--x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js
new file mode 100644
index 0000000..ae9a3d0
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-delete.js
@@ -0,0 +1 @@
+delete x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js
new file mode 100644
index 0000000..c8cf4c9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-destructuring.js
@@ -0,0 +1,42 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+[a, b] = [b, a];
+
+function f() {
+ return [1, 2];
+}
+[a, b] = f();
+
+for (let [name, value] in Iterator(obj)) {
+ print(name);
+ print(value);
+}
+
+for each (let {name: n, family: { father: f } } in people) {
+ print(n);
+ print(f);
+}
+
+var [a, , b] = f();
+[,,,] = f();
+
+function g() {
+ var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
+ if (!parsedURL)
+ return null;
+ var [, protocol, fullhost, fullpath] = parsedURL;
+}
+
+function h(a, [b, c], {foo: d, 'bar': e}) {
+ f();
+ g();
+}
+
+x = function([a, b]) a + b;
+
+({x: x0, y: y0}) = point;
+var {x: x0, y: y0} = point;
+let ({x: x0, y: y0} = point) {
+ print(x0);
+ print(y0);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js
new file mode 100644
index 0000000..e6bbee9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-do.js
@@ -0,0 +1,10 @@
+var x;
+
+do {
+ x = false;
+}
+while (x);
+
+do
+ x = false;
+while (x);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js
new file mode 100644
index 0000000..0b35cdc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-dot.js
@@ -0,0 +1,8 @@
+x.y = y.x;
+x["y"] = y["x"];
+x[y] = y[x];
+x['2y'] = y['var'];
+x[''] = y[""];
+
+print(123.0.toString());
+({}.toString());
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-empty.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js
new file mode 100644
index 0000000..166b586
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-for.js
@@ -0,0 +1,22 @@
+for (i in x) {
+ x();
+}
+
+for (var i in x) {
+ x();
+}
+
+for (i = 0; i < x; i++) {
+ x();
+}
+
+for (var j = 0; j < x; j++) {
+ x();
+}
+
+for (i in x)
+ x();
+
+for (i.value in x) {
+ x();
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js
new file mode 100644
index 0000000..52cb266
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-foreach.js
@@ -0,0 +1,8 @@
+/*
+https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Object_Manipulation_Statements
+https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for_each...in
+*/
+
+for each (var item in obj) {
+ sum += item;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js
new file mode 100644
index 0000000..94fc8bd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-function.js
@@ -0,0 +1,38 @@
+function x() {}
+
+function x() {
+ ;
+}
+
+function x() {
+ x();
+ return 'x';
+}
+
+function x(a) {
+ x();
+}
+
+function x(a, b) {
+ x();
+}
+
+x = function() {
+ x();
+};
+
+(function () {
+ print('x');
+})();
+
+(function (a) {
+ print('x');
+})(1);
+
+(function (a, b) {
+ print('x');
+})(1, 2);
+
+(function () {
+ print('x');
+}).call(window);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js
new file mode 100644
index 0000000..cafec77
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator-expression.js
@@ -0,0 +1,18 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.8
+
+let it = (i + 3 for (i in someObj));
+try {
+ while (true) {
+ document.write(it.next() + "<br>\n");
+ }
+} catch (err if err instanceof StopIteration) {
+ document.write("End of record.<br>\n");
+}
+
+function handleResults( results ) {
+ for ( let i in results )
+ ;
+}
+handleResults( i for ( i in obj ) if ( i > 3 ) );
+
+it = (1 for(a in x) for(b in y));
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js
new file mode 100644
index 0000000..6c1f32a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-generator.js
@@ -0,0 +1,11 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+function fib() {
+ var i = 0, j = 1;
+ while (true) {
+ yield i;
+ var t = i;
+ i = j;
+ j += t;
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js
new file mode 100644
index 0000000..31fca86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-getter-setter.js
@@ -0,0 +1,19 @@
+var o = {
+ _x: 123,
+ get x() {
+ return this._x;
+ },
+ set x(value) {
+ this._x = value;
+ }
+};
+
+o = {
+ _x: 123,
+ get x get_x() {
+ return this._x;
+ },
+ set x set_x(value) {
+ this._x = value;
+ }
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js
new file mode 100644
index 0000000..0e690f8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-hook.js
@@ -0,0 +1,2 @@
+var x = 1;
+var y = x === 1? "x": "y";
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js
new file mode 100644
index 0000000..43d489e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-if.js
@@ -0,0 +1,30 @@
+var x = 0;
+
+if (x)
+ x = 0;
+
+if (x) {
+ x = 0;
+}
+
+if (x)
+ x = 0;
+else
+ x = 0;
+
+if (x) {
+ x = 0;
+}
+else {
+ x = 0;
+}
+
+if (x) {
+ x = 0;
+}
+else if (x) {
+ x = 0;
+}
+else {
+ x = 0;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js
new file mode 100644
index 0000000..75ba66e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-in.js
@@ -0,0 +1,4 @@
+var x = {};
+if ('a' in x) {
+ x = null;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js
new file mode 100644
index 0000000..065c7bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-inc.js
@@ -0,0 +1,2 @@
+x++;
+++x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js
new file mode 100644
index 0000000..2658cee
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-iso-8859-1.js
@@ -0,0 +1,2 @@
+var s = 'eèéê';
+var r = /eèéê/;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js
new file mode 100644
index 0000000..0e5062f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lambda.js
@@ -0,0 +1,3 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.8
+
+var square = function(x) x * x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js
new file mode 100644
index 0000000..7bb777b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-let.js
@@ -0,0 +1,79 @@
+// https://developer.mozilla.org/en/New_in_JavaScript_1.7
+
+// let statement
+
+let (x = x+10, y = 12) {
+ print(x+y + "\n");
+}
+
+// let expressions
+
+print( let(x = x + 10, y = 12) x+y + "<br>\n");
+
+// let definitions
+
+if (x > y) {
+ let gamma = 12.7 + y;
+ i = gamma * x;
+}
+
+var list = document.getElementById("list");
+
+for (var i = 1; i <= 5; i++) {
+ var item = document.createElement("LI");
+ item.appendChild(document.createTextNode("Item " + i));
+
+ let j = i;
+ item.onclick = function (ev) {
+ alert("Item " + j + " is clicked.");
+ };
+ list.appendChild(item);
+}
+
+function varTest() {
+ var x = 31;
+ if (true) {
+ var x = 71; // same variable!
+ alert(x); // 71
+ }
+ alert(x); // 71
+}
+
+function letTest() {
+ let x = 31;
+ if (true) {
+ let x = 71; // different variable
+ alert(x); // 71
+ }
+ alert(x); // 31
+}
+
+function letTests() {
+ let x = 10;
+
+ // let-statement
+ let (x = x + 20) {
+ alert(x); // 30
+ }
+
+ // let-expression
+ alert(let (x = x + 20) x); // 30
+
+ // let-definition
+ {
+ let x = x + 20; // x here evaluates to undefined
+ alert(x); // undefined + 20 ==> NaN
+ }
+}
+
+var x = 'global';
+let x = 42;
+document.write(this.x + "<br>\n");
+
+// let-scoped variables in for loops
+var i=0;
+for ( let i=i ; i < 10 ; i++ )
+ document.write(i + "<br>\n");
+
+for ( let [name,value] in obj )
+ document.write("Name: " + name + ", Value: " + value + "<br>\n");
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js
new file mode 100644
index 0000000..2741068
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-lf.js
@@ -0,0 +1,4 @@
+/*
+This file has LF line endings.
+*/
+var x = 1;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js
new file mode 100644
index 0000000..6801585
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-new.js
@@ -0,0 +1,4 @@
+function X() {}
+x = new X();
+x = new X(1);
+x = new X(1, 2);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js
new file mode 100644
index 0000000..95603d7
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-number.js
@@ -0,0 +1,19 @@
+x = 1;
+y = 2;
+z = 10.5;
+
+a = 1 / 0;
+a = -1 / 0;
+
+a = 0;
+a = -0;
+
+a = 0 / 0;
+a = 0 / -0;
+a = 0 / (-0);
+a = -0 / 0;
+a = (-0) / 0;
+a = -0 / -0;
+a = -0 / (-0);
+a = (-0) / -0;
+a = (-0) / (-0);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js
new file mode 100644
index 0000000..83ce7be
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-object.js
@@ -0,0 +1,2 @@
+x = /x\(\)\\\//i;
+y = /\u0001\u002f/gm;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js
new file mode 100644
index 0000000..9c6e8bb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-op.js
@@ -0,0 +1,55 @@
+var a = 1, b = 1, c = 1, d = 1;
+
+/* TOK_OR */
+x = a || b || c;
+x = a || b || c || d;
+
+/* TOK_AND */
+x = a && b && c;
+x = a && b && c && d;
+
+x = a && b || c;
+
+x = a || b && c;
+
+// TOK_BITOR
+x = a | b | c;
+x = a | b | c | d;
+
+// TOK_BITXOR
+x = a ^ b ^ c;
+x = a ^ b ^ c ^ d;
+
+// TOK_BITAND
+x = a & b & c;
+x = a & b & c & d;
+
+// TOK_EQUOP
+x = a == b;
+x = a != b;
+x = a === b;
+x = a !== b;
+
+// TOK_RELOP
+x = a < b;
+x = a <= b;
+x = a > b;
+x = a >= b;
+
+// TOK_SHOP
+x = a << b;
+x = a >> b;
+x = a >>> b;
+
+/* TOK_PLUS, TOK_MINUS */
+x = a + b;
+x = a + b + c;
+x = a + b + c + d;
+x = a - b;
+
+// TOK_STAR, TOK_DIVOP
+x = a * b;
+x = a * b * c;
+x = a * b * c * d;
+x = a / b;
+x = a % b;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js
new file mode 100644
index 0000000..9a7bc4e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-primary.js
@@ -0,0 +1,4 @@
+x = true;
+x = false;
+x = null;
+x = this;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js
new file mode 100644
index 0000000..57e897c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rb.js
@@ -0,0 +1,5 @@
+x = [];
+x = [x];
+x = [x, y];
+x = [x, y,];
+x = [x,, y];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js
new file mode 100644
index 0000000..f654a9a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rc.js
@@ -0,0 +1,7 @@
+x = {
+ x: y
+};
+x = {
+ x: y,
+ y: x
+};
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js
new file mode 100644
index 0000000..2e17573
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-rp.js
@@ -0,0 +1 @@
+x = a + (b - c);
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js
new file mode 100644
index 0000000..dc8ec36
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-special-characters.js
@@ -0,0 +1,11 @@
+function f() {
+ return '\'';
+}
+
+function g() {
+ return "\"";
+}
+
+function h() {
+ return '\\';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js
new file mode 100644
index 0000000..463824a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-string.js
@@ -0,0 +1,11 @@
+x = "";
+x = '';
+x = "x";
+x = 'x';
+x = "\"";
+x = '\'';
+x = "\b\t\n\v\f\r\"\'\\";
+x = new RegExp('x\\(\\)\\\\\\/');
+
+x = 'foo\
+bar';
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js
new file mode 100644
index 0000000..bb6e01e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-switch.js
@@ -0,0 +1,21 @@
+switch (x) {
+case x:
+ x = 0;
+ break;
+case y:
+ x = 0;
+ y = 0;
+ break;
+default:
+ x = 0;
+ break;
+}
+
+switch (x) {
+case 1:
+ let y = 1;
+ f(y);
+ break;
+case 2:
+ break;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js
new file mode 100644
index 0000000..1fc73c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-throw.js
@@ -0,0 +1,6 @@
+try {
+ throw "x";
+}
+catch (e) {
+ ;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js
new file mode 100644
index 0000000..47a5de4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-try.js
@@ -0,0 +1,32 @@
+function f() {}
+
+try {
+ f();
+}
+catch (e) {
+ f();
+}
+
+try {
+ f();
+}
+catch (e if e instanceof E) {
+ f();
+}
+
+try {
+ f();
+}
+finally {
+ f();
+}
+
+try {
+ f();
+}
+catch (e) {
+ f();
+}
+finally {
+ f();
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js
new file mode 100644
index 0000000..0173913
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-unaryop.js
@@ -0,0 +1,6 @@
+x = -x;
+x = +x;
+x = !x;
+x = ~x;
+x = typeof x;
+x = void x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js
new file mode 100644
index 0000000..4902a44
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-var.js
@@ -0,0 +1,2 @@
+var x;
+var y = x, z = x;
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js
new file mode 100644
index 0000000..f1ec6b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-while.js
@@ -0,0 +1,35 @@
+while (x) {
+ x();
+}
+
+while (x) {
+ ;
+}
+
+while (x)
+ x();
+
+while (x)
+ ;
+
+while (x) {
+ if (x) {
+ continue;
+ }
+}
+
+label:
+while (x) {
+ if (x) {
+ continue label;
+ }
+}
+
+label2: {
+ f();
+ while (x) {
+ if (x) {
+ break label2;
+ }
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js
new file mode 100644
index 0000000..58fd1ac
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/javascript/javascript-with.js
@@ -0,0 +1,9 @@
+function f() {}
+var x = {};
+
+with (x) {
+ f();
+}
+
+with (x)
+ f();
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js b/tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js
new file mode 100644
index 0000000..37e9144
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/json-cmp.js
@@ -0,0 +1,65 @@
+/*
+ json-cmp.js - compare JSON files
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+function json_equals(json1, json2) {
+ if (json1 === null || json2 === null) {
+ return json1 === json2;
+ }
+ else if (json1.constructor === Array && json2.constructor === Array) {
+ if (json1.length !== json2.length) {
+ return false;
+ }
+ var length = json1.length;
+ for (var i = 0; i < length; i++) {
+ if (! json_equals(json1[i], json2[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ else if (typeof(json1) === 'object' && typeof(json2) === 'object') {
+ var i;
+ for (i in json1) {
+ if (! (i in json2)) {
+ return false;
+ }
+ if (! json_equals(json1[i], json2[i])) {
+ return false;
+ }
+ }
+ for (i in json2) {
+ if (! (i in json1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ else {
+ return json1 === json2;
+ }
+}
+
+if (json_equals(EXPECTED, ACTUAL)) {
+ quit(0);
+}
+else {
+ print(EXPECTED.toSource());
+ print(ACTUAL.toSource());
+ quit(1);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/json.c b/tools/node_modules/expresso/deps/jscoverage/tests/json.c
new file mode 100644
index 0000000..3522d86
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/json.c
@@ -0,0 +1,48 @@
+/*
+ json.c - test JSON manipulation
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "instrument-js.h"
+#include "stream.h"
+#include "util.h"
+
+bool jscoverage_highlight = true;
+
+int main(void) {
+ jscoverage_init();
+
+ Stream * stream = Stream_new(0);
+
+ FILE * f = xfopen("store.json", "r");
+ Stream_write_file_contents(stream, f);
+ fclose(f);
+
+ Coverage * coverage = Coverage_new();
+ int result = jscoverage_parse_json(coverage, stream->data, stream->length);
+ assert(result == 0);
+
+ Coverage_delete(coverage);
+ Stream_delete(stream);
+ jscoverage_cleanup();
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/json.sh
new file mode 100755
index 0000000..2f84d4d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/json.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# json.sh - test JSON parsing
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./json
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c
new file mode 100644
index 0000000..027cff6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.c
@@ -0,0 +1,42 @@
+/*
+ mkdirs.c - test `mkdirs' function
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+void cleanup(void) {
+ system("rm -fr DIR");
+}
+
+int main(void) {
+ atexit(cleanup);
+
+ system("rm -fr DIR");
+
+ mkdirs("DIR/a/b");
+
+ struct stat buf;
+ xstat("DIR/a/b", &buf);
+ assert(S_ISDIR(buf.st_mode));
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh
new file mode 100755
index 0000000..f1dc922
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/mkdirs.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# mkdirs.sh - test `mkdirs' function
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./mkdirs
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl b/tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl
new file mode 100644
index 0000000..5df75be
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/netcat.pl
@@ -0,0 +1,35 @@
+use strict;
+use warnings;
+
+use Socket;
+
+binmode(STDIN);
+$| = 1;
+binmode(STDOUT);
+
+if (@ARGV != 2) {
+ die "Usage: netcat.pl HOST PORT\n";
+}
+
+my $host = shift;
+my $port = shift;
+
+my $address = inet_aton($host) or die;
+my $address_and_port = sockaddr_in($port, $address);
+my $protocol = getprotobyname('tcp');
+socket(SOCKET, PF_INET, SOCK_STREAM, $protocol) or die;
+
+my $old = select(SOCKET);
+$| = 1;
+select($old);
+binmode(SOCKET);
+
+connect(SOCKET, $address_and_port) or die;
+while (<STDIN>) {
+ print SOCKET $_;
+}
+while (<SOCKET>) {
+ print;
+}
+close(SOCKET);
+exit 0; \ No newline at end of file
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err
new file mode 100644
index 0000000..c6e2707
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.expected.err
@@ -0,0 +1,2 @@
+jscoverage: missing argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh
new file mode 100755
index 0000000..73eb586
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/no-arguments.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# no-arguments.sh - test jscoverage with no arguments
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+$VALGRIND jscoverage > OUT 2> ERR && exit 1
+test ! -s OUT
+diff --strip-trailing-cr no-arguments.expected.err ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err
new file mode 100644
index 0000000..fdceb30
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/no-instrument-requires-argument.expected.err
@@ -0,0 +1,2 @@
+jscoverage: --no-instrument: option requires an argument
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh
new file mode 100755
index 0000000..0532f38
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-request-body.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# proxy-bad-request-body.sh - test jscoverage-server --proxy with a bad request body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+shutdown_perl() {
+ wget -q -O- --post-data= http://127.0.0.1:8000/perl-shutdown > /dev/null
+ wait $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+ shutdown_perl
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+./http-client-bad-body 8080 http://127.0.0.1:8000/
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh
new file mode 100755
index 0000000..df63686
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body-javascript.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# proxy-bad-response-body-javascript.sh - test jscoverage-server --proxy with bad JavaScript response body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ kill -9 $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+./http-server-bad-body &
+origin_server_pid=$!
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/script.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err
new file mode 100644
index 0000000..9dd02ee
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.expected.err
@@ -0,0 +1 @@
+Warning: error copying response body from server to client
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh
new file mode 100755
index 0000000..aace044
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-body.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# proxy-bad-response-body.sh - test jscoverage-server --proxy with bad response body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ kill -9 $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+./http-server-bad-body &
+origin_server_pid=$!
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 200 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/index.html 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+diff --strip-trailing-cr proxy-bad-response-body.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh
new file mode 100755
index 0000000..e21e22a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-bad-response-headers.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+# proxy-bad-response-headers.sh - test jscoverage-server --proxy with bad response headers
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ kill -9 $origin_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+./http-server-bad-headers &
+origin_server_pid=$!
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 502 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh
new file mode 100755
index 0000000..75f34f6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-no-server.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+# proxy-no-server.sh - test jscoverage-server --proxy without origin server
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 504 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:1/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh
new file mode 100755
index 0000000..413f116
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy-url.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+# proxy-url.sh - test jscoverage-server --proxy with different URLs
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --proxy > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+echo 504 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+./http-client-bad-url 8080 http://127.0.0.1:123456/index.html
+./http-client-bad-url 8080 http://127.0.0.1:xyz/index.html
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+sleep $delay
+
+./http-client-bad-url 8080 http://127.0.0.1:8000
+./http-client-bad-url 8080 'http://127.0.0.1:8000?foo'
+./http-client-bad-url 8080 'foo'
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/proxy.sh b/tools/node_modules/expresso/deps/jscoverage/tests/proxy.sh
new file mode 100755
index 0000000..903ab62
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/proxy.sh
@@ -0,0 +1,143 @@
+#!/bin/sh
+# proxy.sh - test jscoverage-server --proxy
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${proxy_server_port}/jscoverage-shutdown" > /dev/null
+ wait $proxy_server_pid
+}
+
+shutdown_perl() {
+ wget -q -O- --post-data= http://127.0.0.1:8000/perl-shutdown > /dev/null
+ wait $origin_server_pid
+}
+
+cleanup() {
+ rm -fr EXPECTED ACTUAL DIR OUT
+ shutdown
+ shutdown_perl
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+rm -fr DIR
+mkdir DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+proxy_server_pid=$!
+proxy_server_port=8080
+
+sleep $delay
+
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/index.html | diff recursive/index.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/style.css | diff recursive/style.css -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/unix.txt | diff recursive/unix.txt -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/windows.txt | diff recursive/windows.txt -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/image.png | diff recursive/image.png -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/x | diff recursive/x -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/1.html | diff recursive/1/1.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/1.css | diff recursive/1/1.css -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/2/2.html | diff recursive/1/2/2.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/2/2.css | diff recursive/1/2/2.css -
+
+# test localhost
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://localhost:8000/index.html | diff recursive/index.html -
+
+# test actual hostname
+h=`hostname`
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://${h}:8000/index.html | diff recursive/index.html -
+
+# test query string
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/index.html?foo | diff recursive/index.html -
+
+# test POST
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' --post-file=recursive/index.html http://127.0.0.1:8000/ | diff recursive/index.html -
+
+# test javascript
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/1.js > OUT
+cat ../report.js recursive.expected/1/1.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/1/2/2.js > OUT
+cat ../report.js recursive.expected/1/2/2.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+
+## test jscoverage
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage.html | diff ../jscoverage.html -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage.css | diff ../jscoverage.css -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage-throbber.gif | diff ../jscoverage-throbber.gif -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://siliconforks.com/jscoverage.js > OUT
+echo -e 'jscoverage_isServer = true;\r' | cat ../jscoverage.js - | diff - OUT
+
+# load/store
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8080/' --post-data='{}' http://siliconforks.com/jscoverage-store > /dev/null
+echo -n '{}' | diff - DIR/jscoverage.json
+diff ../jscoverage.html DIR/jscoverage.html
+diff ../jscoverage.css DIR/jscoverage.css
+diff ../jscoverage-throbber.gif DIR/jscoverage-throbber.gif
+echo -e 'jscoverage_isReport = true;\r' | cat ../jscoverage.js - | diff - DIR/jscoverage.js
+
+# send it an FTP request
+echo 400 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 ftp://ftp.example.com 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# nonexistent domain
+echo 504 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://nonexistent 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# 404 not found
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://127.0.0.1:8000/missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://siliconforks.com/jscoverage-missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+## send it a server request
+#echo 400 > EXPECTED
+#! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/ 2> /dev/null > ACTUAL
+#diff EXPECTED ACTUAL
+
+# kill $proxy_server_pid
+shutdown
+
+$VALGRIND jscoverage-server --no-highlight --port=8081 --proxy --report-dir=DIR --no-instrument=http://127.0.0.1:8000/1/ &
+proxy_server_pid=$!
+proxy_server_port=8081
+
+sleep $delay
+
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8081/' http://127.0.0.1:8000/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/http:\/\/127.0.0.1:8000\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8081/' http://127.0.0.1:8000/1/1.js | diff --strip-trailing-cr recursive/1/1.js -
+wget -q -O- -e 'http_proxy=http://127.0.0.1:8081/' http://127.0.0.1:8000/1/2/2.js | diff --strip-trailing-cr recursive/1/2/2.js -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh
new file mode 100755
index 0000000..c95ee81
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-crlf.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# recursive-crlf.sh - test recursive directory instrumentation, CRLF line endings
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr TMP EXPECTED DIR OUT' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr TMP EXPECTED DIR OUT
+
+mkdir -p TMP/1/2
+cd recursive
+cp *.html *.js *.css *.png *.txt x ../TMP
+cp 1/1.html 1/1.js 1/1.css ../TMP/1
+cp 1/2/2.html 1/2/2.js 1/2/2.css ../TMP/1/2
+cd ..
+unix2dos TMP/script.js > /dev/null 2> /dev/null
+unix2dos TMP/1/1.js > /dev/null 2> /dev/null
+unix2dos TMP/1/2/2.js > /dev/null 2> /dev/null
+
+mkdir -p EXPECTED/1/2
+cd recursive.expected
+cp *.html *.js *.css *.png *.txt x ../EXPECTED
+cp 1/1.html 1/1.js 1/1.css ../EXPECTED/1
+cp 1/2/2.html 1/2/2.js 1/2/2.css ../EXPECTED/1/2
+cd ..
+cat recursive.expected/script.js | sed 's/@PREFIX@//g' > EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+cat recursive.expected/1/2/2.js | sed 's/@PREFIX@//g' > EXPECTED/1/2/2.js
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight TMP DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+$VALGRIND jscoverage --no-highlight --verbose TMP DIR > OUT
+test -d DIR
+sort OUT -o OUT
+diff --strip-trailing-cr verbose.expected.out OUT
+diff --strip-trailing-cr -r EXPECTED DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c
new file mode 100644
index 0000000..2f1a7bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.c
@@ -0,0 +1,93 @@
+/*
+ recursive-dir-list.c - test `make_recursive_dir_list' function
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+struct Expected {
+ int count;
+ const char * name;
+};
+
+void cleanup(void) {
+ system("rm -fr DIR");
+}
+
+void touch(const char * file) {
+ FILE * f = fopen(file, "w");
+ if (f == NULL) {
+ fatal("cannot open file: %s", file);
+ }
+ fclose(f);
+}
+
+void verify(struct Expected * expected, struct DirListEntry * actual, int length) {
+ struct DirListEntry * p = actual;
+ while (p != NULL) {
+ char * name = p->name;
+ for (int i = 0; i < length; i++) {
+ if (strcmp(expected[i].name, name) == 0) {
+ expected[i].count++;
+ break;
+ }
+ }
+ p = p->next;
+ }
+
+ /* now verify the totals */
+ for (int i = 0; i < length; i++) {
+ assert(expected[i].count == 1);
+ }
+}
+
+int main(void) {
+ atexit(cleanup);
+
+ system("rm -fr DIR");
+
+ /* simple case */
+ xmkdir("DIR");
+ xmkdir("DIR/a");
+ xmkdir("DIR/a/b");
+ xmkdir("DIR/c");
+ xmkdir("DIR/d");
+ touch("DIR/0");
+ touch("DIR/a/1");
+ touch("DIR/a/b/2");
+ touch("DIR/c/3");
+ touch("DIR/c/4");
+ /* DIR/d is empty */
+
+ struct Expected expected[] = {
+ {0, "c/4"},
+ {0, "c/3"},
+ {0, "a/b/2"},
+ {0, "a/1"},
+ {0, "0"},
+ };
+
+ struct DirListEntry * list = make_recursive_dir_list("DIR");
+ verify(expected, list, sizeof(expected) / sizeof(expected[0]));
+ free_dir_list(list);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh
new file mode 100755
index 0000000..d232a0a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-dir-list.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# recursive-dir-list.sh - test `make_recursive_dir_list' function
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./recursive-dir-list
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh
new file mode 100755
index 0000000..4e5d42e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-exclude.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# recursive-exclude.sh - test `--exclude' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr EXPECTED DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+rm -fr EXPECTED
+cp -r recursive.expected EXPECTED
+find EXPECTED -name .svn | xargs rm -fr
+rm EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+rm -fr EXPECTED/1/2
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn --exclude 1/2 --exclude=script.js recursive DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+rm -fr EXPECTED DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh
new file mode 100755
index 0000000..7fdd151
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-fatal.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# recursive-fatal.sh - test various fatal errors
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr DIR DIR2 SYM ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR DIR2 SYM ERR
+
+mkdir DIR
+$VALGRIND jscoverage DIR DIR 2>ERR && exit 1
+
+$VALGRIND jscoverage DIR DIR/1 2>ERR && exit 1
+
+mkdir DIR/1
+$VALGRIND jscoverage DIR/1 DIR 2>ERR && exit 1
+
+cp -r DIR SYM
+$VALGRIND jscoverage DIR SYM 2>ERR && exit 1
+
+$VALGRIND jscoverage SYM DIR 2>ERR && exit 1
+
+rm -fr DIR DIR2 SYM ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh
new file mode 100755
index 0000000..1203bec
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive-no-instrument.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# recursive-no-instrument.sh - test `--no-instrument' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr EXPECTED DIR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+rm -fr EXPECTED
+cp -r recursive.expected EXPECTED
+find EXPECTED -name .svn | xargs rm -fr
+cat recursive/script.js | sed 's/@PREFIX@//g' > EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+cat recursive/1/2/2.js | sed 's/@PREFIX@//g' > EXPECTED/1/2/2.js
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn --no-instrument 1/2 --no-instrument=script.js recursive DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+rm -fr EXPECTED DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css
new file mode 100644
index 0000000..563d20e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.css
@@ -0,0 +1,3 @@
+body {
+ color: green;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html
new file mode 100644
index 0000000..e292b54
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>1</title>
+<script type="text/javascript" src="1.js"></script>
+<link rel="stylesheet" type="text/css" href="1.css">
+</head>
+<body>
+1<br>
+<a href="2/2.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js
new file mode 100644
index 0000000..e237b0f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/1.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['@PREFIX@1/1.js']) {
+ _$jscoverage['@PREFIX@1/1.js'] = [];
+ _$jscoverage['@PREFIX@1/1.js'][1] = 0;
+}
+_$jscoverage['@PREFIX@1/1.js'][1]++;
+alert("This is 1");
+_$jscoverage['@PREFIX@1/1.js'].source = ["alert(\"This is 1\");"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css
new file mode 100644
index 0000000..7cfe2bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.css
@@ -0,0 +1,3 @@
+body {
+ color: blue;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html
new file mode 100644
index 0000000..bb83ca6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>2</title>
+<script type="text/javascript" src="2.js"></script>
+<link rel="stylesheet" type="text/css" href="2.css">
+</head>
+<body>
+2
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js
new file mode 100644
index 0000000..09184a3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/1/2/2.js
@@ -0,0 +1,12 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['@PREFIX@1/2/2.js']) {
+ _$jscoverage['@PREFIX@1/2/2.js'] = [];
+ _$jscoverage['@PREFIX@1/2/2.js'][1] = 0;
+}
+_$jscoverage['@PREFIX@1/2/2.js'][1]++;
+alert("This is 2");
+_$jscoverage['@PREFIX@1/2/2.js'].source = ["alert(\"This is 2\");"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.png b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.png
new file mode 100644
index 0000000..da5ef5d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/image.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html
new file mode 100644
index 0000000..90b7789
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Test</title>
+<script type="text/javascript" src="script.js"></script>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+Test<br>
+<a href="1/1.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js
new file mode 100644
index 0000000..d9bf48b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/script.js
@@ -0,0 +1,19 @@
+/* automatically generated by JSCoverage - do not edit */
+if (! top._$jscoverage) {
+ top._$jscoverage = {};
+}
+var _$jscoverage = top._$jscoverage;
+if (! _$jscoverage['@PREFIX@script.js']) {
+ _$jscoverage['@PREFIX@script.js'] = [];
+ _$jscoverage['@PREFIX@script.js'][1] = 0;
+ _$jscoverage['@PREFIX@script.js'][4] = 0;
+ _$jscoverage['@PREFIX@script.js'][5] = 0;
+}
+_$jscoverage['@PREFIX@script.js'][1]++;
+alert("hello");
+_$jscoverage['@PREFIX@script.js'][4]++;
+if ("a" < "b" && "a" > "b") {
+ _$jscoverage['@PREFIX@script.js'][5]++;
+ alert("?");
+}
+_$jscoverage['@PREFIX@script.js'].source = ["alert(\"hello\");","","// test formatting &amp;lt; &amp;gt; &amp;amp;","if ('a' &lt; 'b' &amp;&amp; 'a' &gt; 'b') {"," alert(\"?\");","}"];
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css
new file mode 100644
index 0000000..60f1eab
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/style.css
@@ -0,0 +1,3 @@
+body {
+ color: red;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt
new file mode 100644
index 0000000..01e79c3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/unix.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt
new file mode 100644
index 0000000..294d779
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/windows.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x
new file mode 100644
index 0000000..587be6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.expected/x
@@ -0,0 +1 @@
+x
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive.sh b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.sh
new file mode 100755
index 0000000..f7c0d09
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+# recursive.sh - test recursive directory instrumentation
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr EXPECTED DIR OUT' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+rm -fr DIR
+rm -fr EXPECTED
+cp -r recursive.expected EXPECTED
+find EXPECTED -name .svn | xargs rm -fr
+cat recursive.expected/script.js | sed 's/@PREFIX@//g' > EXPECTED/script.js
+cat recursive.expected/1/1.js | sed 's/@PREFIX@//g' > EXPECTED/1/1.js
+cat recursive.expected/1/2/2.js | sed 's/@PREFIX@//g' > EXPECTED/1/2/2.js
+cp ../jscoverage.css ../jscoverage-highlight.css ../jscoverage-ie.css \
+ ../jscoverage-throbber.gif \
+ ../jscoverage.html \
+ ../jscoverage.js EXPECTED
+
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive DIR
+test -d DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+
+$VALGRIND jscoverage --no-highlight --verbose --exclude .svn --exclude 1/.svn --exclude 1/2/.svn recursive DIR >OUT
+test -d DIR
+sort OUT -o OUT
+diff --strip-trailing-cr verbose.expected.out OUT
+diff --strip-trailing-cr -r EXPECTED DIR
+
+# does it handle an argument with a slash at the end?
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive/ DIR
+diff --strip-trailing-cr -r EXPECTED DIR
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive DIR/
+diff --strip-trailing-cr -r EXPECTED DIR
+$VALGRIND jscoverage --no-highlight --exclude=.svn --exclude=1/.svn --exclude=1/2/.svn recursive/ DIR/
+diff --strip-trailing-cr -r EXPECTED DIR
+
+rm -fr EXPECTED DIR OUT
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css
new file mode 100644
index 0000000..563d20e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.css
@@ -0,0 +1,3 @@
+body {
+ color: green;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html
new file mode 100644
index 0000000..e292b54
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>1</title>
+<script type="text/javascript" src="1.js"></script>
+<link rel="stylesheet" type="text/css" href="1.css">
+</head>
+<body>
+1<br>
+<a href="2/2.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js
new file mode 100644
index 0000000..5f73e02
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/1.js
@@ -0,0 +1 @@
+alert("This is 1");
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css
new file mode 100644
index 0000000..7cfe2bf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.css
@@ -0,0 +1,3 @@
+body {
+ color: blue;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html
new file mode 100644
index 0000000..bb83ca6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>2</title>
+<script type="text/javascript" src="2.js"></script>
+<link rel="stylesheet" type="text/css" href="2.css">
+</head>
+<body>
+2
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js
new file mode 100644
index 0000000..e0f7496
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/1/2/2.js
@@ -0,0 +1 @@
+alert("This is 2");
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.png b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.png
new file mode 100644
index 0000000..da5ef5d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/image.png
Binary files differ
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html
new file mode 100644
index 0000000..90b7789
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/index.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<title>Test</title>
+<script type="text/javascript" src="script.js"></script>
+<link rel="stylesheet" type="text/css" href="style.css">
+</head>
+<body>
+Test<br>
+<a href="1/1.html">Next</a>
+</body>
+</html>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js
new file mode 100644
index 0000000..1671f23
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/script.js
@@ -0,0 +1,6 @@
+alert("hello");
+
+// test formatting &lt; &gt; &amp;
+if ('a' < 'b' && 'a' > 'b') {
+ alert("?");
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css
new file mode 100644
index 0000000..60f1eab
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/style.css
@@ -0,0 +1,3 @@
+body {
+ color: red;
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt
new file mode 100644
index 0000000..01e79c3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/unix.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt
new file mode 100644
index 0000000..294d779
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/windows.txt
@@ -0,0 +1,3 @@
+1
+2
+3
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/recursive/x b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/x
new file mode 100644
index 0000000..587be6b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/recursive/x
@@ -0,0 +1 @@
+x
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err
new file mode 100644
index 0000000..4f9362a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.expected.err
@@ -0,0 +1 @@
+jscoverage: source and destination are the same
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh
new file mode 100755
index 0000000..e07867b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/same-directory.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# same-directory.sh - test with source and destination same directory
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage javascript javascript > OUT 2> ERR && exit 1
+test ! -s OUT
+test -s ERR
+diff --strip-trailing-cr same-directory.expected.err ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh
new file mode 100755
index 0000000..e85a18d
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-bad-requests.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+# server-bad-requests.sh - test jscoverage-server with bad requests
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ rm -fr EXPECTED ACTUAL OUT ERR
+}
+
+bad_request() {
+ /bin/echo -ne "$1" | $NETCAT 127.0.0.1 $server_port > OUT 2> ERR
+ echo 'HTTP/1.1 400 Bad Request' > EXPECTED
+ head -n 1 OUT > ACTUAL
+ diff --strip-trailing-cr EXPECTED ACTUAL
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+if which netcat > /dev/null 2> /dev/null
+then
+ NETCAT=netcat
+elif which nc > /dev/null 2> /dev/null
+then
+ NETCAT=nc
+else
+ NETCAT='perl netcat.pl';
+fi
+
+rm -fr EXPECTED ACTUAL OUT ERR
+$VALGRIND jscoverage-server --port 8000 > /dev/null 2> /dev/null &
+server_pid=$!
+server_port=8000
+
+sleep $delay
+
+# send NUL in Request-Line
+bad_request 'GET \0000 HTTP/1.1\r\n\r\n'
+
+# send empty Request-Line
+bad_request '\r\n\r\n'
+
+# send bad Request-Line
+bad_request ' \r\n\r\n'
+bad_request 'GET\r\n\r\n'
+bad_request 'GET \r\n\r\n'
+bad_request 'GET \r\n\r\n'
+bad_request 'GET /\r\n\r\n'
+bad_request 'GET / \r\n\r\n'
+
+# bad Host header
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nHost: foo:bar\r\n\r\n'
+
+# NUL in header
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nFoo: \0000\r\n\r\n'
+
+# missing header
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\n: bar\r\n\r\n'
+
+# missing header value
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nFoo:\r\n\r\n'
+
+# bad Transfer-Encoding
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo;\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\\\0200"\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = "\0177"\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: foo; bar = ;\r\n\r\n'
+
+# bad Content-Length
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 4294967296\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 4294967300\r\n\r\n'
+bad_request 'GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: foo\r\n\r\n'
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh
new file mode 100755
index 0000000..4a27b33
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-close-after-request.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+# server-close-after-request.sh - test jscoverage-server with client that closes connection after request
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --port 8000 > OUT 2> ERR &
+server_pid=$!
+server_port=8000
+
+sleep $delay
+
+./http-client-close-after-request
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh
new file mode 100755
index 0000000..69e6b6a
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-content-types.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# server-content-types.sh - test jscoverage-server Content-Type headers
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ rm -f x x.y
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo text/html > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/recursive/index.html 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo text/plain > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/recursive/unix.txt 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+echo text/plain > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/recursive/windows.txt 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+touch x
+echo application/octet-stream > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/x 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+touch x.y
+echo application/octet-stream > EXPECTED
+! curl -f -w '%{content_type}\n' -o /dev/null http://127.0.0.1:8080/x.y 2> /dev/null > ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected
new file mode 100644
index 0000000..2a9fdd3
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.expected
@@ -0,0 +1,4 @@
+<a href=".">.</a><br>
+<a href="..">..</a><br>
+<a href="1&amp;2.txt">1&amp;2.txt</a><br>
+<a href="1%202.txt">1 2.txt</a><br>
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh
new file mode 100755
index 0000000..fca3c2f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-listing.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# server-directory-listing.sh - test jscoverage-server directory listings
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+$VALGRIND jscoverage-server --document-root=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# make some funny files
+echo x > 'DIR/1&2.txt'
+echo x > 'DIR/1 2.txt'
+
+sort server-directory-listing.expected -o EXPECTED
+wget -q -O- http://127.0.0.1:8080/ > ACTUAL
+sort ACTUAL -o ACTUAL
+diff --strip-trailing-cr EXPECTED ACTUAL
+
+rm -fr DIR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh
new file mode 100755
index 0000000..179cefd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-directory-redirect.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# server-directory-redirect.sh - test jscoverage-server directory redirect
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --document-root=recursive > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 'HTTP/1.1 301 Moved Permanently' > EXPECTED
+# curl -f doesn't seem to work with 3xx
+! curl -D ACTUAL http://127.0.0.1:8080/1 2> /dev/null > /dev/null
+cat ACTUAL | tr -d '\r' | head -1 | diff EXPECTED -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh
new file mode 100755
index 0000000..e205c18
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-encoded-url.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# server-encoded-url.sh - test jscoverage-server with encoded URL
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+}
+
+cleanup() {
+ shutdown
+ # rm -fr DIR
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+$VALGRIND jscoverage-server --document-root=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# make some funny files
+echo x > 'DIR/1+2.txt'
+echo x > 'DIR/1&2.txt'
+echo x > 'DIR/1 2.txt'
+
+wget -q -O- 'http://127.0.0.1:8080/1%2B2.txt' | diff 'DIR/1+2.txt' -
+wget -q -O- 'http://127.0.0.1:8080/1%2b2.txt' | diff 'DIR/1+2.txt' -
+wget -q -O- 'http://127.0.0.1:8080/1%262.txt' | diff 'DIR/1&2.txt' -
+wget -q -O- 'http://127.0.0.1:8080/1%202.txt' | diff 'DIR/1 2.txt' -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-error.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-error.sh
new file mode 100755
index 0000000..c2a47c4
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-error.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+# server-error.sh - test jscoverage-server with invalid options
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+! jscoverage-server --report-dir > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --document-root > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --ip-address > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --no-instrument > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --port > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --foo > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server foo > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --port x > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --port 123456 > OUT 2> ERR
+test ! -s OUT
+test -s ERR
+
+! jscoverage-server --encoding > OUT 2> ERR
+test ! -s OUT
+test -s ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-help.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-help.sh
new file mode 100755
index 0000000..b644549
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-help.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+# server-help.sh - test jscoverage-server --help
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+jscoverage-server --help > OUT 2> ERR
+diff --strip-trailing-cr ../jscoverage-server-help.txt OUT
+> TMP
+diff TMP ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out
new file mode 100644
index 0000000..b1838fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.expected.out
@@ -0,0 +1,4 @@
+Starting HTTP server on @ADDRESS@:8080
+GET / HTTP/1.0
+POST /jscoverage-shutdown HTTP/1.0
+Stopping HTTP server
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh
new file mode 100755
index 0000000..b4a5770
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-ip-address.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+# server-ip-address.sh - test jscoverage-server --ip-address
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ # shutdown
+ :
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --verbose --ip-address=0.0.0.0 > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:${server_port}/ > /dev/null
+
+shutdown
+
+cat server-ip-address.expected.out | sed 's/@ADDRESS@/0.0.0.0/g' > EXPECTED
+cat OUT | tr -d '\r' > ACTUAL
+diff EXPECTED ACTUAL
+
+$VALGRIND jscoverage-server --verbose --ip-address 127.0.0.1 > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:${server_port}/ > /dev/null
+
+shutdown
+
+cat server-ip-address.expected.out | sed 's/@ADDRESS@/127.0.0.1/g' > EXPECTED
+cat OUT | tr -d '\r' > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh
new file mode 100755
index 0000000..d6fa877
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown-bad-method.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+# server-shutdown-bad-method.sh - test jscoverage-server --shutdown with GET
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 405 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-shutdown 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err
new file mode 100644
index 0000000..5dd4646
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.expected.err
@@ -0,0 +1 @@
+POST /jscoverage-shutdown
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh
new file mode 100755
index 0000000..c91e6bd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-shutdown.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# server-shutdown.sh - test jscoverage-server --shutdown
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+cleanup() {
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+perl server.pl > OUT 2> ERR &
+origin_server_pid=$!
+
+sleep $delay
+
+$VALGRIND jscoverage-server --port 8000 --shutdown
+cat ERR | cut -d'"' -f2 | diff --strip-trailing-cr server-shutdown.expected.err -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh
new file mode 100755
index 0000000..76196fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-special-file.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# server-special-file.sh - test jscoverage-server with special file
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+# skip on mingw
+uname=`uname`
+case "$uname" in
+ MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rm -f DIR/foo
+ rm -fr DIR
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+mkfifo DIR/foo
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/DIR/foo 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh
new file mode 100755
index 0000000..4de4ba8
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-directory.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+# server-unreadable-directory.sh - test jscoverage-server with unreadable directory
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+# skip on windows
+uname=`uname`
+case "$uname" in
+ CYGWIN* | MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rmdir DIR
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+chmod 000 DIR
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/DIR/ 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh
new file mode 100755
index 0000000..20e1369
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-unreadable-file.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# server-unreadable-file.sh - test jscoverage-server with unreadable file
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+# skip on windows
+uname=`uname`
+case "$uname" in
+ CYGWIN* | MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rm -fr DIR
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+mkdir DIR
+echo Hello > DIR/index.html
+chmod 000 DIR/index.html
+$VALGRIND jscoverage-server > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/DIR/index.html 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err
new file mode 100644
index 0000000..e578f28
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.expected.err
@@ -0,0 +1,4 @@
+Starting HTTP server on 127.0.0.1:8080
+GET /index.html HTTP/1.0
+POST /jscoverage-shutdown HTTP/1.0
+Stopping HTTP server
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh
new file mode 100755
index 0000000..174692e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-verbose.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# server-verbose.sh - test jscoverage-server --verbose
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ # shutdown
+ :
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+$VALGRIND jscoverage-server --document-root=recursive --verbose > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8080/index.html | diff --strip-trailing-cr recursive/index.html -
+
+shutdown
+
+sleep $delay
+
+cat OUT | tr -d '\r' | diff server-verbose.expected.err -
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server-version.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server-version.sh
new file mode 100755
index 0000000..c2a629f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server-version.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# server-version.sh - test jscoverage-server --version
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+export PATH=.:..:$PATH
+
+jscoverage-server --version > OUT 2> ERR
+test -s OUT
+test ! -s ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server.pl b/tools/node_modules/expresso/deps/jscoverage/tests/server.pl
new file mode 100644
index 0000000..86064b1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server.pl
@@ -0,0 +1,61 @@
+use strict;
+use warnings;
+
+use HTTP::Daemon;
+use HTTP::Status;
+
+$|++;
+
+my $d = HTTP::Daemon->new(LocalPort => 8000, ReuseAddr => 1) || die;
+print "Please contact me at: <URL:", $d->url, ">\n";
+my $done = 0;
+while (not $done and my $c = $d->accept) {
+ my $r = $c->get_request;
+ if (not defined($r)) {
+ print "Error: ", $c->reason, "\n";
+ $c->close;
+ undef($c);
+ next;
+ }
+ print STDERR $r->method, ' ', $r->url, "\n";
+ $c->force_last_request;
+ if ($r->method eq 'GET') {
+ my $file = substr($r->url->path, 1);
+ if (open FILE, $file) {
+ undef $/;
+ binmode FILE;
+ my $content = <FILE>;
+ close FILE;
+ my @headers = ('Connection' => 'close');
+ if ($file =~ /\.js$/) {
+ push @headers, 'Content-Type' => 'text/javascript';
+ }
+ elsif ($file =~ /\.[^\/]+$/) {
+ push @headers, 'Content-Type' => 'application/octet-stream';
+ }
+ else {
+ # do nothing - no Content-Type
+ }
+ my $response = HTTP::Response->new(200, 'OK', \@headers, $content);
+ $c->send_response($response);
+ }
+ else {
+ my $response = HTTP::Response->new(404, 'Not found', ['Connection' => 'close'], 'Not found');
+ $c->send_response($response);
+ }
+ }
+ elsif ($r->method eq 'POST') {
+ if ($r->url->path eq '/perl-shutdown') {
+ $done = 1;
+ }
+ my $content = $r->content;
+ my $response = HTTP::Response->new(200, 'OK', ['Connection' => 'close'], $content);
+ $c->send_response($response);
+ }
+ else {
+ $c->send_error(RC_FORBIDDEN);
+ }
+ $c->close;
+ undef($c);
+}
+
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/server.sh b/tools/node_modules/expresso/deps/jscoverage/tests/server.sh
new file mode 100755
index 0000000..e936fa1
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/server.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+# server.sh - test jscoverage-server
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ rm -fr EXPECTED ACTUAL DIR OUT
+ # kill $server_pid
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+if jscoverage-server --version | grep -q 'iconv\|MultiByteToWideChar'
+then
+ character_encoding_support=yes
+else
+ character_encoding_support=no
+fi
+
+rm -fr EXPECTED ACTUAL DIR OUT
+mkdir DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8080/index.html | diff recursive/index.html -
+wget -q -O- http://127.0.0.1:8080/style.css | diff recursive/style.css -
+wget -q -O- http://127.0.0.1:8080/unix.txt | diff recursive/unix.txt -
+wget -q -O- http://127.0.0.1:8080/windows.txt | diff recursive/windows.txt -
+wget -q -O- http://127.0.0.1:8080/image.png | diff recursive/image.png -
+wget -q -O- http://127.0.0.1:8080/x | diff recursive/x -
+wget -q -O- http://127.0.0.1:8080/1/1.html | diff recursive/1/1.html -
+wget -q -O- http://127.0.0.1:8080/1/1.css | diff recursive/1/1.css -
+wget -q -O- http://127.0.0.1:8080/1/2/2.html | diff recursive/1/2/2.html -
+wget -q -O- http://127.0.0.1:8080/1/2/2.css | diff recursive/1/2/2.css -
+
+# test query string
+wget -q -O- http://127.0.0.1:8080/index.html?foo | diff recursive/index.html -
+
+# test javascript
+wget -q -O- http://127.0.0.1:8080/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8080/1/1.js > OUT
+cat ../report.js recursive.expected/1/1.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8080/1/2/2.js > OUT
+cat ../report.js recursive.expected/1/2/2.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+
+# test jscoverage
+wget -q -O- http://127.0.0.1:8080/jscoverage.html | diff ../jscoverage.html -
+wget -q -O- http://127.0.0.1:8080/jscoverage.css | diff ../jscoverage.css -
+wget -q -O- http://127.0.0.1:8080/jscoverage-throbber.gif | diff ../jscoverage-throbber.gif -
+wget -q -O- http://127.0.0.1:8080/jscoverage.js > OUT
+echo -e 'jscoverage_isServer = true;\r' | cat ../jscoverage.js - | diff - OUT
+
+# load/store
+wget --post-data='{}' -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+echo -n '{}' | diff - DIR/jscoverage.json
+diff ../jscoverage.html DIR/jscoverage.html
+diff ../jscoverage.css DIR/jscoverage.css
+diff ../jscoverage-throbber.gif DIR/jscoverage-throbber.gif
+echo -e 'jscoverage_isReport = true;\r' | cat ../jscoverage.js - | diff - DIR/jscoverage.js
+
+# 404 not found
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+echo 404 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-missing 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# 403 forbidden
+echo 403 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/../Makefile.am 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+## send it a proxy request
+#echo 400 > EXPECTED
+#! curl -f -w '%{http_code}\n' -x 127.0.0.1:8080 http://siliconforks.com/ 2> /dev/null > ACTUAL
+#diff EXPECTED ACTUAL
+
+# kill $server_pid
+shutdown
+
+rm -fr DIR
+mkdir DIR
+case `uname` in
+ MINGW*)
+ $VALGRIND jscoverage-server --no-highlight --port=8081 --document-root=recursive --report-dir=DIR --no-instrument=1/ &
+ ;;
+ *)
+ $VALGRIND jscoverage-server --no-highlight --port=8081 --document-root=recursive --report-dir=DIR --no-instrument=/1/ &
+ ;;
+esac
+server_pid=$!
+server_port=8081
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8081/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8081/1/1.js | diff --strip-trailing-cr recursive/1/1.js -
+wget -q -O- http://127.0.0.1:8081/1/2/2.js | diff --strip-trailing-cr recursive/1/2/2.js -
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --no-highlight --port 8082 --document-root recursive --report-dir DIR --no-instrument 1/ &
+server_pid=$!
+server_port=8082
+
+sleep $delay
+
+wget -q -O- http://127.0.0.1:8082/script.js > OUT
+cat ../report.js recursive.expected/script.js | sed 's/@PREFIX@/\//g' | diff --strip-trailing-cr - OUT
+wget -q -O- http://127.0.0.1:8082/1/1.js | diff --strip-trailing-cr recursive/1/1.js -
+wget -q -O- http://127.0.0.1:8082/1/2/2.js | diff --strip-trailing-cr recursive/1/2/2.js -
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --port 8080 --encoding iso-8859-1 --document-root javascript &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ wget -q -O- http://127.0.0.1:8080/javascript-iso-8859-1.js > OUT
+ cat ../report.js javascript.expected/javascript-iso-8859-1.js | sed 's/javascript-iso-8859-1.js/\/javascript-iso-8859-1.js/g' | diff --strip-trailing-cr - OUT
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-iso-8859-1.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --no-highlight --port=8080 --encoding=utf-8 --document-root=javascript-utf-8 &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+case "$character_encoding_support" in
+ yes)
+ wget -q -O- http://127.0.0.1:8080/javascript-utf-8.js > OUT
+ cat ../report.js javascript-utf-8.expected/javascript-utf-8.js | sed 's/javascript-utf-8.js/\/javascript-utf-8.js/g' | diff --strip-trailing-cr - OUT
+ ;;
+ *)
+ echo 500 > EXPECTED
+ ! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-utf-8.js 2> /dev/null > ACTUAL
+ diff EXPECTED ACTUAL
+ ;;
+esac
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --port 8080 --encoding BOGUS --document-root javascript &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 500 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-iso-8859-1.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# kill $server_pid
+shutdown
+
+$VALGRIND jscoverage-server --port 8080 --encoding utf-8 --document-root javascript &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 500 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/javascript-iso-8859-1.js 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err
new file mode 100644
index 0000000..caf61ca
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/source-does-not-exist.expected.err
@@ -0,0 +1,2 @@
+jscoverage: cannot stat file: foo
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err
new file mode 100644
index 0000000..b3fb0b6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/source-is-file.expected.err
@@ -0,0 +1,2 @@
+jscoverage: not a directory: foo
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh
new file mode 100755
index 0000000..5519514
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-json.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# store-bad-json.sh - test store with invalid JSON
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+echo 400 > EXPECTED
+! curl -d '!@#$%^&*()' -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh
new file mode 100755
index 0000000..ef9883e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-request-body.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+# store-bad-request-body.sh - test store with a bad request body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+export PATH=.:..:$PATH
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+./http-client-bad-body 8080 http://127.0.0.1:8080/jscoverage-store
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh
new file mode 100755
index 0000000..28747b5
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-response-headers.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+# store-bad-response-headers.sh - test store with bad response headers
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ kill -9 $origin_server_pid
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+./http-server-bad-headers &
+origin_server_pid=$!
+
+sleep $delay
+
+# server sending malformed headers
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err
new file mode 100644
index 0000000..49fb754
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.err
@@ -0,0 +1,3 @@
+Warning: cannot retrieve URL: 1/1.js
+Warning: cannot retrieve URL: 1/2/2.js
+Warning: cannot retrieve URL: script.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json
new file mode 100644
index 0000000..eb24c47
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-bad-source-urls.expected.json
@@ -0,0 +1,14 @@
+{
+ "script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":[]
+ },
+ "1/1.js":{
+ "coverage":[null,1],
+ "source":[]
+ },
+ "1/2/2.js":{
+ "coverage":[null,1],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json
new file mode 100644
index 0000000..9546103
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.expected.json
@@ -0,0 +1,6 @@
+{
+ "/store-escaped-characters.js":{
+ "coverage":[null,1,0,null,null,1,0,null,null,1,0],
+ "source":["function f() {","\treturn \'\\\'\';","}","&#11;","function g() {","\treturn \"\\\"\";","}","\f","function h() {","\treturn \'\\\\\';","}"]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js
new file mode 100644
index 0000000..dc8ec36
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.js
@@ -0,0 +1,11 @@
+function f() {
+ return '\'';
+}
+
+function g() {
+ return "\"";
+}
+
+function h() {
+ return '\\';
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json
new file mode 100644
index 0000000..59cf4de
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.json
@@ -0,0 +1,3 @@
+{
+ "/store-escaped-characters.js":[null,1,0,null,null,1,0,null,null,1,0]
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh
new file mode 100755
index 0000000..5eb9180
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-escaped-characters.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# store-escaped-characters.sh - test storing escaped characters in JavaScript source
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --report-dir=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget --post-file=store-escaped-characters.json -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+json_cmp store-escaped-characters.expected.json DIR/jscoverage.json
+wget --post-file=store-escaped-characters.json -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store-escaped-characters.expected.json | sed s/1,/2,/g > TMP
+json_cmp TMP DIR/jscoverage.json
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh
new file mode 100755
index 0000000..b6ae810
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-bad-body.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# store-server-bad-body.sh - test storing when server sends bad response body
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+./http-server-bad-body &
+origin_server_pid=$!
+
+sleep $delay
+
+# server sending malformed body
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh
new file mode 100755
index 0000000..a0ef9f9
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-server-closes-immediately.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# store-server-closes-immediately.sh - test storing when server closes immediately
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+./http-server-close-immediately &
+origin_server_pid=$!
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err
new file mode 100644
index 0000000..f00a540
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.err
@@ -0,0 +1 @@
+Warning: cannot open file: /missing.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json
new file mode 100644
index 0000000..3750b51
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.expected.json
@@ -0,0 +1,6 @@
+{
+ "/missing.js":{
+ "coverage":[null,1,0],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json
new file mode 100644
index 0000000..cfad0dd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.json
@@ -0,0 +1,3 @@
+{
+ "/missing.js":[null, 1, 0]
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh
new file mode 100755
index 0000000..aa2a1fa
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-not-found.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+# store-source-not-found.sh - test store with JavaScript source not found
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+wget --post-file=store-source-not-found.json -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+json_cmp store-source-not-found.expected.json DIR/jscoverage.json
+diff --strip-trailing-cr store-source-not-found.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err
new file mode 100644
index 0000000..90a2dd6
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.err
@@ -0,0 +1,3 @@
+Warning: cannot retrieve URL: http://127.0.0.1:8000/1/1.js
+Warning: cannot retrieve URL: http://127.0.0.1:8000/1/2/2.js
+Warning: cannot retrieve URL: http://127.0.0.1:8000/script.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json
new file mode 100644
index 0000000..cb8d058
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-source-urls.expected.json
@@ -0,0 +1,14 @@
+{
+ "http://127.0.0.1:8000/script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":[]
+ },
+ "http://127.0.0.1:8000/1/1.js":{
+ "coverage":[null,1],
+ "source":[]
+ },
+ "http://127.0.0.1:8000/1/2/2.js":{
+ "coverage":[null,1],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err
new file mode 100644
index 0000000..96781cf
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.err
@@ -0,0 +1,3 @@
+Warning: cannot retrieve URL: http://127.0.0.1:1/1/1.js
+Warning: cannot retrieve URL: http://127.0.0.1:1/1/2/2.js
+Warning: cannot retrieve URL: http://127.0.0.1:1/script.js
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json
new file mode 100644
index 0000000..0885998
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreachable-source-urls.expected.json
@@ -0,0 +1,14 @@
+{
+ "http://127.0.0.1:1/script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":[]
+ },
+ "http://127.0.0.1:1/1/1.js":{
+ "coverage":[null,1],
+ "source":[]
+ },
+ "http://127.0.0.1:1/1/2/2.js":{
+ "coverage":[null,1],
+ "source":[]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh
new file mode 100755
index 0000000..026512b
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unreadable-json.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# store-unreadable-json.sh - test store when jscoverage.json is not readable
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+# skip on windows
+uname=`uname`
+case "$uname" in
+ CYGWIN* | MINGW*)
+ exit 77
+ ;;
+esac
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+chmod -r DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+echo 500 > EXPECTED
+! curl -d @TMP -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh
new file mode 100755
index 0000000..786e9bc
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store-unwritable-json.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# store-unwritable-json.sh - test store when jscoverage.json is not writable
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ shutdown
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+chmod -w DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+echo 500 > EXPECTED
+! curl -d @TMP -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json b/tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json
new file mode 100644
index 0000000..2aa393e
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store.expected.json
@@ -0,0 +1,14 @@
+{
+ "@PREFIX@script.js":{
+ "coverage":[null,1,null,null,1,0],
+ "source":["alert(\"hello\");","","// test formatting &amp;lt; &amp;gt; &amp;amp;","if ('a' &lt; 'b' &amp;&amp; 'a' &gt; 'b') {"," alert(\"?\");","}"]
+ },
+ "@PREFIX@1/1.js":{
+ "coverage":[null,1],
+ "source":["alert(\"This is 1\");"]
+ },
+ "@PREFIX@1/2/2.js":{
+ "coverage":[null,1],
+ "source":["alert(\"This is 2\");"]
+ }
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store.json b/tools/node_modules/expresso/deps/jscoverage/tests/store.json
new file mode 100644
index 0000000..942d686
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store.json
@@ -0,0 +1,5 @@
+{
+ "@PREFIX@script.js":[null,1,null,null,1,0],
+ "@PREFIX@1/1.js":[null,1],
+ "@PREFIX@1/2/2.js":[null,1]
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/store.sh b/tools/node_modules/expresso/deps/jscoverage/tests/store.sh
new file mode 100755
index 0000000..fb12574
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/store.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+# store.sh - test storing coverage reports with jscoverage-server
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+. common.sh
+
+shutdown() {
+ wget -q -O- --post-data= "http://127.0.0.1:${server_port}/jscoverage-shutdown" > /dev/null
+ wait $server_pid
+}
+
+cleanup() {
+ # rm -fr DIR
+ # kill $server_pid
+ shutdown
+ if [ "$origin_server_pid" != "" ]
+ then
+ kill -9 $origin_server_pid
+ fi
+}
+
+trap 'cleanup' 0 1 2 3 15
+
+if [ -z "$VALGRIND" ]
+then
+ delay=0.2
+else
+ delay=2
+fi
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --document-root=recursive --report-dir=DIR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" | sed "s/,1/,2/g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+# try invalid method
+echo 405 > EXPECTED
+! curl -f -w '%{http_code}\n' http://127.0.0.1:8080/jscoverage-store 2> /dev/null > ACTUAL
+diff EXPECTED ACTUAL
+
+# try with a path
+cat store.json | sed "s/@PREFIX@/\\//g" > TMP
+wget --post-file=TMP -q -O- http://127.0.0.1:8080/jscoverage-store/DIR > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/\\//g" > TMP
+json_cmp TMP DIR/DIR/jscoverage.json
+
+shutdown
+
+cd recursive
+perl ../server.pl > /dev/null 2> /dev/null &
+origin_server_pid=$!
+cd ..
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# test with proxy
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" | sed "s/,1/,2/g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+# test cached source
+rm -fr DIR
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+cat store.expected.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:8000\\//g" > TMP
+json_cmp TMP DIR/jscoverage.json
+
+shutdown
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# store JSON with bad source URLs
+cat store.json | sed "s/@PREFIX@//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-bad-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-bad-source-urls.expected.err ERR
+
+shutdown
+
+rm -fr DIR
+$VALGRIND jscoverage-server --no-highlight --proxy --report-dir=DIR > OUT 2> ERR &
+server_pid=$!
+server_port=8080
+
+sleep $delay
+
+# store JSON with unreachable source URLs
+cat store.json | sed "s/@PREFIX@/http:\\/\\/127.0.0.1:1\\//g" > TMP
+wget --post-file=TMP -q -O- -e 'http_proxy=http://127.0.0.1:8080/' http://127.0.0.1:8000/jscoverage-store > /dev/null
+json_cmp store-unreachable-source-urls.expected.json DIR/jscoverage.json
+sort ERR -o ERR
+diff --strip-trailing-cr store-unreachable-source-urls.expected.err ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/streams.c b/tools/node_modules/expresso/deps/jscoverage/tests/streams.c
new file mode 100644
index 0000000..06389fb
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/streams.c
@@ -0,0 +1,107 @@
+/*
+ streams.c - test `Stream' object
+ Copyright (C) 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <assert.h>
+#include <string.h>
+
+#include "stream.h"
+#include "util.h"
+
+int main(void) {
+ Stream * stream;
+
+ stream = Stream_new(0);
+ Stream_write_string(stream, "a");
+ Stream_write_string(stream, "bc");
+ assert(stream->length == 3);
+ assert(memcmp(stream->data, "abc", 3) == 0);
+ Stream_delete(stream);
+
+ /* test writing chars to stream */
+ stream = Stream_new(2);
+ Stream_write_char(stream, 'a');
+ Stream_write_char(stream, 'b');
+ Stream_write_char(stream, 'c');
+ assert(stream->length == 3);
+ assert(memcmp(stream->data, "abc", 3) == 0);
+ Stream_reset(stream);
+ Stream_write_char(stream, 'x');
+ Stream_write_char(stream, 'y');
+ assert(stream->length == 2);
+ assert(memcmp(stream->data, "xy", 2) == 0);
+ Stream_delete(stream);
+
+ /* test writing file to stream */
+ stream = Stream_new(0);
+ FILE * f = xfopen("Makefile", "r");
+ fseek(f, 0, SEEK_END);
+ long file_length = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ uint8_t * file_contents = xmalloc(file_length);
+ fread(file_contents, 1, file_length, f);
+ fseek(f, 0, SEEK_SET);
+ Stream_write_file_contents(stream, f);
+ fclose(f);
+ assert(stream->length == (size_t) file_length);
+ assert(memcmp(stream->data, file_contents, file_length) == 0);
+ free(file_contents);
+ Stream_delete(stream);
+
+ stream = Stream_new(0);
+ Stream_printf(stream, "%s %d\n", "abc", 123);
+ assert(stream->length == 8);
+ assert(memcmp(stream->data, "abc 123\n", 8) == 0);
+ Stream_delete(stream);
+
+ stream = Stream_new(10);
+ size_t length = 0;
+ for (int i = 0; i < 100; i++) {
+ Stream_printf(stream, "%s %d\n", "abc", i);
+ if (i < 10) {
+ length += 6;
+ }
+ else {
+ length += 7;
+ }
+ }
+ assert(stream->length == length);
+ length = 0;
+ for (int i = 0; i < 100; i++) {
+ char buffer[8];
+ int result = sprintf(buffer, "%s %d\n", "abc", i);
+ assert(memcmp(stream->data + length, buffer, result) == 0);
+ length += result;
+ }
+ assert(stream->length == length);
+ Stream_delete(stream);
+
+ stream = Stream_new(10);
+ char buffer[100];
+ for (int i = 0; i < 100; i++) {
+ buffer[i] = 'x';
+ }
+ Stream_write(stream, buffer, 100);
+ assert(stream->length == 100);
+ for (int i = 0; i < 100; i++) {
+ assert(stream->data[i] == 'x');
+ }
+ Stream_delete(stream);
+
+ exit(EXIT_SUCCESS);
+}
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/streams.sh b/tools/node_modules/expresso/deps/jscoverage/tests/streams.sh
new file mode 100755
index 0000000..74cfebd
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/streams.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# streams.sh - test `Stream' object
+# Copyright (C) 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+$VALGRIND ./streams
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err b/tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err
new file mode 100644
index 0000000..4ab8b42
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/too-many-arguments.expected.err
@@ -0,0 +1,2 @@
+jscoverage: too many arguments
+Try `jscoverage --help' for more information.
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh b/tools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh
new file mode 100755
index 0000000..c575324
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/valgrind.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+rm -f VALGRIND.*
+export VALGRIND='valgrind --log-file=VALGRIND.%p'
+make check
+grep --color=always 'ERROR SUMMARY:' VALGRIND.*
+grep --color=always 'definitely lost:' VALGRIND.*
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out b/tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out
new file mode 100644
index 0000000..c2c147f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/verbose.expected.out
@@ -0,0 +1,13 @@
+Instrumenting file 1/1.css
+Instrumenting file 1/1.html
+Instrumenting file 1/1.js
+Instrumenting file 1/2/2.css
+Instrumenting file 1/2/2.html
+Instrumenting file 1/2/2.js
+Instrumenting file image.png
+Instrumenting file index.html
+Instrumenting file script.js
+Instrumenting file style.css
+Instrumenting file unix.txt
+Instrumenting file windows.txt
+Instrumenting file x
diff --git a/tools/node_modules/expresso/deps/jscoverage/tests/version.sh b/tools/node_modules/expresso/deps/jscoverage/tests/version.sh
new file mode 100755
index 0000000..da0a26c
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/tests/version.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# version.sh - test `--version' option
+# Copyright (C) 2007, 2008 siliconforks.com
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+set -e
+
+trap 'rm -fr OUT ERR' 1 2 3 15
+
+export PATH=.:..:$PATH
+
+$VALGRIND jscoverage --version > OUT 2> ERR
+test -s OUT
+test ! -s ERR
+
+rm -fr OUT ERR
diff --git a/tools/node_modules/expresso/deps/jscoverage/util.c b/tools/node_modules/expresso/deps/jscoverage/util.c
new file mode 100644
index 0000000..40636ff
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/util.c
@@ -0,0 +1,570 @@
+/*
+ util.c - general purpose utility routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define _GNU_SOURCE
+
+#include <config.h>
+
+#include "util.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <strings.h>
+
+#include <dirent.h>
+#include <libgen.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+const char * program = NULL;
+
+void fatal(const char * format, ...) {
+ fprintf(stderr, "%s: ", program);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ exit(EXIT_FAILURE);
+}
+
+void fatal_command_line(const char * format, ...) {
+ fprintf(stderr, "%s: ", program);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ fprintf(stderr, "Try `%s --help' for more information.\n", program);
+ exit(EXIT_FAILURE);
+}
+
+void fatal_source(const char * source_file, unsigned int line_number, const char * format, ...) {
+ fprintf(stderr, "%s:%s:%u: ", program, source_file, line_number);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+ exit(EXIT_FAILURE);
+}
+
+void warn_source(const char * source_file, unsigned int line_number, const char * format, ...) {
+ fprintf(stderr, "%s:%s:%u: ", program, source_file, line_number);
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputc('\n', stderr);
+}
+
+void version(void) {
+ printf("%s %s\n", program, VERSION);
+ printf("Character encoding support: ");
+#if HAVE_ICONV
+ printf("iconv\n");
+#elif HAVE_MULTIBYTETOWIDECHAR
+ printf("MultiByteToWideChar\n");
+#else
+ printf("none\n");
+#endif
+ exit(EXIT_SUCCESS);
+}
+
+size_t addst(size_t x, size_t y) {
+ if (SIZE_MAX - x < y) {
+ fatal("integer overflow");
+ }
+ return x + y;
+}
+
+size_t mulst(size_t x, size_t y) {
+ if (x == 0 || y == 0) {
+ return 0;
+ }
+ if (SIZE_MAX / x < y) {
+ fatal("integer overflow");
+ }
+ return x * y;
+}
+
+void * xmalloc(size_t size) {
+ void * result = malloc(size);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+void * xrealloc(void * p, size_t size) {
+ void * result = realloc(p, size);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+char * xstrdup(const char * s) {
+ char * result = strdup(s);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+char * xstrndup(const char * s, size_t size) {
+ char * result = strndup(s, size);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+int xasprintf(char ** s, const char * template, ...) {
+ va_list a;
+ va_start(a, template);
+ int result = vasprintf(s, template, a);
+ va_end(a);
+ if (result < 0) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+char * xgetcwd(void) {
+ char * result = getcwd(NULL, 0);
+ if (result == NULL) {
+ fatal("out of memory");
+ }
+ return result;
+}
+
+FILE * xfopen(const char * file, const char * mode) {
+ FILE * result = fopen(file, mode);
+ if (result == NULL) {
+ fatal("cannot open file: %s", file);
+ }
+ return result;
+}
+
+DIR * xopendir(const char * directory) {
+ DIR * result = opendir(directory);
+ if (result == NULL) {
+ fatal("cannot open directory: %s", directory);
+ }
+ return result;
+}
+
+void xlstat(const char * file, struct stat * buf) {
+#ifdef _WIN32
+ return xstat(file, buf);
+#else
+ if (lstat(file, buf) == -1) {
+ fatal("cannot stat file: %s", file);
+ }
+#endif
+}
+
+void xstat(const char * file, struct stat * buf) {
+ if (stat(file, buf) == -1) {
+ fatal("cannot stat file: %s", file);
+ }
+}
+
+void xmkdir(const char * directory) {
+ int result;
+#ifdef _WIN32
+ result = mkdir(directory);
+#else
+ result = mkdir(directory, 0755);
+#endif
+ if (result == -1) {
+ fatal("cannot create directory: %s", directory);
+ }
+}
+
+void mkdir_if_necessary(const char * directory) {
+ struct stat buf;
+ if (stat(directory, &buf) == 0) {
+ if (! S_ISDIR(buf.st_mode)) {
+ fatal("not a directory: %s", directory);
+ }
+ }
+ else {
+ if (errno == ENOENT) {
+ xmkdir(directory);
+ }
+ else {
+ fatal("cannot stat directory: %s", directory);
+ }
+ }
+}
+
+void mkdirs(const char * directory) {
+ char * d = xmalloc(strlen(directory) + 1);
+ for (const char * p = directory; *p != '\0'; p++) {
+ if (*p == '/' && p > directory) {
+ strncpy(d, directory, p - directory);
+ d[p - directory] = '\0';
+ mkdir_if_necessary(d);
+ }
+ }
+ mkdir_if_necessary(directory);
+ free(d);
+}
+
+void xchdir(const char * directory) {
+ if (chdir(directory) == -1) {
+ fatal("cannot change directory: %s", directory);
+ }
+}
+
+bool str_starts_with(const char * string, const char * prefix) {
+ const char * string_ptr = string;
+ const char * prefix_ptr = prefix;
+ while (*string_ptr != '\0' && *prefix_ptr != '\0') {
+ if (*string_ptr != *prefix_ptr) {
+ return false;
+ }
+ string_ptr++;
+ prefix_ptr++;
+ }
+ if (*string_ptr == '\0' && *prefix_ptr != '\0') {
+ return false;
+ }
+ return true;
+}
+
+bool str_ends_with(const char * string, const char * suffix) {
+ size_t string_length = strlen(string);
+ size_t suffix_length = strlen(suffix);
+ if (string_length < suffix_length) {
+ return false;
+ }
+ return strcmp(string + string_length - suffix_length, suffix) == 0;
+}
+
+char * make_path(const char * parent, const char * relative_path) {
+ size_t parent_length = strlen(parent);
+ size_t relative_path_length = strlen(relative_path);
+ size_t result_length = addst(parent_length, relative_path_length);
+ result_length = addst(result_length, 2);
+ char * result = xmalloc(result_length);
+ strcpy(result, parent);
+ result[parent_length] = '/';
+ strcpy(result + parent_length + 1, relative_path);
+ return result;
+}
+
+char * make_canonical_path(const char * relative_path) {
+ char * original_directory = xgetcwd();
+ char * base = make_basename(relative_path);
+ char * dir = make_dirname(relative_path);
+
+ xchdir(dir);
+ char * canonical_dir = xgetcwd();
+ char * result = make_path(canonical_dir, base);
+
+ free(canonical_dir);
+ free(base);
+ free(dir);
+ xchdir(original_directory);
+ free(original_directory);
+
+ return result;
+}
+
+char * make_basename(const char * path) {
+ char * copy = xstrdup(path);
+ char * result = xstrdup(basename(copy));
+ free(copy);
+ return result;
+}
+
+char * make_dirname(const char * path) {
+ char * copy = xstrdup(path);
+ char * result = xstrdup(dirname(copy));
+ free(copy);
+ return result;
+}
+
+int is_same_file(const char * file1, const char * file2) {
+#ifdef _WIN32
+#define FILECMP strcasecmp
+#else
+#define FILECMP strcmp
+#endif
+ if (FILECMP(file1, file2) == 0) {
+ return 1;
+ }
+
+ char * canonical1 = make_canonical_path(file1);
+ char * canonical2 = make_canonical_path(file2);
+ int cmp = FILECMP(canonical1, canonical2);
+ free(canonical1);
+ free(canonical2);
+ if (cmp == 0) {
+ return 1;
+ }
+
+#ifndef _WIN32
+ struct stat buf1;
+ if (stat(file1, &buf1) == -1) {
+ if (errno == ENOENT) {
+ return 0;
+ }
+ else {
+ fatal("cannot stat file: %s", file1);
+ }
+ }
+ struct stat buf2;
+ if (stat(file2, &buf2) == -1) {
+ if (errno == ENOENT) {
+ return 0;
+ }
+ else {
+ fatal("cannot stat file: %s", file2);
+ }
+ }
+ if (buf1.st_dev == buf2.st_dev &&
+ buf1.st_ino == buf2.st_ino) {
+ return 1;
+ }
+#endif
+ return 0;
+#undef FILECMP
+}
+
+int contains_file(const char * file1, const char * file2) {
+ int result = 0;
+ char * ancestor = make_canonical_path(file1);
+ char * d = make_canonical_path(file2);
+ char * parent = make_dirname(d);
+ while (strcmp(d, parent) != 0) {
+ if (is_same_file(ancestor, parent)) {
+ result = 1;
+ break;
+ }
+ free(d);
+ d = parent;
+ parent = make_dirname(d);
+ }
+ free(d);
+ free(parent);
+ free(ancestor);
+ return result;
+}
+
+void copy_stream(FILE * source, FILE * destination) {
+ unsigned char buffer[8192];
+ for (;;) {
+ int bytes_read = fread(buffer, 1, sizeof(buffer), source);
+ if (bytes_read == 0) {
+ break;
+ }
+ fwrite(buffer, 1, bytes_read, destination);
+ }
+}
+
+void copy_file(const char * source_file, const char * destination_file) {
+ FILE * source = xfopen(source_file, "rb");
+ FILE * destination = xfopen(destination_file, "wb");
+
+ copy_stream(source, destination);
+
+#ifndef _WIN32
+ /* copy permissions */
+ struct stat buf;
+ if (fstat(fileno(source), &buf) == -1) {
+ fatal("cannot stat file: %s", source_file);
+ }
+ fchmod(fileno(destination), buf.st_mode);
+#endif
+
+ fclose(source);
+ fclose(destination);
+}
+
+bool directory_is_empty(const char * directory) {
+ bool result = true;
+ DIR * dir = xopendir(directory);
+ struct dirent * e;
+ while ((e = readdir(dir)) != NULL) {
+ if (strcmp(e->d_name, ".") != 0 &&
+ strcmp(e->d_name, "..") != 0) {
+ result = false;
+ break;
+ }
+ }
+ closedir(dir);
+ return result;
+}
+
+static struct DirListEntry * recursive_dir_list(const char * root, const char * directory_wrt_root, struct DirListEntry * head) {
+ char * directory = directory_wrt_root == NULL? xstrdup(root): make_path(root, directory_wrt_root);
+ DIR * dir = xopendir(directory);
+ struct dirent * e;
+ while ((e = readdir(dir)) != NULL) {
+ if (strcmp(e->d_name, ".") == 0 ||
+ strcmp(e->d_name, "..") == 0) {
+ continue;
+ }
+ char * entry = make_path(directory, e->d_name);
+ char * entry_wrt_root = directory_wrt_root == NULL? xstrdup(e->d_name): make_path(directory_wrt_root, e->d_name);
+ struct stat buf;
+ xlstat(entry, &buf);
+ if (S_ISREG(buf.st_mode)) {
+ struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
+ p->name = entry_wrt_root;
+ p->next = head;
+ head = p;
+ }
+ else if (S_ISDIR(buf.st_mode)) {
+ head = recursive_dir_list(root, entry_wrt_root, head);
+ free(entry_wrt_root);
+ }
+#ifndef _WIN32
+ else if (S_ISLNK(buf.st_mode)) {
+ /* check what it points to */
+ xstat(entry, &buf);
+ if (S_ISREG(buf.st_mode)) {
+ struct DirListEntry * p = xmalloc(sizeof(struct DirListEntry));
+ p->name = entry_wrt_root;
+ p->next = head;
+ head = p;
+ }
+ else {
+ fatal("refusing to follow symbolic link: %s", entry);
+ }
+ }
+#endif
+ else {
+ fatal("unknown file type: %s", entry);
+ }
+ free(entry);
+ }
+ closedir(dir);
+ free(directory);
+ return head;
+}
+
+struct DirListEntry * make_recursive_dir_list(const char * directory) {
+ return recursive_dir_list(directory, NULL, NULL);
+}
+
+void free_dir_list(struct DirListEntry * list) {
+ while (list != NULL) {
+ struct DirListEntry * next = list->next;
+ free(list->name);
+ free(list);
+ list = next;
+ }
+}
+
+#ifndef HAVE_STRNDUP
+char * strndup(const char * s, size_t size) {
+ size_t length = strlen(s);
+ if (length > size) {
+ char * result = xmalloc(size + 1);
+ strncpy(result, s, size);
+ result[size] = '\0';
+ return result;
+ }
+ else {
+ char * result = xmalloc(length + 1);
+ strcpy(result, s);
+ return result;
+ }
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int vasprintf(char ** s, const char * template, va_list a) {
+ int size = 100;
+ *s = malloc(size);
+ if (*s == NULL) {
+ return -1;
+ }
+
+ va_list copy;
+ va_copy(copy, a);
+ int result = vsnprintf(*s, size, template, copy);
+ if (result >= size) {
+ int new_size = result;
+ if (new_size == INT_MAX) {
+ free(*s);
+ return -1;
+ }
+ new_size++;
+ char * new_s = realloc(*s, new_size);
+ if (new_s == NULL) {
+ free(*s);
+ return -1;
+ }
+ *s = new_s;
+ size = new_size;
+ va_copy(copy, a);
+ result = vsnprintf(*s, size, template, copy);
+ assert(result == size - 1);
+ }
+ else if (result == -1) {
+ while (result == -1) {
+ if (size == INT_MAX) {
+ free(*s);
+ return -1;
+ }
+ int new_size;
+ if (size > INT_MAX / 2) {
+ new_size = INT_MAX;
+ }
+ else {
+ new_size = 2 * size;
+ }
+ char * new_s = realloc(*s, new_size);
+ if (new_s == NULL) {
+ free(*s);
+ return -1;
+ }
+ *s = new_s;
+ size = new_size;
+ va_copy(copy, a);
+ result = vsnprintf(*s, size, template, copy);
+ }
+ assert(result <= size - 1);
+ }
+
+ return result;
+}
+#endif
+
+#ifndef HAVE_ASPRINTF
+int asprintf(char ** s, const char * template, ...) {
+ va_list a;
+ va_start(a, template);
+ int result = vasprintf(s, template, a);
+ va_end(a);
+ return result;
+}
+#endif
diff --git a/tools/node_modules/expresso/deps/jscoverage/util.h b/tools/node_modules/expresso/deps/jscoverage/util.h
new file mode 100644
index 0000000..5cd063f
--- /dev/null
+++ b/tools/node_modules/expresso/deps/jscoverage/util.h
@@ -0,0 +1,133 @@
+/*
+ util.h - general purpose utility routines
+ Copyright (C) 2007, 2008 siliconforks.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef UTIL_H_
+#define UTIL_H_
+
+#ifndef HAVE_VASPRINTF
+#include <stdarg.h>
+#endif
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/stat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char * program;
+
+void fatal(const char * format, ...)
+ __attribute__((__noreturn__))
+ __attribute__((__format__(printf, 1, 2)));
+
+void fatal_command_line(const char * format, ...)
+ __attribute__((__noreturn__))
+ __attribute__((__format__(printf, 1, 2)));
+
+void fatal_source(const char * source_file, unsigned int line_number, const char * format, ...)
+ __attribute__((__noreturn__))
+ __attribute__((__format__(printf, 3, 4)));
+
+void warn_source(const char * source_file, unsigned int line_number, const char * format, ...)
+ __attribute__((__format__(printf, 3, 4)));
+
+void version(void)
+ __attribute__((__noreturn__));
+
+size_t addst(size_t x, size_t y);
+
+size_t mulst(size_t x, size_t y);
+
+void * xmalloc(size_t size);
+
+#define xnew(type, count) ((type *) xmalloc(mulst((count), sizeof(type))))
+
+void * xrealloc(void * p, size_t size);
+
+char * xstrdup(const char * s);
+
+char * xstrndup(const char * s, size_t size);
+
+int xasprintf(char ** s, const char * format, ...) __attribute__((__format__(printf, 2, 3)));
+
+char * xgetcwd(void);
+
+FILE * xfopen(const char * file, const char * mode);
+
+void xstat(const char * file, struct stat * buf);
+
+void xlstat(const char * file, struct stat * buf);
+
+void xmkdir(const char * directory);
+
+void mkdir_if_necessary(const char * directory);
+
+void mkdirs(const char * path);
+
+bool str_starts_with(const char * string, const char * prefix);
+
+bool str_ends_with(const char * string, const char * suffix);
+
+char * make_path(const char * parent, const char * relative_path);
+
+char * make_canonical_path(const char * relative_path);
+
+char * make_basename(const char * path);
+
+char * make_dirname(const char * path);
+
+int is_same_file(const char * file1, const char * file2);
+
+int contains_file(const char * file1, const char * file2);
+
+void copy_stream(FILE * source, FILE * destination);
+
+void copy_file(const char * source_file, const char * destination_file);
+
+bool directory_is_empty(const char * directory);
+
+struct DirListEntry {
+ char * name;
+ struct DirListEntry * next;
+};
+
+struct DirListEntry * make_recursive_dir_list(const char * directory);
+
+void free_dir_list(struct DirListEntry * list);
+
+#ifndef HAVE_STRNDUP
+char * strndup(const char * s, size_t size);
+#endif
+
+#ifndef HAVE_VASPRINTF
+int vasprintf(char ** s, const char * format, va_list a);
+#endif
+
+#ifndef HAVE_ASPRINTF
+int asprintf(char ** s, const char * format, ...) __attribute__((__format__(printf, 2, 3)));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTIL_H_ */